[PATCH OLK-6.6 0/2] net: Fix CVE-2026-53264
net: Fix CVE-2026-53264 Dong Chenchen (1): net: Fix kabi breakage of struct tc_action Jamal Hadi Salim (1): net/sched: act_api: use RCU with deferred freeing for action lifecycle include/net/act_api.h | 7 +++++++ net/sched/act_api.c | 26 ++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) -- 2.25.1
From: Jamal Hadi Salim <jhs@mojatatu.com> stable inclusion from stable-v6.6.143 commit 8b136f18ac4b2ace5aaad3305b3f8a5d8165a009 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15950 CVE: CVE-2026-53264 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 5057e1aca011e51ef51498c940ef96f3d3e8a305 ] When NEWTFILTER and DELFILTER are run concurrently it is possible to create a race with an associated action. Let's illustrate with CPU0 running NEWTFILTER and CPU1 running DELFILTER: 0: mutex_lock() <-- holds the idr lock 0: rcu_read_lock() 0: p = idr_find(idr, index) <-- action p is valid (RCU protects IDR) 0: mutex_unlock() <-- releases the idr lock 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held 1: idr_remove(idr, index) <-- Action removed from IDR 1: mutex_unlock() <-- mutex released allowing us to delete the action 1: tcf_action_cleanup(p); kfree(p) <-- Kfrees p immediately, no deferral 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- ouch, UAF p points to freed memory This patch fixes the race condition between NEWTFILTER and DELFILTER by adding struct rcu_head to tc_action used in the deferral and introducing a call_rcu() in the delete path to defer the final kfree(). Note: this is a revert of commit d7fb60b9cafb ("net_sched: get rid of tcfa_rcu") but also modernization/simplification to directly use kfree_rcu(). Let's illustrate the new restored code path: 0: rcu_read_lock() 1: refcount_dec_and_mutex_lock() <-- refcnt 1->0, mutex held 1: idr_remove(idr, index) 1: mutex_unlock() 1: call_rcu(&p->tcfa_rcu, tcf_action_rcu_free) <-- defer kfree after grace period 0: p = idr_find(idr, index) 0: refcount_inc_not_zero(&p->tcfa_refcnt) <-- fails, refcnt already 0 1: rcu_read_unlock() <-- release so freeing can run after grace period After CPU1 calls idr_remove(), the object is no longer reachable through the IDR. CPU0's subsequent idr_find() will return NULL, and even if it still held a stale pointer, the immediate kfree() is now deferred until after the RCU grace period, so no UAF can occur. Fixes: d7fb60b9cafb ("net_sched: get rid of tcfa_rcu") Suggested-by: Jakub Kicinski <kuba@kernel.org> Reported-by: Kyle Zeng <kylebot@openai.com> Tested-by: Victor Nogueira <victor@mojatatu.com> Tested-by: syzbot@syzkaller.appspotmail.com Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Tested-by: Kyle Zeng <kylebot@openai.com> Reviewed-by: Pedro Tammela <pctammela@mojatatu.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Victor Nogueira <victor@mojatatu.com> Link: https://patch.msgid.link/20260531160812.68020-1-jhs@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> --- include/net/act_api.h | 1 + net/sched/act_api.c | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 8db6994c90ee..56f49351fd51 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -42,6 +42,7 @@ struct tc_action { struct tc_cookie __rcu *user_cookie; struct tcf_chain __rcu *goto_chain; u32 tcfa_flags; + struct rcu_head tcfa_rcu; u8 hw_stats; u8 used_hw_stats; bool used_hw_stats_valid; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index e509ac28c492..bed04ae3003c 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -112,11 +112,6 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action, } EXPORT_SYMBOL(tcf_action_set_ctrlact); -/* XXX: For standalone actions, we don't need a RCU grace period either, because - * actions are always connected to filters and filters are already destroyed in - * RCU callbacks, so after a RCU grace period actions are already disconnected - * from filters. Readers later can not find us. - */ static void free_tcf(struct tc_action *p) { struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1); @@ -129,7 +124,7 @@ static void free_tcf(struct tc_action *p) if (chain) tcf_chain_put_by_act(chain); - kfree(p); + kfree_rcu(p, tcfa_rcu); } static void offload_action_hw_count_set(struct tc_action *act, -- 2.25.1
Offering: HULK hulk inclusion category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15950 CVE: CVE-2026-53264 -------------------------------- Add struct tc_action_rcu to fix kabi breakage of struct tc_action. Fixes: 5057e1aca011 ("net/sched: act_api: use RCU with deferred freeing for action lifecycle") Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> --- include/net/act_api.h | 8 +++++++- net/sched/act_api.c | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 56f49351fd51..93935a2e0b0f 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -20,6 +20,7 @@ struct tcf_idrinfo { }; struct tc_action_ops; +struct tc_action_rcu; struct tc_action { const struct tc_action_ops *ops; @@ -31,6 +32,7 @@ struct tc_action { atomic_t tcfa_bindcnt; int tcfa_action; struct tcf_t tcfa_tm; + KABI_FILL_HOLE(struct tc_action_rcu *tcfa_rcu) struct gnet_stats_basic_sync tcfa_bstats; struct gnet_stats_basic_sync tcfa_bstats_hw; struct gnet_stats_queue tcfa_qstats; @@ -42,7 +44,6 @@ struct tc_action { struct tc_cookie __rcu *user_cookie; struct tcf_chain __rcu *goto_chain; u32 tcfa_flags; - struct rcu_head tcfa_rcu; u8 hw_stats; u8 used_hw_stats; bool used_hw_stats_valid; @@ -58,6 +59,11 @@ struct tc_action { #define tcf_rate_est common.tcfa_rate_est #define tcf_lock common.tcfa_lock +struct tc_action_rcu { + struct tc_action *action; + struct rcu_head rcu; +}; + #define TCA_ACT_HW_STATS_ANY (TCA_ACT_HW_STATS_IMMEDIATE | \ TCA_ACT_HW_STATS_DELAYED) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index bed04ae3003c..b29d1f34a6d4 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -112,9 +112,18 @@ struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action, } EXPORT_SYMBOL(tcf_action_set_ctrlact); +static void tc_action_free_rcu(struct rcu_head *p) +{ + struct tc_action_rcu *ta = container_of(p, struct tc_action_rcu, rcu); + + kfree(ta->action); + kfree(ta); +} + static void free_tcf(struct tc_action *p) { struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1); + struct tc_action_rcu *ta = p->tcfa_rcu; free_percpu(p->cpu_bstats); free_percpu(p->cpu_bstats_hw); @@ -124,7 +133,7 @@ static void free_tcf(struct tc_action *p) if (chain) tcf_chain_put_by_act(chain); - kfree_rcu(p, tcfa_rcu); + call_rcu(&ta->rcu, tc_action_free_rcu); } static void offload_action_hw_count_set(struct tc_action *act, @@ -731,10 +740,16 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, { struct tc_action *p = kzalloc(ops->size, GFP_KERNEL); struct tcf_idrinfo *idrinfo = tn->idrinfo; + struct tc_action_rcu *ta; int err = -ENOMEM; if (unlikely(!p)) return -ENOMEM; + + ta = kzalloc(sizeof(*ta), GFP_KERNEL); + if (unlikely(!ta)) + goto err0; + refcount_set(&p->tcfa_refcnt, 1); if (bind) atomic_set(&p->tcfa_bindcnt, 1); @@ -758,6 +773,8 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, p->tcfa_tm.lastuse = jiffies; p->tcfa_tm.firstuse = 0; p->tcfa_flags = flags; + p->tcfa_rcu = ta; + ta->action = p; if (est) { err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, &p->tcfa_rate_est, @@ -778,6 +795,8 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, err2: free_percpu(p->cpu_bstats); err1: + kfree(ta); +err0: kfree(p); return err; } -- 2.25.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/24899 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/T6O... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/24899 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/T6O...
participants (2)
-
Dong Chenchen -
patchwork bot