add ip6_tables fixes

svn path=/dists/trunk/linux-2.6/; revision=7652
This commit is contained in:
maximilian attems 2006-10-26 20:21:37 +00:00
parent 87aff8ee57
commit 8061cb107f
4 changed files with 253 additions and 1 deletions

3
debian/changelog vendored
View File

@ -26,8 +26,9 @@ linux-2.6 (2.6.18-4) UNRELEASED; urgency=low
* Bump build-dependency on kernel-package to 10.063.
* [sparc64] Add davem fix memory corruption in pci_4u_free_consistent().
* [sparc64] Add davem fix central/FHC bus handling on Ex000 systems.
* [ip6_tables] Add patches for protocol and extension header bypass bug.
-- maximilian attems <maks@sternwelten.at> Thu, 26 Oct 2006 21:58:59 +0200
-- maximilian attems <maks@sternwelten.at> Thu, 26 Oct 2006 22:20:34 +0200
linux-2.6 (2.6.18-3) unstable; urgency=low

View File

@ -0,0 +1,174 @@
From git-commits-head-owner@vger.kernel.org Wed Oct 25 14:13:09 2006
Date: Wed, 25 Oct 2006 05:59:05 GMT
Message-Id: <200610250559.k9P5x5tk014073@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [NETFILTER]: Fix ip6_tables extension header bypass bug
commit 6d381634d213580d40d431e7664dfb45f641b884
tree a8680dd059e9a4e115d17e54d4a8dcea4d196a3e
parent 51d8b1a65291a6956b79374b6adbbadc2263bcf6
author Patrick McHardy <kaber@trash.net> 1161731710 -0700
committer David S. Miller <davem@davemloft.net> 1161731710 -0700
[NETFILTER]: Fix ip6_tables extension header bypass bug
As reported by Mark Dowd <Mark_Dowd@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@toshiba.co.jp>.
Fixed reject in ip6t_hbh.c for stable. -maks
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: maximilian attems <maks@sternwelten.at>
net/ipv6/netfilter/ip6_tables.c | 11 +++++++----
net/ipv6/netfilter/ip6t_ah.c | 7 ++++++-
net/ipv6/netfilter/ip6t_frag.c | 7 ++++++-
net/ipv6/netfilter/ip6t_hbh.c | 7 ++++++-
net/ipv6/netfilter/ip6t_rt.c | 7 ++++++-
5 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index f0328c7..53bf977 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1440,6 +1440,9 @@ static void __exit ip6_tables_fini(void)
* 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
@@ -1463,12 +1466,12 @@ int ipv6_find_hdr(const struct sk_buff *
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,
@@ -1477,7 +1480,7 @@ int ipv6_find_hdr(const struct sk_buff *
sizeof(_frag_off),
&_frag_off);
if (fp == NULL)
- return -1;
+ return -EBADMSG;
_frag_off = ntohs(*fp) & ~0x7;
if (_frag_off) {
@@ -1488,7 +1491,7 @@ int ipv6_find_hdr(const struct sk_buff *
*fragoff = _frag_off;
return hp->nexthdr;
}
- return -1;
+ return -ENOENT;
}
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index ec1b160..4648664 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -54,9 +54,14 @@ match(const struct sk_buff *skb,
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 --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 78d9c8b..cd22eaa 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -52,9 +52,14 @@ match(const struct sk_buff *skb,
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) {
--- a/net/ipv6/netfilter/ip6t_hbh.c.orig 2006-10-26 22:11:31.000000000 +0200
+++ b/net/ipv6/netfilter/ip6t_hbh.c 2006-10-26 22:13:06.000000000 +0200
@@ -72,11 +72,15 @@ match(const struct sk_buff *skb,
unsigned int optlen;
#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 --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index bcb2e16..54d7d14 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -58,9 +58,14 @@ match(const struct sk_buff *skb,
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) {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

View File

@ -0,0 +1,75 @@
From git-commits-head-owner@vger.kernel.org Tue Jun 6 18:56:24 2006
Message-Id: <200610250559.k9P5x4BG014065@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [NETFILTER]: Fix ip6_tables protocol bypass bug
commit 51d8b1a65291a6956b79374b6adbbadc2263bcf6
tree d6b8cbd6628c11d1c3e9c8c8e9ca048acf723a71
parent 2fab22f2d3290ff7c602fe62f22e825c48e97a06
author Patrick McHardy <kaber@trash.net> 1161731644 -0700
committer David S. Miller <davem@davemloft.net> 1161731644 -0700
[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>
net/ipv6/netfilter/ip6_tables.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368f..f0328c7 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 *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 @@ #define FWINV(bool,invflg) ((bool) ^ !!(
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,
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

View File

@ -9,3 +9,5 @@
+ bugfix/net-r8169-hotplug_loop.patch
+ bugfix/sparc/mem_corruption-pci_4u_free_consistent.patch
+ bugfix/sparc/central_fhc_bus-Ex000.patch
+ bugfix/net-ip6_tables_extension_header-bypass.patch
+ bugfix/net-ip6_tables_protocol-bypass.patch