On Thu, 28 May 2026 16:08:45 +0000 Tristan Madani wrote:
net_shaper_flush() frees shaper objects with plain kfree() after
xa_erase(), but net_shaper_nl_get_doit() and net_shaper_nl_get_dumpit()
read shaper objects under rcu_read_lock() via xa_load(). This creates a
use-after-free window where an RCU reader may still hold a pointer to a
shaper object that has been freed.
The race is:
CPU 0 (reader) CPU 1 (flush/unregister)
rcu_read_lock()
shaper = xa_load(...) xa_lock()
// shaper points to valid obj __xa_erase(...)
kfree(shaper) <- frees immediately
net_shaper_fill_one(shaper) xa_unlock()
// use-after-free
rcu_read_unlock()
Other code paths in the same file already use kfree_rcu() correctly
(net_shaper_pre_insert error path, net_shaper_notify_down,
net_shaper_cap_pair_update, and net_shaper_rollback as of commit
b8d7519352ba). The struct net_shaper already contains an rcu_head field.
Fix by replacing kfree() with kfree_rcu() in net_shaper_flush() to
defer freeing until after the RCU grace period.
Found by source code audit.
No, the device is fully invisible at this point.
Please don't send fixes unless you can actually trigger the crash.
--
pw-bot: reject
pv-bot: slop