/[linux-patches]/genpatches-2.6/tags/2.6.15-11/1031_4_bridge-netfilter-race.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.15-11/1031_4_bridge-netfilter-race.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 351 - (show annotations) (download)
Wed Mar 29 11:55:38 2006 UTC (12 years, 6 months ago) by dsd
File size: 5830 byte(s)
2.6.15-11 release
1 From stable-bounces@linux.kernel.org Mon Feb 6 15:49:07 2006
2 Date: Mon, 6 Feb 2006 15:41:15 -0800
3 From: Stephen Hemminger <shemminger@osdl.org>
4 To: stable@kernel.org
5 Cc: netdev@vger.kernel.org, David Miller <davem@davemloft.net>
6 Subject: [PATCH] bridge: netfilter races on device removal
7
8 Fix bridge netfilter to handle case where interface is deleted
9 from bridge while packet is being processed (on other CPU).
10
11 Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=5803
12
13 Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
14 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
15 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
16 ---
17
18 net/bridge/br_netfilter.c | 55 +++++++++++++++++++++++++++++++---------------
19 1 files changed, 38 insertions(+), 17 deletions(-)
20
21 Index: linux-2.6.15.3/net/bridge/br_netfilter.c
22 ===================================================================
23 --- linux-2.6.15.3.orig/net/bridge/br_netfilter.c
24 +++ linux-2.6.15.3/net/bridge/br_netfilter.c
25 @@ -47,9 +47,6 @@
26 #define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr)
27 #define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr)
28
29 -#define has_bridge_parent(device) ((device)->br_port != NULL)
30 -#define bridge_parent(device) ((device)->br_port->br->dev)
31 -
32 #ifdef CONFIG_SYSCTL
33 static struct ctl_table_header *brnf_sysctl_header;
34 static int brnf_call_iptables = 1;
35 @@ -94,6 +91,12 @@ static struct rtable __fake_rtable = {
36 .rt_flags = 0,
37 };
38
39 +static inline struct net_device *bridge_parent(const struct net_device *dev)
40 +{
41 + struct net_bridge_port *port = rcu_dereference(dev->br_port);
42 +
43 + return port ? port->br->dev : NULL;
44 +}
45
46 /* PF_BRIDGE/PRE_ROUTING *********************************************/
47 /* Undo the changes made for ip6tables PREROUTING and continue the
48 @@ -185,11 +188,15 @@ static int br_nf_pre_routing_finish_brid
49 skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
50
51 skb->dev = bridge_parent(skb->dev);
52 - if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
53 - skb_pull(skb, VLAN_HLEN);
54 - skb->nh.raw += VLAN_HLEN;
55 + if (!skb->dev)
56 + kfree_skb(skb);
57 + else {
58 + if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
59 + skb_pull(skb, VLAN_HLEN);
60 + skb->nh.raw += VLAN_HLEN;
61 + }
62 + skb->dst->output(skb);
63 }
64 - skb->dst->output(skb);
65 return 0;
66 }
67
68 @@ -266,7 +273,7 @@ bridged_dnat:
69 }
70
71 /* Some common code for IPv4/IPv6 */
72 -static void setup_pre_routing(struct sk_buff *skb)
73 +static struct net_device *setup_pre_routing(struct sk_buff *skb)
74 {
75 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
76
77 @@ -278,6 +285,8 @@ static void setup_pre_routing(struct sk_
78 nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
79 nf_bridge->physindev = skb->dev;
80 skb->dev = bridge_parent(skb->dev);
81 +
82 + return skb->dev;
83 }
84
85 /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
86 @@ -372,7 +381,8 @@ static unsigned int br_nf_pre_routing_ip
87 nf_bridge_put(skb->nf_bridge);
88 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
89 return NF_DROP;
90 - setup_pre_routing(skb);
91 + if (!setup_pre_routing(skb))
92 + return NF_DROP;
93
94 NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
95 br_nf_pre_routing_finish_ipv6);
96 @@ -409,7 +419,6 @@ static unsigned int br_nf_pre_routing(un
97
98 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
99 skb_pull(skb, VLAN_HLEN);
100 - (skb)->nh.raw += VLAN_HLEN;
101 }
102 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
103 }
104 @@ -426,7 +435,6 @@ static unsigned int br_nf_pre_routing(un
105
106 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
107 skb_pull(skb, VLAN_HLEN);
108 - (skb)->nh.raw += VLAN_HLEN;
109 }
110
111 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
112 @@ -456,7 +464,8 @@ static unsigned int br_nf_pre_routing(un
113 nf_bridge_put(skb->nf_bridge);
114 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
115 return NF_DROP;
116 - setup_pre_routing(skb);
117 + if (!setup_pre_routing(skb))
118 + return NF_DROP;
119 store_orig_dstaddr(skb);
120
121 NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
122 @@ -530,11 +539,16 @@ static unsigned int br_nf_forward_ip(uns
123 struct sk_buff *skb = *pskb;
124 struct nf_bridge_info *nf_bridge;
125 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
126 + struct net_device *parent;
127 int pf;
128
129 if (!skb->nf_bridge)
130 return NF_ACCEPT;
131
132 + parent = bridge_parent(out);
133 + if (!parent)
134 + return NF_DROP;
135 +
136 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
137 pf = PF_INET;
138 else
139 @@ -555,8 +569,8 @@ static unsigned int br_nf_forward_ip(uns
140 nf_bridge->mask |= BRNF_BRIDGED;
141 nf_bridge->physoutdev = skb->dev;
142
143 - NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
144 - bridge_parent(out), br_nf_forward_finish);
145 + NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent,
146 + br_nf_forward_finish);
147
148 return NF_STOLEN;
149 }
150 @@ -679,6 +693,8 @@ static unsigned int br_nf_local_out(unsi
151 goto out;
152 }
153 realoutdev = bridge_parent(skb->dev);
154 + if (!realoutdev)
155 + return NF_DROP;
156
157 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
158 /* iptables should match -o br0.x */
159 @@ -692,9 +708,11 @@ static unsigned int br_nf_local_out(unsi
160 /* IP forwarded traffic has a physindev, locally
161 * generated traffic hasn't. */
162 if (realindev != NULL) {
163 - if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
164 - has_bridge_parent(realindev))
165 - realindev = bridge_parent(realindev);
166 + if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) {
167 + struct net_device *parent = bridge_parent(realindev);
168 + if (parent)
169 + realindev = parent;
170 + }
171
172 NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
173 realoutdev, br_nf_local_out_finish,
174 @@ -734,6 +752,9 @@ static unsigned int br_nf_post_routing(u
175 if (!nf_bridge)
176 return NF_ACCEPT;
177
178 + if (!realoutdev)
179 + return NF_DROP;
180 +
181 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
182 pf = PF_INET;
183 else

  ViewVC Help
Powered by ViewVC 1.1.20