diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-10-20 11:51:57 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-01-06 11:53:47 -0500 |
commit | c9233eb7b0b11ef176d4bf68da2ce85464b6ec39 (patch) | |
tree | 22f9f999e0d48a5f3aae6b32f9ff702eb4db05cc /net | |
parent | 548eaca46b3cf4419b6c2be839a106d8641ffb70 (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')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 22 |
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 | */ |
529 | static void svc_check_conn_limits(struct svc_serv *serv) | 535 | static 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, |