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

Contents of /genpatches-2.6/tags/2.6.15-11/1030_4_bridge-rcu-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 ago) by dsd
File size: 3614 byte(s)
2.6.15-11 release
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 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
15 ---
16
17 net/bridge/br_if.c | 7 ++-----
18 net/bridge/br_input.c | 10 ++++++++--
19 net/bridge/br_stp_bpdu.c | 8 ++++++--
20 3 files changed, 16 insertions(+), 9 deletions(-)
21
22 Index: linux-2.6.15.3/net/bridge/br_if.c
23 ===================================================================
24 --- linux-2.6.15.3.orig/net/bridge/br_if.c
25 +++ linux-2.6.15.3/net/bridge/br_if.c
26 @@ -99,7 +99,6 @@ static void del_nbp(struct net_bridge_po
27 struct net_bridge *br = p->br;
28 struct net_device *dev = p->dev;
29
30 - dev->br_port = NULL;
31 dev_set_promiscuity(dev, -1);
32
33 spin_lock_bh(&br->lock);
34 @@ -110,9 +109,7 @@ static void del_nbp(struct net_bridge_po
35
36 list_del_rcu(&p->list);
37
38 - del_timer_sync(&p->message_age_timer);
39 - del_timer_sync(&p->forward_delay_timer);
40 - del_timer_sync(&p->hold_timer);
41 + rcu_assign_pointer(dev->br_port, NULL);
42
43 call_rcu(&p->rcu, destroy_nbp_rcu);
44 }
45 @@ -217,7 +214,6 @@ static struct net_bridge_port *new_nbp(s
46 p->dev = dev;
47 p->path_cost = cost;
48 p->priority = 0x8000 >> BR_PORT_BITS;
49 - dev->br_port = p;
50 p->port_no = index;
51 br_init_port(p);
52 p->state = BR_STATE_DISABLED;
53 @@ -360,6 +356,7 @@ int br_add_if(struct net_bridge *br, str
54 else if ((err = br_sysfs_addif(p)))
55 del_nbp(p);
56 else {
57 + rcu_assign_pointer(dev->br_port, p);
58 dev_set_promiscuity(dev, 1);
59
60 list_add_rcu(&p->list, &br->port_list);
61 Index: linux-2.6.15.3/net/bridge/br_input.c
62 ===================================================================
63 --- linux-2.6.15.3.orig/net/bridge/br_input.c
64 +++ linux-2.6.15.3/net/bridge/br_input.c
65 @@ -45,11 +45,17 @@ static void br_pass_frame_up(struct net_
66 int br_handle_frame_finish(struct sk_buff *skb)
67 {
68 const unsigned char *dest = eth_hdr(skb)->h_dest;
69 - struct net_bridge_port *p = skb->dev->br_port;
70 - struct net_bridge *br = p->br;
71 + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
72 + struct net_bridge *br;
73 struct net_bridge_fdb_entry *dst;
74 int passedup = 0;
75
76 + if (unlikely(!p || p->state == BR_STATE_DISABLED)) {
77 + kfree_skb(skb);
78 + return 0;
79 + }
80 +
81 + br = p->br;
82 /* insert into forwarding database after filtering to avoid spoofing */
83 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
84
85 Index: linux-2.6.15.3/net/bridge/br_stp_bpdu.c
86 ===================================================================
87 --- linux-2.6.15.3.orig/net/bridge/br_stp_bpdu.c
88 +++ linux-2.6.15.3/net/bridge/br_stp_bpdu.c
89 @@ -136,10 +136,13 @@ static const unsigned char header[6] = {
90 /* NO locks */
91 int br_stp_handle_bpdu(struct sk_buff *skb)
92 {
93 - struct net_bridge_port *p = skb->dev->br_port;
94 - struct net_bridge *br = p->br;
95 + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
96 + struct net_bridge *br;
97 unsigned char *buf;
98
99 + if (!p)
100 + goto err;
101 +
102 /* insert into forwarding database after filtering to avoid spoofing */
103 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
104
105 @@ -150,6 +153,7 @@ int br_stp_handle_bpdu(struct sk_buff *s
106
107 buf = skb_pull(skb, sizeof(header));
108
109 + br = p->br;
110 spin_lock_bh(&br->lock);
111 if (p->state == BR_STATE_DISABLED
112 || !(br->dev->flags & IFF_UP)

  ViewVC Help
Powered by ViewVC 1.1.20