data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2025-38248 in the interactive tracker

CVE-2025-38248

bridge: mcast: Fix use-after-free during router port configuration

7.8 EPSS 0.3% AV:L

Published 2025-07-09 (15 months ago) by the Linux kernel CNA. Subsystem net/bridge. Debian urgency: not yet assigned.

What to do, per Debian release

Debian's own status for CVE-2025-38248 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormvulnerable6.1.190-1No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication.
Debian 13trixiefixedDSA-6126-1 · 2026-02-09 · text6.12.69-1Update the kernel and reboot. DSA-6126-1 shipped the fix on 2026-02-09, in 6.12.69-1. A running kernel keeps the old code until the machine restarts.
Debian 14forkyfixed6.16.3-1Update the kernel and reboot. Fixed in 6.16.3-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed6.16.3-1Update the kernel and reboot. Fixed in 6.16.3-1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

The bridge maintains a global list of ports behind which a multicast router resides. The list is consulted during forwarding to ensure multicast packets are forwarded to these ports even if the ports are not member in the matching MDB entry. When per-VLAN multicast snooping is enabled, the per-port multicast context is disabled on each port and the port is removed from the global router port list: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 # ip link add name dummy1 up master br1 type dummy # ip link set dev dummy1 type bridge_slave mcast_router 2 $ bridge -d mdb show | grep router router ports on br1: dummy1 # ip link set dev br1 type bridge mcast_vlan_snooping 1 $ bridge -d mdb show | grep router However, the port can be re-added to the global list even when per-VLAN multicast snooping is enabled: # ip link set dev dummy1 type bridge_slave mcast_router 0 # ip link set dev dummy1 type bridge_slave mcast_router 2 $ bridge -d mdb show | grep router router ports on br1: dummy1 Since commit 4b30ae9adb04 ("net: bridge: mcast: re-implement br_multicast_{enable, disable}_port functions"), when per-VLAN multicast snooping is enabled, multicast disablement on a port will disable the per-{port, VLAN} multicast contexts and not the per-port one. As a result, a port will remain in the global router port list even after it is deleted. This will lead to a use-after-free [1] when the list is traversed (when adding a new port to the list, for example): # ip link del dev dummy1 # ip link add name dummy2 up master br1 type dummy # ip link set dev dummy2 type bridge_slave mcast_router 2 Similarly, stale entries can also be found in the per-VLAN router port list. When per-VLAN multicast snooping is disabled, the per-{port, VLAN} contexts are disabled on each port and the port is removed from the per-VLAN router port list: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1 # ip link add name dummy1 up master br1 type dummy # bridge vlan add vid 2 dev dummy1 # bridge vlan global set vid 2 dev br1 mcast_snooping 1 # bridge vlan set vid 2 dev dummy1 mcast_router 2 $ bridge vlan global show dev br1 vid 2 | grep router router ports: dummy1 # ip link set dev br1 type bridge mcast_vlan_snooping 0 $ bridge vlan global show dev br1 vid 2 | grep router However, the port can be re-added to the per-VLAN list even when per-VLAN multicast snooping is disabled: # bridge vlan set vid 2 dev dummy1 mcast_router 0 # bridge vlan set vid 2 dev dummy1 mcast_router 2 $ bridge vlan global show dev br1 vid 2 | grep router router ports: dummy1 When the VLAN is deleted from the port, the per-{port, VLAN} multicast context will not be disabled since multicast snooping is not enabled on the VLAN. As a result, the port will remain in the per-VLAN router port list even after it is no longer member in the VLAN. This will lead to a use-after-free [2] when the list is traversed (when adding a new port to the list, for example): # ip link add name dummy2 up master br1 type dummy # bridge vlan add vid 2 dev dummy2 # bridge vlan del vid 2 dev dummy1 # bridge vlan set vid 2 dev dummy2 mcast_router 2 Fix these issues by removing the port from the relevant (global or per-VLAN) router port list in br_multicast_port_ctx_deinit(). The function is invoked during port deletion with the per-port multicast context and during VLAN deletion with the per-{port, VLAN} multicast context. Note that deleting the multicast router timer is not enough as it only takes care of the temporary multicast router states (1 or 3) and not the permanent one (2). [1] BUG: KASAN: slab-out-of-bounds in br_multicast_add_router.part.0+0x3f1/0x560 Write of size 8 at addr ffff888004a67328 by task ip/384 [...] Call Trace: <TASK> dump_stack ---truncated---

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

