CVE-2026-72404: tipc: fix UAF in cleanup_bearer() due to premature dst_cache_destroy()
In the Linux kernel, the following vulnerability has been resolved:
tipc: fix UAF in cleanupbearer() due to premature dstcachedestroy()
TIPC UDP media bearer teardown calls dstcachedestroy() on its replicast caches before calling synchronizenet() to wait for concurrent RCU readers (transmitters) to finish:
static void cleanupbearer(struct workstruct work) { ... listforeachentrysafe(rcast, tmp, &ub->rcast.list, list) { dstcachedestroy(&rcast->dstcache); listdelrcu(&rcast->list); kfreercu(rcast, rcu); } ... dstcachedestroy(&ub->rcast.dstcache); udptunnelsockrelease(ub->sk); synchronizenet(); ... }
This is highly buggy because dstcachedestroy() immediately frees the per-CPU cache memory (freepercpu()) and releases the cached dst entries without any synchronization.
If a concurrent transmitter (e.g., tipcudpxmit()) is running on another CPU under RCU protection, it can call dstcacheget() concurrently, leading to: 1. Use-After-Free on the per-CPU cache pointer itself (crash). 2. "rcuref - imbalanced put()" warning if it attempts to release a dst that was concurrently released by dstcachedestroy().
Furthermore, calling kfree(ub) immediately after synchronizenet() without closing the socket first (or waiting after closing it) leaves a window where a concurrent receiver (tipcudprecv()) could start after synchronizenet(), access ub, and suffer a UAF when kfree(ub) runs.
To fix this, we must defer dstcachedestroy() and kfree(ub) until after we have ensured that no more readers can see the bearer/socket and all existing readers have finished:
1. Defer rcast entry destruction (both dstcachedestroy() and kfree()) to an RCU callback using callrcuhurry(). Using callrcuhurry() ensures the dst entries are released quickly.
2. Release the bearer socket using udptunnelsockrelease() (stops new receive readers).
3. Call synchronizenet() to wait for all outstanding RCU readers (both transmit and receive) to finish.
4. Now that it is safe, call dstcachedestroy() on the main bearer cache, and free ub.
Note: 3) and 4) can be changed later in net-next to also use callrcuhurry() and get rid of the synchronizenet() latency.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
Linux kernelto a version that resolves this vulnerability.Patch tipc: fix UAF in cleanup_bearer() due to premature dst_cache_destroy() - Configuration
In cleanup_bearer(), stop the bearer socket teardown first via udp_tunnel_sock_release(ub->sk). Then ensure dst_cache_destroy(&rcast->dst_cache) and dst_cache_destroy(&ub->rcast.dst_cache), and destruction/freeing of ub (kfree(ub)) are deferred via an RCU callback (use call_rcu_hurry()) so concurrent RCU readers (e.g., transmitters) cannot hit freed dst/cache pointers.
TIPC UDP media bearer cleanup (cleanup_bearer) dst_cache_destroy() and kfree(ub) timing = defer to RCU callback using call_rcu_hurry() after udp_tunnel_sock_release(ub->sk) - Compensating control
If you must match the legacy logic described for this fix, call synchronize_net() to wait for all outstanding RCU readers (transmitters/receivers) to finish before performing dst cache destruction and freeing per the fixed deferred RCU teardown flow.