3.13.11-ckt24 -stable review patch.  If anyone has any objections, please let 
me know.

------------------

From: Nikolay Aleksandrov <ra...@blackwall.org>

[ Upstream commit 2dab80a8b486f02222a69daca6859519e05781d9 ]

After the ->set() spinlocks were removed br_stp_set_bridge_priority
was left running without any protection when used via sysfs. It can
race with port add/del and could result in use-after-free cases and
corrupted lists. Tested by running port add/del in a loop with stp
enabled while setting priority in a loop, crashes are easily
reproducible.
The spinlocks around sysfs ->set() were removed in commit:
14f98f258f19 ("bridge: range check STP parameters")
There's also a race condition in the netlink priority support that is
fixed by this change, but it was introduced recently and the fixes tag
covers it, just in case it's needed the commit is:
af615762e972 ("bridge: add ageing_time, stp_state, priority over netlink")

Signed-off-by: Nikolay Aleksandrov <ra...@blackwall.org>
Fixes: 14f98f258f19 ("bridge: range check STP parameters")
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Kamal Mostafa <ka...@canonical.com>
---
 net/bridge/br_ioctl.c  | 2 --
 net/bridge/br_stp_if.c | 4 +++-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index cd8c3a4..b73eaba 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_device *dev, struct 
ifreq *rq, int cmd)
                if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_bh(&br->lock);
                br_stp_set_bridge_priority(br, args[1]);
-               spin_unlock_bh(&br->lock);
                return 0;
 
        case BRCTL_SET_PORT_PRIORITY:
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 656a6f3..886f6d6 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -241,12 +241,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
        return true;
 }
 
-/* called under bridge lock */
+/* Acquires and releases bridge lock */
 void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
 {
        struct net_bridge_port *p;
        int wasroot;
 
+       spin_lock_bh(&br->lock);
        wasroot = br_is_root_bridge(br);
 
        list_for_each_entry(p, &br->port_list, list) {
@@ -264,6 +265,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 
newprio)
        br_port_state_selection(br);
        if (br_is_root_bridge(br) && !wasroot)
                br_become_root_bridge(br);
+       spin_unlock_bh(&br->lock);
 }
 
 /* called under bridge lock */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to