aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/netfilter
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-10-24 16:14:04 -0700
committerDavid S. Miller <davem@davemloft.net>2006-10-24 16:14:04 -0700
commit51d8b1a65291a6956b79374b6adbbadc2263bcf6 (patch)
treed6b8cbd6628c11d1c3e9c8c8e9ca048acf723a71 /net/ipv6/netfilter
parent[XFRM]: Fix xfrm_state accounting (diff)
downloadlinux-dev-51d8b1a65291a6956b79374b6adbbadc2263bcf6.tar.xz
linux-dev-51d8b1a65291a6956b79374b6adbbadc2263bcf6.zip
[NETFILTER]: Fix ip6_tables protocol bypass bug
As reported by Mark Dowd <Mark_Dowd@McAfee.com>, ip6_tables is susceptible to a fragmentation attack causing false negatives on protocol matches. When the protocol header doesn't follow the fragment header immediately, the fragment header contains the protocol number of the next extension header. When the extension header and the protocol header are sent in a second fragment a rule like "ip6tables .. -p udp -j DROP" will never match. Drop fragments that are at offset 0 and don't contain the final protocol header regardless of the ruleset, since this should not happen normally. With help from Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/netfilter')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368fa0b8f..f0328c7bc1c9 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -111,7 +111,7 @@ ip6_packet_match(const struct sk_buff *skb,
const char *outdev,
const struct ip6t_ip6 *ip6info,
unsigned int *protoff,
- int *fragoff)
+ int *fragoff, int *hotdrop)
{
size_t i;
unsigned long ret;
@@ -169,9 +169,11 @@ ip6_packet_match(const struct sk_buff *skb,
unsigned short _frag_off;
protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
- if (protohdr < 0)
+ if (protohdr < 0) {
+ if (_frag_off == 0)
+ *hotdrop = 1;
return 0;
-
+ }
*fragoff = _frag_off;
dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -290,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb,
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
- &protoff, &offset)) {
+ &protoff, &offset, &hotdrop)) {
struct ip6t_entry_target *t;
if (IP6T_MATCH_ITERATE(e, do_match,