Skip to content

Commit 2dab80a

Browse files
NikAleksandrovdavem330
authored andcommitted
bridge: fix br_stp_set_bridge_priority race conditions
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: 14f98f2 ("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: af61576 ("bridge: add ageing_time, stp_state, priority over netlink") Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org> Fixes: 14f98f2 ("bridge: range check STP parameters") Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ac0a72a commit 2dab80a

File tree

2 files changed

+3
-3
lines changed

2 files changed

+3
-3
lines changed

net/bridge/br_ioctl.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
247247
if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
248248
return -EPERM;
249249

250-
spin_lock_bh(&br->lock);
251250
br_stp_set_bridge_priority(br, args[1]);
252-
spin_unlock_bh(&br->lock);
253251
return 0;
254252

255253
case BRCTL_SET_PORT_PRIORITY:

net/bridge/br_stp_if.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
243243
return true;
244244
}
245245

246-
/* called under bridge lock */
246+
/* Acquires and releases bridge lock */
247247
void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
248248
{
249249
struct net_bridge_port *p;
250250
int wasroot;
251251

252+
spin_lock_bh(&br->lock);
252253
wasroot = br_is_root_bridge(br);
253254

254255
list_for_each_entry(p, &br->port_list, list) {
@@ -266,6 +267,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
266267
br_port_state_selection(br);
267268
if (br_is_root_bridge(br) && !wasroot)
268269
br_become_root_bridge(br);
270+
spin_unlock_bh(&br->lock);
269271
}
270272

271273
/* called under bridge lock */

0 commit comments

Comments
 (0)