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

Contents of /genpatches-2.6/trunk/2.6.14/1432_15.4_bridge-rcu-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: 3563 byte(s)
2.6.14-11, rebase against local tree
1 From stable-bounces@linux.kernel.org Mon Feb 6 15:50:01 2006
2 Date: Mon, 6 Feb 2006 15:42:45 -0800
3 From: Stephen Hemminger <shemminger@osdl.org>
4 To: stable@kernel.org
5 Cc:
6 Subject: [PATCH] bridge: fix RCU race on device removal
7
8 Patch to 2.6.15 stable kernel to fix race conditions on device
9 removal. These are reproducible by doing delif while packets are
10 in flight.
11
12 Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
13 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
14 ---
15
16 net/bridge/br_if.c | 7 ++-----
17 net/bridge/br_input.c | 10 ++++++++--
18 net/bridge/br_stp_bpdu.c | 8 ++++++--
19 3 files changed, 16 insertions(+), 9 deletions(-)
20
21 Index: linux-2.6.15.3/net/bridge/br_if.c
22 ===================================================================
23 --- linux-2.6.15.3.orig/net/bridge/br_if.c
24 +++ linux-2.6.15.3/net/bridge/br_if.c
25 @@ -99,7 +99,6 @@ static void del_nbp(struct net_bridge_po
26 struct net_bridge *br = p->br;
27 struct net_device *dev = p->dev;
28
29 - dev->br_port = NULL;
30 dev_set_promiscuity(dev, -1);
31
32 spin_lock_bh(&br->lock);
33 @@ -110,9 +109,7 @@ static void del_nbp(struct net_bridge_po
34
35 list_del_rcu(&p->list);
36
37 - del_timer_sync(&p->message_age_timer);
38 - del_timer_sync(&p->forward_delay_timer);
39 - del_timer_sync(&p->hold_timer);
40 + rcu_assign_pointer(dev->br_port, NULL);
41
42 call_rcu(&p->rcu, destroy_nbp_rcu);
43 }
44 @@ -217,7 +214,6 @@ static struct net_bridge_port *new_nbp(s
45 p->dev = dev;
46 p->path_cost = cost;
47 p->priority = 0x8000 >> BR_PORT_BITS;
48 - dev->br_port = p;
49 p->port_no = index;
50 br_init_port(p);
51 p->state = BR_STATE_DISABLED;
52 @@ -360,6 +356,7 @@ int br_add_if(struct net_bridge *br, str
53 else if ((err = br_sysfs_addif(p)))
54 del_nbp(p);
55 else {
56 + rcu_assign_pointer(dev->br_port, p);
57 dev_set_promiscuity(dev, 1);
58
59 list_add_rcu(&p->list, &br->port_list);
60 Index: linux-2.6.15.3/net/bridge/br_input.c
61 ===================================================================
62 --- linux-2.6.15.3.orig/net/bridge/br_input.c
63 +++ linux-2.6.15.3/net/bridge/br_input.c
64 @@ -45,11 +45,17 @@ static void br_pass_frame_up(struct net_
65 int br_handle_frame_finish(struct sk_buff *skb)
66 {
67 const unsigned char *dest = eth_hdr(skb)->h_dest;
68 - struct net_bridge_port *p = skb->dev->br_port;
69 - struct net_bridge *br = p->br;
70 + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
71 + struct net_bridge *br;
72 struct net_bridge_fdb_entry *dst;
73 int passedup = 0;
74
75 + if (unlikely(!p || p->state == BR_STATE_DISABLED)) {
76 + kfree_skb(skb);
77 + return 0;
78 + }
79 +
80 + br = p->br;
81 /* insert into forwarding database after filtering to avoid spoofing */
82 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
83
84 Index: linux-2.6.15.3/net/bridge/br_stp_bpdu.c
85 ===================================================================
86 --- linux-2.6.15.3.orig/net/bridge/br_stp_bpdu.c
87 +++ linux-2.6.15.3/net/bridge/br_stp_bpdu.c
88 @@ -136,10 +136,13 @@ static const unsigned char header[6] = {
89 /* NO locks */
90 int br_stp_handle_bpdu(struct sk_buff *skb)
91 {
92 - struct net_bridge_port *p = skb->dev->br_port;
93 - struct net_bridge *br = p->br;
94 + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
95 + struct net_bridge *br;
96 unsigned char *buf;
97
98 + if (!p)
99 + goto err;
100 +
101 /* insert into forwarding database after filtering to avoid spoofing */
102 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
103
104 @@ -150,6 +153,7 @@ int br_stp_handle_bpdu(struct sk_buff *s
105
106 buf = skb_pull(skb, sizeof(header));
107
108 + br = p->br;
109 spin_lock_bh(&br->lock);
110 if (p->state == BR_STATE_DISABLED
111 || !(br->dev->flags & IFF_UP)

  ViewVC Help
Powered by ViewVC 1.1.20