[kernel] r8024 - in dists/sid/linux-2.6/debian: . patches/bugfix
patches/series
Dann Frazier
dannf at alioth.debian.org
Mon Dec 18 00:26:17 UTC 2006
Author: dannf
Date: Mon Dec 18 01:26:17 2006
New Revision: 8024
Added:
dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-extension-header-bypass-bug.patch
dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-protocol-bypass-bug.patch
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/patches/series/9
Log:
* Fix potential fragmentation attacks in ip6_tables (CVE-2006-4572)
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog (original)
+++ dists/sid/linux-2.6/debian/changelog Mon Dec 18 01:26:17 2006
@@ -11,8 +11,9 @@
[ dann frazier ]
* Fix data corruption with dm-crypt over RAID5 (closes: #402812)
+ * Fix potential fragmentation attacks in ip6_tables (CVE-2006-4572)
- -- dann frazier <dannf at debian.org> Tue, 12 Dec 2006 13:38:26 -0700
+ -- dann frazier <dannf at debian.org> Sun, 17 Dec 2006 17:18:20 -0700
linux-2.6 (2.6.18-8) unstable; urgency=low
Added: dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-extension-header-bypass-bug.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-extension-header-bypass-bug.patch Mon Dec 18 01:26:17 2006
@@ -0,0 +1,157 @@
+From: Patrick McHardy <kaber at trash.net>
+Date: Tue, 24 Oct 2006 23:15:10 +0000 (-0700)
+Subject: [NETFILTER]: Fix ip6_tables extension header bypass bug
+X-Git-Tag: v2.6.19-rc4
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=6d381634d213580d40d431e7664dfb45f641b884
+
+[NETFILTER]: Fix ip6_tables extension header bypass bug
+
+As reported by Mark Dowd <Mark_Dowd at McAfee.com>, ip6_tables is susceptible
+to a fragmentation attack causing false negatives on extension header matches.
+
+When extension headers occur in the non-first fragment after the fragment
+header (possibly with an incorrect nexthdr value in the fragment header)
+a rule looking for this extension header 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.
+Since all extension headers are before the protocol header this makes sure
+an extension header is either not present or in the first fragment, where
+we can properly parse it.
+
+With help from Yasuyuki KOZAKAI <yasuyuki.kozakai at toshiba.co.jp>.
+
+Signed-off-by: Patrick McHardy <kaber at trash.net>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+Backported to Debian's 2.6.18 by dann frazier <dannf at debian.org>
+
+---
+diff -urN linux-source-2.6.18.orig/net/ipv6/netfilter/ip6_tables.c linux-source-2.6.18/net/ipv6/netfilter/ip6_tables.c
+--- linux-source-2.6.18.orig/net/ipv6/netfilter/ip6_tables.c 2006-12-17 17:04:11.676261000 -0700
++++ linux-source-2.6.18/net/ipv6/netfilter/ip6_tables.c 2006-12-17 17:04:47.298488000 -0700
+@@ -1447,6 +1447,9 @@
+ * If target header is found, its offset is set in *offset and return protocol
+ * number. Otherwise, return -1.
+ *
++ * If the first fragment doesn't contain the final protocol header or
++ * NEXTHDR_NONE it is considered invalid.
++ *
+ * Note that non-1st fragment is special case that "the protocol number
+ * of last header" is "next header" field in Fragment header. In this case,
+ * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
+@@ -1470,12 +1473,12 @@
+ if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
+ if (target < 0)
+ break;
+- return -1;
++ return -ENOENT;
+ }
+
+ hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+- return -1;
++ return -EBADMSG;
+ if (nexthdr == NEXTHDR_FRAGMENT) {
+ unsigned short _frag_off, *fp;
+ fp = skb_header_pointer(skb,
+@@ -1484,7 +1487,7 @@
+ sizeof(_frag_off),
+ &_frag_off);
+ if (fp == NULL)
+- return -1;
++ return -EBADMSG;
+
+ _frag_off = ntohs(*fp) & ~0x7;
+ if (_frag_off) {
+@@ -1495,7 +1498,7 @@
+ *fragoff = _frag_off;
+ return hp->nexthdr;
+ }
+- return -1;
++ return -ENOENT;
+ }
+ hdrlen = 8;
+ } else if (nexthdr == NEXTHDR_AUTH)
+diff -urN linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_ah.c linux-source-2.6.18/net/ipv6/netfilter/ip6t_ah.c
+--- linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_ah.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv6/netfilter/ip6t_ah.c 2006-12-17 17:04:47.302488250 -0700
+@@ -54,9 +54,14 @@
+ const struct ip6t_ah *ahinfo = matchinfo;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
++ int err;
+
+- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0)
++ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
++ if (err < 0) {
++ if (err != -ENOENT)
++ *hotdrop = 1;
+ return 0;
++ }
+
+ ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
+ if (ah == NULL) {
+diff -urN linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_frag.c linux-source-2.6.18/net/ipv6/netfilter/ip6t_frag.c
+--- linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_frag.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv6/netfilter/ip6t_frag.c 2006-12-17 17:04:47.302488250 -0700
+@@ -52,9 +52,14 @@
+ struct frag_hdr _frag, *fh;
+ const struct ip6t_frag *fraginfo = matchinfo;
+ unsigned int ptr;
++ int err;
+
+- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0)
++ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
++ if (err < 0) {
++ if (err != -ENOENT)
++ *hotdrop = 1;
+ return 0;
++ }
+
+ fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
+ if (fh == NULL) {
+diff -urN linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_hbh.c linux-source-2.6.18/net/ipv6/netfilter/ip6t_hbh.c
+--- linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_hbh.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv6/netfilter/ip6t_hbh.c 2006-12-17 17:12:20.758827500 -0700
+@@ -70,13 +70,18 @@
+ u8 _opttype, *tp = NULL;
+ u8 _optlen, *lp = NULL;
+ unsigned int optlen;
++ int err;
+
+ #if HOPBYHOP
+- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
++ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL);
+ #else
+- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
++ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL;
+ #endif
++ if (err < 0) {
++ if (err != -ENOENT)
++ *hotdrop = 1;
+ return 0;
++ }
+
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ if (oh == NULL) {
+diff -urN linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_rt.c linux-source-2.6.18/net/ipv6/netfilter/ip6t_rt.c
+--- linux-source-2.6.18.orig/net/ipv6/netfilter/ip6t_rt.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/net/ipv6/netfilter/ip6t_rt.c 2006-12-17 17:04:47.302488250 -0700
+@@ -58,9 +58,14 @@
+ unsigned int hdrlen = 0;
+ unsigned int ret = 0;
+ struct in6_addr *ap, _addr;
++ int err;
+
+- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0)
++ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
++ if (err < 0) {
++ if (err != -ENOENT)
++ *hotdrop = 1;
+ return 0;
++ }
+
+ rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+ if (rh == NULL) {
Added: dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-protocol-bypass-bug.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/ip6_tables-protocol-bypass-bug.patch Mon Dec 18 01:26:17 2006
@@ -0,0 +1,60 @@
+From: Patrick McHardy <kaber at trash.net>
+Date: Tue, 24 Oct 2006 23:14:04 +0000 (-0700)
+Subject: [NETFILTER]: Fix ip6_tables protocol bypass bug
+X-Git-Tag: v2.6.19-rc4
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=51d8b1a65291a6956b79374b6adbbadc2263bcf6
+
+[NETFILTER]: Fix ip6_tables protocol bypass bug
+
+As reported by Mark Dowd <Mark_Dowd at 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 at toshiba.co.jp>.
+
+Signed-off-by: Patrick McHardy <kaber at trash.net>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+--- 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 *s
+ 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 *s
+ 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,
Modified: dists/sid/linux-2.6/debian/patches/series/9
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/9 (original)
+++ dists/sid/linux-2.6/debian/patches/series/9 Mon Dec 18 01:26:17 2006
@@ -1,2 +1,4 @@
+ bugfix/dm-crypt-fix-data-corruption-with-dm-crypt-over-raid5.patch
- bugfix/2.6.18.5-revert-abi-1.patch
+bugfix/ip6_tables-protocol-bypass-bug.patch
+bugfix/ip6_tables-extension-header-bypass-bug.patch
More information about the Kernel-svn-changes
mailing list