[PATCH net] net: bridge: mcast: fix br_multicast_list_adjacent rcu walk of mglist
Nikolay Aleksandrov <[email protected]>
| Newsgroups | gmane.linux.network.bridge,gmane.linux.network |
|---|---|
| Message-ID | <[email protected]> |
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