diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-10-10 20:30:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-10-10 20:30:46 -0400 |
commit | 227b60f5102cda4e4ab792b526a59c8cb20cd9f8 (patch) | |
tree | 2c9e372601ba794894833b0618bc531a9f5d57c4 /net/ipv4/inet_hashtables.c | |
parent | 06393009000779b00a558fd2f280882cc7dc2008 (diff) |
[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/ipv4/inet_hashtables.c')
-rw-r--r-- | net/ipv4/inet_hashtables.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index fb662621c54e..fac6398e4367 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -279,19 +279,18 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row, | |||
279 | int ret; | 279 | int ret; |
280 | 280 | ||
281 | if (!snum) { | 281 | if (!snum) { |
282 | int low = sysctl_local_port_range[0]; | 282 | int i, remaining, low, high, port; |
283 | int high = sysctl_local_port_range[1]; | ||
284 | int range = high - low; | ||
285 | int i; | ||
286 | int port; | ||
287 | static u32 hint; | 283 | static u32 hint; |
288 | u32 offset = hint + inet_sk_port_offset(sk); | 284 | u32 offset = hint + inet_sk_port_offset(sk); |
289 | struct hlist_node *node; | 285 | struct hlist_node *node; |
290 | struct inet_timewait_sock *tw = NULL; | 286 | struct inet_timewait_sock *tw = NULL; |
291 | 287 | ||
288 | inet_get_local_port_range(&low, &high); | ||
289 | remaining = high - low; | ||
290 | |||
292 | local_bh_disable(); | 291 | local_bh_disable(); |
293 | for (i = 1; i <= range; i++) { | 292 | for (i = 1; i <= remaining; i++) { |
294 | port = low + (i + offset) % range; | 293 | port = low + (i + offset) % remaining; |
295 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; | 294 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; |
296 | spin_lock(&head->lock); | 295 | spin_lock(&head->lock); |
297 | 296 | ||