FAILED: patch "[PATCH] ieee802154: hwsim: serialize pib updates to fix double-free" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 979d5b8de8ed4e1f997aef12da5694b99be7b871
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091659-marry-gender-6432@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 979d5b8de8ed4e1f997aef12da5694b99be7b871 Mon Sep 17 00:00:00 2001
From: David Carlier <[email protected]>
Date: Thu, 9 Jul 2026 23:18:58 +0100
Subject: [PATCH] ieee802154: hwsim: serialize pib updates to fix double-free
hwsim_update_pib() does an unserialized read-swap-free of phy->pib:
pib_old = rtnl_dereference(phy->pib); ... rcu_assign_pointer(phy->pib, pib); kfree_rcu(pib_old, rcu);
It assumes the RTNL is held, but ->set_channel is not always called under it: the mac802154 scan worker changes channels via drv_set_channel() without the RTNL. Such an update can race an RTNL-held one on the same phy; both read the same pib_old and both kfree_rcu() it, double-freeing the object. With SLUB percpu sheaves batching kfree_rcu(), this surfaces as a KASAN invalid-free in rcu_free_sheaf().
struct hwsim_phy has no lock for pib. Add one and make the swap atomic with rcu_replace_pointer() under it, dropping the misleading rtnl_dereference().
drivers/net/ieee802154/mac802154_hwsim.c +7 -3
@@ -72,6 +72,8 @@ struct hwsim_phy {struct ieee802154_hw *hw;u32 idx; +/* Serializes phy->pib_updates. */ +spinlock_t pib_lock;struct hwsim_pib __rcu *pib;bool suspended;
@@ -102,8 +104,6 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel,if (!pib)return -ENOMEM ; - pib_old =rtnl_dereference (phy->pib); - pib->page = page; pib->channel = channel; pib->filt.short_addr = filt->short_addr;
@@ -112,7 +112,10 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel, pib->filt.pan_coord = filt->pan_coord; pib->filt_level = filt_level; -rcu_assign_pointer (phy->pib, pib); +spin_lock_bh (&phy->pib_lock); + pib_old =rcu_replace_pointer (phy->pib, pib, +lockdep_is_held (&phy->pib_lock)); +spin_unlock_bh (&phy->pib_lock);kfree_rcu (pib_old, rcu);return 0 ; }
@@ -952,6 +955,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev, goto err_pib; } +spin_lock_init (&phy->pib_lock); pib->channel =13 ; pib->filt.short_addr =cpu_to_le16 (IEEE802154_ADDR_BROADCAST ); pib->filt.pan_id =cpu_to_le16 (IEEE802154_PANID_BROADCAST );
Sasha Levin
maintainerPATCH 1/1 ieee802154: hwsim: serialize pib updates to fix double-free
From: David Carlier <[email protected]>
[ Upstream commit 979d5b8de8ed4e1f997aef12da5694b99be7b871 ]
hwsim_update_pib() does an unserialized read-swap-free of phy->pib:
pib_old = rtnl_dereference(phy->pib); ... rcu_assign_pointer(phy->pib, pib); kfree_rcu(pib_old, rcu);
It assumes the RTNL is held, but ->set_channel is not always called under it: the mac802154 scan worker changes channels via drv_set_channel() without the RTNL. Such an update can race an RTNL-held one on the same phy; both read the same pib_old and both kfree_rcu() it, double-freeing the object. With SLUB percpu sheaves batching kfree_rcu(), this surfaces as a KASAN invalid-free in rcu_free_sheaf().
struct hwsim_phy has no lock for pib. Add one and make the swap atomic with rcu_replace_pointer() under it, dropping the misleading rtnl_dereference().
--- drivers/net/ieee802154/mac802154_hwsim.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/net/ieee802154/mac802154_hwsim.c +7 -2
@@ -69,6 +69,8 @@ struct hwsim_phy {struct ieee802154_hw *hw;u32 idx; +/* Serializes phy->pib_updates. */ +spinlock_t pib_lock;struct hwsim_pib __rcu *pib;bool suspended;
@@ -100,8 +102,10 @@ static int hwsim_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel) pib->page = page; pib->channel = channel; - pib_old =rtnl_dereference (phy->pib); -rcu_assign_pointer (phy->pib, pib); +spin_lock_bh (&phy->pib_lock); + pib_old =rcu_replace_pointer (phy->pib, pib, +lockdep_is_held (&phy->pib_lock)); +spin_unlock_bh (&phy->pib_lock);kfree_rcu (pib_old, rcu);return 0 ; }
@@ -788,6 +792,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev, goto err_pib; } +spin_lock_init (&phy->pib_lock); pib->channel =13 ;rcu_assign_pointer (phy->pib, pib); phy->idx = idx;
Signature · 1 line
2.53.0