Thread (6 messages) flat view 6 messages, 3 authors, 8h ago
HOTtoday REVIEWED: 3 (3M)

1 review trailer (1 from subsystem maintainers).

[PATCH net v2] net: bridge: mcast: fix br_multicast_list_adjacent rcu walk of mglist

From: Nikolay Aleksandrov <razor@blackwall.org>
Date: 2026-09-01 07:40:59
Also in: bridge
Subsystem: ethernet bridge, networking [general], the rest · Maintainers: Nikolay Aleksandrov, Ido Schimmel, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

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. Return -ENOMEM on allocation error.

[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260826014200.362304-1-littleddfu%40gmail.com

Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Fixes: 07f8ac4a1e26 ("bridge: add export of multicast database adjacent to net_dev")
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
---
v2: while changing this fn, return -ENOMEM on error and document it in
    the kdoc (sashiko)

 net/bridge/br_multicast.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 3ef5d8bbf552..97686984de6d 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -4936,13 +4936,15 @@ void br_multicast_set_startup_query_intvl(struct net_bridge_mcast *brmctx,
  * snooping feature on all bridge ports of dev's bridge device, excluding
  * the addresses from dev itself.
  *
- * Returns the number of items added to br_ip_list.
+ * Return: The number of items added to br_ip_list or -ENOMEM on memory
+ *         allocation error
  *
  * Notes:
  * - br_ip_list needs to be initialized by caller
  * - br_ip_list might contain duplicates in the end
  *   (needs to be taken care of by caller)
  * - br_ip_list needs to be freed by caller
+ * - on -ENOMEM the caller must free any allocated entries
  */
 int br_multicast_list_adjacent(struct net_device *dev,
 			       struct list_head *br_ip_list)
@@ -4967,15 +4969,20 @@ 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);
+				count = -ENOMEM;
 				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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help