diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-10-10 17:30:46 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-10-10 17:30:46 -0700 |
commit | 227b60f5102cda4e4ab792b526a59c8cb20cd9f8 (patch) | |
tree | 2c9e372601ba794894833b0618bc531a9f5d57c4 /net/ipv6/inet6_hashtables.c | |
parent | 06393009000779b00a558fd2f280882cc7dc2008 (diff) | |
download | op-kernel-dev-227b60f5102cda4e4ab792b526a59c8cb20cd9f8.zip op-kernel-dev-227b60f5102cda4e4ab792b526a59c8cb20cd9f8.tar.gz |
[INET]: local port range robustness
Expansion of original idea from Denis V. Lunev <den@openvz.org>
Add robustness and locking to the local_port_range sysctl.
1. Enforce that low < high when setting.
2. Use seqlock to ensure atomic update.
The locking might seem like overkill, but there are
cases where sysadmin might want to change value in the
middle of a DoS attack.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/inet6_hashtables.c')
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index ae6b0e7..1c2c276 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -254,18 +254,18 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, int ret; if (snum == 0) { - const int low = sysctl_local_port_range[0]; - const int high = sysctl_local_port_range[1]; - const int range = high - low; - int i, port; + int i, port, low, high, remaining; static u32 hint; const u32 offset = hint + inet6_sk_port_offset(sk); struct hlist_node *node; struct inet_timewait_sock *tw = NULL; + inet_get_local_port_range(&low, &high); + remaining = high - low; + local_bh_disable(); - for (i = 1; i <= range; i++) { - port = low + (i + offset) % range; + for (i = 1; i <= remaining; i++) { + port = low + (i + offset) % remaining; head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; spin_lock(&head->lock); |