Sashiko reported a bug [1] that br_multicast_del_port_group unlists the port group not using proper rcu helper that preserves the next pointer and after that immediately frees the port group without waiting for rcu grace period. The only rcu walker of mglist is br_multicast_list_adjacent() and it turns out that function has always been buggy because mglist was never converted to RCU. Fix it by acquiring the bridge's multicast lock for the mglist walk. We can do a proper mglist rcu conversion later.
[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260826014200.362304-1-littleddfu%40gmail.com Fixes: 07f8ac4a1e26 ("bridge: add export of multicast database adjacent to net_dev") Signed-off-by: Nikolay Aleksandrov <[email protected]> --- We can do a proper mglist rcu conversion when net-next opens up. net/bridge/br_multicast.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 3ef5d8bbf552..7fa5f4444c4c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -4967,15 +4967,19 @@ int br_multicast_list_adjacent(struct net_device *dev, if (!port->dev || port->dev == dev) continue; - hlist_for_each_entry_rcu(group, &port->mglist, mglist) { + spin_lock_bh(&br->multicast_lock); + hlist_for_each_entry(group, &port->mglist, mglist) { entry = kmalloc_obj(*entry, GFP_ATOMIC); - if (!entry) + if (!entry) { + spin_unlock_bh(&br->multicast_lock); goto unlock; + } entry->addr = group->key.addr; list_add(&entry->list, br_ip_list); count++; } + spin_unlock_bh(&br->multicast_lock); } unlock: -- 2.47.3
