From: Zhan Jun hwsim_del() queued the current PIB for RCU freeing before calling ieee802154_unregister_hw(). Unregistering the hardware closes its interfaces and aborts an in-progress scan; scan cleanup calls set_channel(), which replaces the same phy->pib and queues the old object for RCU freeing again. KASAN then reports an invalid free in hwsim_update_pib(). Unregister the hardware first, then atomically detach the final PIB under pib_lock and queue only that current object for RCU freeing. This lets all driver callbacks finish before the PIB is reclaimed and avoids freeing a PIB that was already replaced during teardown. Reported-by: syzbot+8a8482d4c33cc58babb4@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/6af5f575.b350cda4.2b6a63.0000.GAE@google.com/T/ Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb") Cc: stable@vger.kernel.org Signed-off-by: Zhan Jun Signed-off-by: Yichong Chen --- drivers/net/ieee802154/mac802154_hwsim.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c index a9bd1555d2dc..a65ae2afb789 100644 --- a/drivers/net/ieee802154/mac802154_hwsim.c +++ b/drivers/net/ieee802154/mac802154_hwsim.c @@ -1008,12 +1008,16 @@ static void hwsim_del(struct hwsim_phy *phy) list_del_rcu(&e->list); hwsim_free_edge(e); } - pib = rcu_dereference(phy->pib); rcu_read_unlock(); + ieee802154_unregister_hw(phy->hw); + + spin_lock_bh(&phy->pib_lock); + pib = rcu_replace_pointer(phy->pib, NULL, + lockdep_is_held(&phy->pib_lock)); + spin_unlock_bh(&phy->pib_lock); kfree_rcu(pib, rcu); - ieee802154_unregister_hw(phy->hw); ieee802154_free_hw(phy->hw); } -- 2.51.0