diff options
author | Florian Westphal <fwestphal@astaro.com> | 2010-02-15 12:17:10 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-02-15 12:17:10 -0500 |
commit | 3e5e524ffb5fcf2447eb5dd9f8e54ad22dd9baa7 (patch) | |
tree | a78b8d92a63dd217e114a02e1ff0902e5e23cc41 | |
parent | fc0e3df4f00a5f62c2f2fce84bf496136b58c474 (diff) |
netfilter: CONFIG_COMPAT: allow delta to exceed 32767
with 32 bit userland and 64 bit kernels, it is unlikely but possible
that insertion of new rules fails even tough there are only about 2000
iptables rules.
This happens because the compat delta is using a short int.
Easily reproducible via "iptables -m limit" ; after about 2050
rules inserting new ones fails with -ELOOP.
Note that compat_delta included 2 bytes of padding on x86_64, so
structure size remains the same.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter/x_tables.h | 2 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 6 |
2 files changed, 4 insertions, 4 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index c61758f4be31..a18119fb88f0 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
@@ -588,7 +588,7 @@ extern void xt_compat_unlock(u_int8_t af); | |||
588 | 588 | ||
589 | extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta); | 589 | extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta); |
590 | extern void xt_compat_flush_offsets(u_int8_t af); | 590 | extern void xt_compat_flush_offsets(u_int8_t af); |
591 | extern short xt_compat_calc_jump(u_int8_t af, unsigned int offset); | 591 | extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset); |
592 | 592 | ||
593 | extern int xt_compat_match_offset(const struct xt_match *match); | 593 | extern int xt_compat_match_offset(const struct xt_match *match); |
594 | extern int xt_compat_match_from_user(struct xt_entry_match *m, | 594 | extern int xt_compat_match_from_user(struct xt_entry_match *m, |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 69c56287d518..0a12cedfe9e3 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -39,7 +39,7 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module"); | |||
39 | struct compat_delta { | 39 | struct compat_delta { |
40 | struct compat_delta *next; | 40 | struct compat_delta *next; |
41 | unsigned int offset; | 41 | unsigned int offset; |
42 | short delta; | 42 | int delta; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct xt_af { | 45 | struct xt_af { |
@@ -439,10 +439,10 @@ void xt_compat_flush_offsets(u_int8_t af) | |||
439 | } | 439 | } |
440 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); | 440 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); |
441 | 441 | ||
442 | short xt_compat_calc_jump(u_int8_t af, unsigned int offset) | 442 | int xt_compat_calc_jump(u_int8_t af, unsigned int offset) |
443 | { | 443 | { |
444 | struct compat_delta *tmp; | 444 | struct compat_delta *tmp; |
445 | short delta; | 445 | int delta; |
446 | 446 | ||
447 | for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next) | 447 | for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next) |
448 | if (tmp->offset < offset) | 448 | if (tmp->offset < offset) |