Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2880

kernel-2.6.18-238.el5.src.rpm

From: Jiri Pirko <jpirko@redhat.com>
Date: Tue, 24 Aug 2010 17:13:34 -0400
Subject: [net] netfilter: fix crashes caused by fragment jumps
Message-id: <20100824171333.GA2681@psychotron.redhat.com>
Patchwork-id: 27806
O-Subject: [RHEL5.6 patch] BZ617268 net: netfilter: fix crashes in bridge
	netfilter caused by fragment jumps
Bugzilla: 617268
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Thomas Graf <tgraf@redhat.com>
RH-Acked-by: David S. Miller <davem@redhat.com>

BZ617268
https://bugzilla.redhat.com/show_bug.cgi?id=617268

Description:
When fragments from bridge netfilter are passed to IPv4 conntrack
and a reassembly queue with the same fragment key already exists from
reassembling a similar packet received on a different device (f.i. with
multicasted fragments), the reassembled packet might continue on a different
codepath than where the head fragment originated. This was causing crashes
in bridge netfilter when a fragment received on a non-bridge device (and
thus with skb->nf_bridge == NULL) continues through the bridge netfilter
code.

Add a new reassembly identifier for packets originating from bridge
netfilter and use it to put those packets in insolated queues.

Upstream:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=8fa9ff6849bb86c59cc2ea9faadf3cb2d5223497

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=2682317

Sucessfully tested by customer.

Jirka

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/include/net/ip.h b/include/net/ip.h
index f8c889c..8bc7617 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -329,6 +329,7 @@ enum ip_defrag_users
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
 	IP_DEFRAG_CONNTRACK_OUT,
+	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 3b3a393..453d2aa 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -31,6 +31,7 @@
 #define ASSERT_READ_LOCK(x)
 #define ASSERT_WRITE_LOCK(x)
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -430,6 +431,20 @@ static unsigned int ip_conntrack_help(unsigned int hooknum,
 	return NF_ACCEPT;
 }
 
+static enum ip_defrag_users ip_ct_defrag_user(unsigned int hooknum,
+					      struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+	if (hooknum == NF_IP_PRE_ROUTING)
+		return IP_DEFRAG_CONNTRACK_IN;
+	else
+		return IP_DEFRAG_CONNTRACK_OUT;
+}
+
 static unsigned int ip_conntrack_defrag(unsigned int hooknum,
 				        struct sk_buff **pskb,
 				        const struct net_device *in,
@@ -449,10 +464,8 @@ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
 #endif
 	/* Gather fragments. */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		*pskb = ip_ct_gather_frags(*pskb,
-		                           hooknum == NF_IP_PRE_ROUTING ? 
-					   IP_DEFRAG_CONNTRACK_IN :
-					   IP_DEFRAG_CONNTRACK_OUT);
+		enum ip_defrag_users user = ip_ct_defrag_user(hooknum, *pskb);
+		*pskb = ip_ct_gather_frags(*pskb, user);
 		if (!*pskb)
 			return NF_STOLEN;
 	}