diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-03-20 10:40:06 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-03-20 10:40:06 -0400 |
commit | db856674ac69e31946e56085239757cca3f7655f (patch) | |
tree | 73fc82e92a119dcf1a0ce4e2ca45ef410165776f /net/ipv6 | |
parent | 5c1aba467828bf0574ec5754c84884d573f590af (diff) |
netfilter: xtables: fix reentrancy
commit f3c5c1bfd4308 (make ip_tables reentrant) introduced a race in
handling the stackptr restore, at the end of ipt_do_table()
We should do it before the call to xt_info_rdunlock_bh(), or we allow
cpu preemption and another cpu overwrites stackptr of original one.
A second fix is to change the underflow test to check the origptr value
instead of 0 to detect underflow, or else we allow a jump from different
hooks.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index c9598a9067d7..0b2af9b85cec 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
410 | verdict = (unsigned)(-v) - 1; | 410 | verdict = (unsigned)(-v) - 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
413 | if (*stackptr == 0) | 413 | if (*stackptr <= origptr) |
414 | e = get_entry(table_base, | 414 | e = get_entry(table_base, |
415 | private->underflow[hook]); | 415 | private->underflow[hook]); |
416 | else | 416 | else |
@@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
441 | break; | 441 | break; |
442 | } while (!acpar.hotdrop); | 442 | } while (!acpar.hotdrop); |
443 | 443 | ||
444 | xt_info_rdunlock_bh(); | ||
445 | *stackptr = origptr; | 444 | *stackptr = origptr; |
445 | xt_info_rdunlock_bh(); | ||
446 | 446 | ||
447 | #ifdef DEBUG_ALLOW_ALL | 447 | #ifdef DEBUG_ALLOW_ALL |
448 | return NF_ACCEPT; | 448 | return NF_ACCEPT; |