mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
mac802154: hold an interface reference across the scan worker
commit234e5e898bupstream. mac802154_scan_worker() captures the scanning sub-interface under RCU and then keeps dereferencing sdata->dev after rcu_read_unlock() and outside the rtnl -- in the failure traces, in mac802154_transmit_beacon_req() (skb->dev = sdata->dev), and in the end_scan cleanup. Nothing keeps that netdev alive across the worker iteration. A concurrent DEL_INTERFACE or PHY removal can unregister the interface once the worker drops the rtnl between its two drv_set_channel() sections. unregister_netdevice() frees the netdev asynchronously from netdev_run_todo() with the rtnl already dropped, so neither holding the rtnl nor the per-PHY IEEE802154_IS_SCANNING flag prevents a stale worker iteration from dereferencing the freed netdev -- a KASAN slab-use-after-free, reachable by racing TRIGGER_SCAN against DEL_INTERFACE (both CAP_NET_ADMIN). Pin the netdev with netdev_hold() while the RCU read lock is still held, and release it at every worker exit. Fixes:57588c7117("mac802154: Handle passive scanning") Cc: stable@vger.kernel.org Signed-off-by: Ibrahim Hashimov <security@auditcode.ai> Link: https://patch.msgid.link/20260721211228.34578-1-security@auditcode.ai Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
896a9512d0
commit
bd7110f0ca
@@ -179,6 +179,7 @@ void mac802154_scan_worker(struct work_struct *work)
|
||||
enum nl802154_scan_types scan_req_type;
|
||||
struct ieee802154_sub_if_data *sdata;
|
||||
unsigned int scan_duration = 0;
|
||||
netdevice_tracker dev_tracker;
|
||||
struct wpan_phy *wpan_phy;
|
||||
u8 scan_req_duration;
|
||||
u8 page, channel;
|
||||
@@ -209,6 +210,14 @@ void mac802154_scan_worker(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sdata->dev is dereferenced below after rcu_read_unlock() and outside
|
||||
* the rtnl, and a concurrent DEL_INTERFACE / PHY teardown can free it
|
||||
* asynchronously from netdev_run_todo(). Pin it with a reference taken
|
||||
* while the RCU read lock is still held, and drop it at every exit.
|
||||
*/
|
||||
netdev_hold(sdata->dev, &dev_tracker, GFP_ATOMIC);
|
||||
|
||||
wpan_phy = scan_req->wpan_phy;
|
||||
scan_req_type = scan_req->type;
|
||||
scan_req_duration = scan_req->duration;
|
||||
@@ -262,12 +271,14 @@ void mac802154_scan_worker(struct work_struct *work)
|
||||
"Scan page %u channel %u for %ums\n",
|
||||
page, channel, jiffies_to_msecs(scan_duration));
|
||||
queue_delayed_work(local->mac_wq, &local->scan_work, scan_duration);
|
||||
netdev_put(sdata->dev, &dev_tracker);
|
||||
return;
|
||||
|
||||
end_scan:
|
||||
rtnl_lock();
|
||||
mac802154_scan_cleanup_locked(local, sdata, false);
|
||||
rtnl_unlock();
|
||||
netdev_put(sdata->dev, &dev_tracker);
|
||||
}
|
||||
|
||||
int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
|
||||
|
||||
Reference in New Issue
Block a user