]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.32.3/netfilter-fix-crashes-in-bridge-netfilter-caused-by-fragment-jumps.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.3 / netfilter-fix-crashes-in-bridge-netfilter-caused-by-fragment-jumps.patch
CommitLineData
80e6ae8f
GKH
1From 8fa9ff6849bb86c59cc2ea9faadf3cb2d5223497 Mon Sep 17 00:00:00 2001
2From: Patrick McHardy <kaber@trash.net>
3Date: Tue, 15 Dec 2009 16:59:59 +0100
4Subject: netfilter: fix crashes in bridge netfilter caused by fragment jumps
5
6From: Patrick McHardy <kaber@trash.net>
7
8commit 8fa9ff6849bb86c59cc2ea9faadf3cb2d5223497 upstream.
9
10When fragments from bridge netfilter are passed to IPv4 or IPv6 conntrack
11and a reassembly queue with the same fragment key already exists from
12reassembling a similar packet received on a different device (f.i. with
13multicasted fragments), the reassembled packet might continue on a different
14codepath than where the head fragment originated. This can cause crashes
15in bridge netfilter when a fragment received on a non-bridge device (and
16thus with skb->nf_bridge == NULL) continues through the bridge netfilter
17code.
18
19Add a new reassembly identifier for packets originating from bridge
20netfilter and use it to put those packets in insolated queues.
21
22Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14805
23
24Reported-and-Tested-by: Chong Qiao <qiaochong@loongson.cn>
25Signed-off-by: Patrick McHardy <kaber@trash.net>
26Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
27
28---
29 include/net/ip.h | 1 +
30 include/net/ipv6.h | 1 +
31 net/ipv4/netfilter/nf_defrag_ipv4.c | 21 +++++++++++++++++----
32 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 6 ++++++
33 4 files changed, 25 insertions(+), 4 deletions(-)
34
35--- a/include/net/ip.h
36+++ b/include/net/ip.h
37@@ -342,6 +342,7 @@ enum ip_defrag_users
38 IP_DEFRAG_CALL_RA_CHAIN,
39 IP_DEFRAG_CONNTRACK_IN,
40 IP_DEFRAG_CONNTRACK_OUT,
41+ IP_DEFRAG_CONNTRACK_BRIDGE_IN,
42 IP_DEFRAG_VS_IN,
43 IP_DEFRAG_VS_OUT,
44 IP_DEFRAG_VS_FWD
45--- a/include/net/ipv6.h
46+++ b/include/net/ipv6.h
47@@ -358,6 +358,7 @@ enum ip6_defrag_users {
48 IP6_DEFRAG_LOCAL_DELIVER,
49 IP6_DEFRAG_CONNTRACK_IN,
50 IP6_DEFRAG_CONNTRACK_OUT,
51+ IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
52 };
53
54 struct ip6_create_arg {
55--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
56+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
57@@ -14,6 +14,7 @@
58 #include <net/route.h>
59 #include <net/ip.h>
60
61+#include <linux/netfilter_bridge.h>
62 #include <linux/netfilter_ipv4.h>
63 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
64
65@@ -34,6 +35,20 @@ static int nf_ct_ipv4_gather_frags(struc
66 return err;
67 }
68
69+static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
70+ struct sk_buff *skb)
71+{
72+#ifdef CONFIG_BRIDGE_NETFILTER
73+ if (skb->nf_bridge &&
74+ skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
75+ return IP_DEFRAG_CONNTRACK_BRIDGE_IN;
76+#endif
77+ if (hooknum == NF_INET_PRE_ROUTING)
78+ return IP_DEFRAG_CONNTRACK_IN;
79+ else
80+ return IP_DEFRAG_CONNTRACK_OUT;
81+}
82+
83 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
84 struct sk_buff *skb,
85 const struct net_device *in,
86@@ -50,10 +65,8 @@ static unsigned int ipv4_conntrack_defra
87 #endif
88 /* Gather fragments. */
89 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
90- if (nf_ct_ipv4_gather_frags(skb,
91- hooknum == NF_INET_PRE_ROUTING ?
92- IP_DEFRAG_CONNTRACK_IN :
93- IP_DEFRAG_CONNTRACK_OUT))
94+ enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
95+ if (nf_ct_ipv4_gather_frags(skb, user))
96 return NF_STOLEN;
97 }
98 return NF_ACCEPT;
99--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
100+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
101@@ -20,6 +20,7 @@
102 #include <net/ipv6.h>
103 #include <net/inet_frag.h>
104
105+#include <linux/netfilter_bridge.h>
106 #include <linux/netfilter_ipv6.h>
107 #include <net/netfilter/nf_conntrack.h>
108 #include <net/netfilter/nf_conntrack_helper.h>
109@@ -190,6 +191,11 @@ out:
110 static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
111 struct sk_buff *skb)
112 {
113+#ifdef CONFIG_BRIDGE_NETFILTER
114+ if (skb->nf_bridge &&
115+ skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
116+ return IP6_DEFRAG_CONNTRACK_BRIDGE_IN;
117+#endif
118 if (hooknum == NF_INET_PRE_ROUTING)
119 return IP6_DEFRAG_CONNTRACK_IN;
120 else