/[linux-patches]/genpatches-2.6/trunk/2.6.14/1431_15.4_bridge-netfilter-race.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.14/1431_15.4_bridge-netfilter-race.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20