]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.0.8/bridge-fix-br_stp_set_bridge_priority-race-conditions.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.0.8 / bridge-fix-br_stp_set_bridge_priority-race-conditions.patch
CommitLineData
da495922
GKH
1From foo@baz Fri Jul 3 19:59:52 PDT 2015
2From: Nikolay Aleksandrov <razor@blackwall.org>
3Date: Mon, 15 Jun 2015 20:28:51 +0300
4Subject: bridge: fix br_stp_set_bridge_priority race conditions
5
6From: Nikolay Aleksandrov <razor@blackwall.org>
7
8[ Upstream commit 2dab80a8b486f02222a69daca6859519e05781d9 ]
9
10After the ->set() spinlocks were removed br_stp_set_bridge_priority
11was left running without any protection when used via sysfs. It can
12race with port add/del and could result in use-after-free cases and
13corrupted lists. Tested by running port add/del in a loop with stp
14enabled while setting priority in a loop, crashes are easily
15reproducible.
16The spinlocks around sysfs ->set() were removed in commit:
1714f98f258f19 ("bridge: range check STP parameters")
18There's also a race condition in the netlink priority support that is
19fixed by this change, but it was introduced recently and the fixes tag
20covers it, just in case it's needed the commit is:
21af615762e972 ("bridge: add ageing_time, stp_state, priority over netlink")
22
23Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
24Fixes: 14f98f258f19 ("bridge: range check STP parameters")
25Signed-off-by: David S. Miller <davem@davemloft.net>
26Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27---
28 net/bridge/br_ioctl.c | 2 --
29 net/bridge/br_stp_if.c | 4 +++-
30 2 files changed, 3 insertions(+), 3 deletions(-)
31
32--- a/net/bridge/br_ioctl.c
33+++ b/net/bridge/br_ioctl.c
34@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_devi
35 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
36 return -EPERM;
37
38- spin_lock_bh(&br->lock);
39 br_stp_set_bridge_priority(br, args[1]);
40- spin_unlock_bh(&br->lock);
41 return 0;
42
43 case BRCTL_SET_PORT_PRIORITY:
44--- a/net/bridge/br_stp_if.c
45+++ b/net/bridge/br_stp_if.c
46@@ -243,12 +243,13 @@ bool br_stp_recalculate_bridge_id(struct
47 return true;
48 }
49
50-/* called under bridge lock */
51+/* Acquires and releases bridge lock */
52 void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
53 {
54 struct net_bridge_port *p;
55 int wasroot;
56
57+ spin_lock_bh(&br->lock);
58 wasroot = br_is_root_bridge(br);
59
60 list_for_each_entry(p, &br->port_list, list) {
61@@ -266,6 +267,7 @@ void br_stp_set_bridge_priority(struct n
62 br_port_state_selection(br);
63 if (br_is_root_bridge(br) && !wasroot)
64 br_become_root_bridge(br);
65+ spin_unlock_bh(&br->lock);
66 }
67
68 /* called under bridge lock */