net/bridge/br_multicast.c

What this is
ETHERNET BRIDGEMAINTAINERS section matched on net/bridge/ · bridge@lists.linux.dev · Maintained
Kernel module
bridge

Check it on the machine

grep -wE 'CONFIG_BRIDGE|CONFIG_BRIDGE_IGMP_SNOOPING' /boot/config-$(uname -r)

Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.

lsmod | grep -w bridge

Prints a line if that module is loaded right now, and nothing if it is not. One that is not loaded can still be loaded later by anything that needs it.

Show whether Debian builds this, per release

Debian builds this as a loadable module. Every release below compiles it as a module on every flavour, so whether the code is in the running kernel depends on whether that module is loaded.

  • bookworm, trixie, forky, sidm
m
a loadable module on every flavour - check lsmod, can be blacklisted
Build switches
CONFIG_BRIDGE, CONFIG_BRIDGE_IGMP_SNOOPING
Reads as
all on means the file is compiled; any one off means it is not.

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages

Signals

Published
2025-07-09 (15 months ago)source
CVSS
7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it
Attack vector
local (AV:L)source
EPSS
0.30%, higher than 21.3% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
not yet assignedsource
Subsystem
net/bridge

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
5.156.6.1224d3c2a1d4c7c
5.156.12.67bdced577da71
5.156.15.5f05a4f9e959e
5.156.167544f3f5b0b5

Debian advisories

AdvisoryDateShipped toDebian
DSA-6126-12026-02-09trixie 6.12.69-1tracker

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
The dangling router-port entry is created and triggered through rtnetlink configuration messages (RTM_NEWLINK/RTM_SETLINK with IFLA_BRPORT_MULTICAST_ROUTER and RTM_NEWVLAN options), which require a local socket. Per kernel guidance, netlink-reachable bugs are Local.
AC:LAttack complexity, low
The bug is a deterministic state-machine error, not a race: a fixed sequence of `ip link`/`bridge vlan` commands leaves the freed port on the router list and the very next mcast_router set triggers the UAF, as shown by the reproducers and the syzkaller report.
PR:LPrivileges required, low
Bridge port and VLAN configuration only requires CAP_NET_ADMIN in the netns owning the device, which any unprivileged user obtains via `unshare -Urn` and then creates the bridge, dummy ports and multicast options entirely inside that namespace.
UI:NUser interaction, none
The attacker performs the entire configuration sequence themselves through their own netlink socket; no victim action is needed at any point.
S:UScope, unchanged
The corruption stays within the kernel's own memory and security authority, with no crossing of a VM, IOMMU or sandbox boundary.
C:HConfidentiality impact, high
List traversal reads `pmctx->port` and the `hlist_node` links out of freed slab memory, and the resulting dangling entries are also walked on the multicast forwarding path, giving an attacker who reallocates the freed object a means to read kernel memory and defeat KASLR.
I:HIntegrity impact, high
`hlist_add_behind_rcu()` writes 8 bytes into the freed (attacker-reallocatable) object and later `hlist_del_init_rcu()` writes through an attacker-controlled `pprev`, yielding a controlled-write primitive; freed ports are additionally used to deliver packets via a dangling `net_device`, enabling control-flow hijack.
A:HAvailability impact, high
The use-after-free corrupts the bridge router list and reliably produces a KASAN-confirmed slab-use-after-free/out-of-bounds access, causing kernel oops or panic, and can be repeated at will.