UAF in add_bw_upcall: mfc pointer used after mroute_token released across blocking kmalloc
Summary
add_bw_upcall(:2285) captures mfc under token, releases token(:2301), kmalloc(M_INTWAIT blocks)(:2304), re-acquires token(:2319), writes through stale mfc(:2321-2322). Concurrent del_mfc(:1117) or MRT_DONE(:661) frees mfc during gap. Write to freed heap + dangling bm_mfc deref later. Root (mrouter socket) but kernel-scope.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0306 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-trace confirmed UAF, root-only path | 2.7 KB | β raw |
| README.md | readme | status explanation | 787 B | β raw |
| fix.diff | suggested-fix | hold mroute_token across kmalloc | 1.4 KB | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0306 PoC β UAF in add_bw_upcall
Status: REAL (source-trace confirmed), not reproduced at runtime
The bug is a genuine use-after-free confirmed by source trace of
sys/net/ip_mroute/ip_mroute.c:2285-2326. It is not compiled
into the default GENERIC kernel (options MROUTING required) and
is root-only (requires SYSCAP_NONET_RAW for the raw IGMP
socket needed by MRT_INIT).
No runtime PoC is provided because:
1. The code is not in the default kernel.
2. The race window is the M_INTWAIT kmalloc duration β too narrow
to reliably win without memory-pressure grooming.
3. The entire multicast routing API requires root.
Fix
See fix.diff β holds mroute_token across the kmalloc to
prevent concurrent del_mfc()/MRT_DONE from freeing mfc.
DF-0306 β UAF in add_bw_upcall: mfc pointer used after mroute_token released
Verdict: REAL (source-trace confirmed) β root-only path, not unpriv-escalatable
Mechanism
add_bw_upcall() in sys/net/ip_mroute/ip_mroute.c:2285-2326:
2285: lwkt_gettoken(&mroute_token); 2286: mfc = mfc_find(src, dst); // captures mfc pointer ... 2301: lwkt_reltoken(&mroute_token); // β releases token 2304: x = kmalloc(sizeof(*x), M_BWMETER, M_INTWAIT); // can block ... 2319: lwkt_gettoken(&mroute_token); // re-acquires token 2320: x->bm_mfc = mfc; // β stale mfc write 2321: x->bm_mfc_next = mfc->mfc_bw_meter; // β stale mfc deref 2322: mfc->mfc_bw_meter = x; // β stale mfc write
During the token-released gap (lines 2301β2319), a concurrent
del_mfc() or MRT_DONE can free mfc. The subsequent writes
through the stale mfc pointer are a use-after-free (write to
freed heap + dangling pointer installation).
Privilege requirement
The multicast routing API (MRT_INIT and all subsequent MRT_*
setsockopts) requires a raw IGMP socket, which requires
SYSCAP_NONET_RAW (root). See:
- sys/netinet/raw_ip.c:473 β caps_priv_check(ai->p_ucred, SYSCAP_NONET_RAW)
- sys/net/ip_mroute/ip_mroute.c:371 β if (so != ip_mrouter && sopt->sopt_name != MRT_INIT) return EPERM;
- sys/conf/files:net/ip_mroute/ip_mroute.c optional mrouting β not even compiled into GENERIC
This is a valid hard blocker for unprivileged escalation: the write is reachable only from an already-root context (a multicast routing daemon). rootβkernel is game-over by definition.
Reproduction status
- Source trace: confirmed β the UAF pattern is unambiguous.
- The code is not compiled into the default GENERIC kernel
(requires
options MROUTING). - Even with MROUTING, the race window is the
M_INTWAITkmalloc duration (microseconds unless under memory pressure), making reliable triggering very difficult without memory-pressure grooming. - Not testable from an unprivileged user under any condition.
Fix
fix.diff β hold mroute_token continuously across the kmalloc,
matching the existing pattern at ip_mroute.c:1055 (add_mfc does the
same: gettoken β kmalloc M_INTWAIT β reltoken). Also switch to
M_NULLOK so failure is handled gracefully.
Impact
rootβkernel UAF write. In a deployment where mrouted/pimd runs
as root, a local attacker controlling the mrouter daemon (or racing
it from root) could corrupt kernel heap. Realistic impact ceiling:
root-operated daemon compromise β kernel privilege escalation beyond
the daemon's sandbox. Low practical risk since rootβkernel is already
high-impact.
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. add_bw_upcall mfc UAF across M_INTWAIT kmalloc gap. ip_mroute not in GENERIC, root-only.
No comments yet.