aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc_xprt.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-10-20 11:51:57 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-01-06 11:53:47 -0500
commitc9233eb7b0b11ef176d4bf68da2ce85464b6ec39 (patch)
tree22f9f999e0d48a5f3aae6b32f9ff702eb4db05cc /net/sunrpc/svc_xprt.c
parent548eaca46b3cf4419b6c2be839a106d8641ffb70 (diff)
sunrpc: add sv_maxconn field to svc_serv (try #3)
svc_check_conn_limits() attempts to prevent denial of service attacks by having the service close old connections once it reaches a threshold. This threshold is based on the number of threads in the service: (serv->sv_nrthreads + 3) * 20 Once we reach this, we drop the oldest connections and a printk pops to warn the admin that they should increase the number of threads. Increasing the number of threads isn't an option however for services like lockd. We don't want to eliminate this check entirely for such services but we need some way to increase this limit. This patch adds a sv_maxconn field to the svc_serv struct. When it's set to 0, we use the current method to calculate the max number of connections. RPC services can then set this on an as-needed basis. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Neil Brown <neilb@suse.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r--net/sunrpc/svc_xprt.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index bf5b5cdafebf..3fe4f1004278 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -515,8 +515,10 @@ int svc_port_is_privileged(struct sockaddr *sin)
515} 515}
516 516
517/* 517/*
518 * Make sure that we don't have too many active connections. If we 518 * Make sure that we don't have too many active connections. If we have,
519 * have, something must be dropped. 519 * something must be dropped. It's not clear what will happen if we allow
520 * "too many" connections, but when dealing with network-facing software,
521 * we have to code defensively. Here we do that by imposing hard limits.
520 * 522 *
521 * There's no point in trying to do random drop here for DoS 523 * There's no point in trying to do random drop here for DoS
522 * prevention. The NFS clients does 1 reconnect in 15 seconds. An 524 * prevention. The NFS clients does 1 reconnect in 15 seconds. An
@@ -525,19 +527,27 @@ int svc_port_is_privileged(struct sockaddr *sin)
525 * The only somewhat efficient mechanism would be if drop old 527 * The only somewhat efficient mechanism would be if drop old
526 * connections from the same IP first. But right now we don't even 528 * connections from the same IP first. But right now we don't even
527 * record the client IP in svc_sock. 529 * record the client IP in svc_sock.
530 *
531 * single-threaded services that expect a lot of clients will probably
532 * need to set sv_maxconn to override the default value which is based
533 * on the number of threads
528 */ 534 */
529static void svc_check_conn_limits(struct svc_serv *serv) 535static void svc_check_conn_limits(struct svc_serv *serv)
530{ 536{
531 if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) { 537 unsigned int limit = serv->sv_maxconn ? serv->sv_maxconn :
538 (serv->sv_nrthreads+3) * 20;
539
540 if (serv->sv_tmpcnt > limit) {
532 struct svc_xprt *xprt = NULL; 541 struct svc_xprt *xprt = NULL;
533 spin_lock_bh(&serv->sv_lock); 542 spin_lock_bh(&serv->sv_lock);
534 if (!list_empty(&serv->sv_tempsocks)) { 543 if (!list_empty(&serv->sv_tempsocks)) {
535 if (net_ratelimit()) { 544 if (net_ratelimit()) {
536 /* Try to help the admin */ 545 /* Try to help the admin */
537 printk(KERN_NOTICE "%s: too many open " 546 printk(KERN_NOTICE "%s: too many open "
538 "connections, consider increasing the " 547 "connections, consider increasing %s\n",
539 "number of nfsd threads\n", 548 serv->sv_name, serv->sv_maxconn ?
540 serv->sv_name); 549 "the max number of connections." :
550 "the number of threads.");
541 } 551 }
542 /* 552 /*
543 * Always select the oldest connection. It's not fair, 553 * Always select the oldest connection. It's not fair,