[PATCH OLK-6.6] netfilter: nf_tables: use list_del_rcu for netlink hooks
From: Florian Westphal <fw@strlen.de> mainline inclusion from mainline-v7.1-rc2 commit f3224ee463f8f6f6ced7dcdf6081add4f8128527 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15588 CVE: CVE-2026-46324 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- nft_netdev_unregister_hooks and __nft_unregister_flowtable_net_hooks need to use list_del_rcu(), this list can be walked by concurrent dumpers. Add a new helper and use it consistently. Fixes: f9a43007d3f7 ("netfilter: nf_tables: double hook unregistration in netns path") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Conflicts: net/netfilter/nf_tables_api.c [commit 73319a8ee18b ("netfilter: nf_tables: Have a list of nf_hook_ops in nft_hook") introduced the ops_list structure and __nft_netdev_hook_free_rcu() helper which are not present in OLK-6.6. Adapted to use the single hook->ops and existing kfree_rcu()-based nft_netdev_hook_free_rcu() helper instead.] Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> --- net/netfilter/nf_tables_api.c | 38 +++++++++++++++-------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 919be34ac7a0..8602dc3dfe08 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -333,6 +333,12 @@ static void nft_netdev_hook_free_rcu(struct nft_hook *hook) kfree_rcu(hook, rcu); } +static void nft_netdev_hook_unlink_free_rcu(struct nft_hook *hook) +{ + list_del_rcu(&hook->list); + nft_netdev_hook_free_rcu(hook); +} + static void nft_netdev_unregister_hooks(struct net *net, struct list_head *hook_list, bool release_netdev) @@ -341,10 +347,8 @@ static void nft_netdev_unregister_hooks(struct net *net, list_for_each_entry_safe(hook, next, hook_list, list) { nf_unregister_net_hook(net, &hook->ops); - if (release_netdev) { - list_del(&hook->list); - nft_netdev_hook_free_rcu(hook); - } + if (release_netdev) + nft_netdev_hook_unlink_free_rcu(hook); } } @@ -2106,10 +2110,8 @@ void nf_tables_chain_destroy(struct nft_chain *chain) if (nft_base_chain_netdev(table->family, basechain->ops.hooknum)) { list_for_each_entry_safe(hook, next, - &basechain->hook_list, list) { - list_del_rcu(&hook->list); - nft_netdev_hook_free_rcu(hook); - } + &basechain->hook_list, list) + nft_netdev_hook_unlink_free_rcu(hook); } module_put(basechain->type->owner); if (rcu_access_pointer(basechain->stats)) { @@ -2784,6 +2786,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, list_for_each_entry_safe(h, next, &hook.list, list) { if (unregister) nf_unregister_net_hook(ctx->net, &h->ops); + /* hook.list is on stack, no need for list_del_rcu() */ list_del(&h->list); nft_netdev_hook_free_rcu(h); } @@ -8495,10 +8498,8 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net, nf_unregister_net_hook(net, &hook->ops); flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_UNBIND); - if (release_netdev) { - list_del(&hook->list); - nft_netdev_hook_free_rcu(hook); - } + if (release_netdev) + nft_netdev_hook_unlink_free_rcu(hook); } } @@ -8557,8 +8558,7 @@ static int nft_register_flowtable_net_hooks(struct net *net, break; nft_unregister_flowtable_hook(net, flowtable, hook); - list_del_rcu(&hook->list); - nft_netdev_hook_free_rcu(hook); + nft_netdev_hook_unlink_free_rcu(hook); } return err; @@ -8655,8 +8655,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh, list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) { if (unregister) nft_unregister_flowtable_hook(ctx->net, flowtable, hook); - list_del_rcu(&hook->list); - nft_netdev_hook_free_rcu(hook); + nft_netdev_hook_unlink_free_rcu(hook); } return err; @@ -9149,13 +9148,8 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx, static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) { - struct nft_hook *hook, *next; - flowtable->data.type->free(&flowtable->data); - list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { - list_del_rcu(&hook->list); - nft_netdev_hook_free_rcu(hook); - } + nft_hooks_destroy(&flowtable->hook_list); kfree(flowtable->name); module_put(flowtable->data.type->owner); kfree(flowtable); -- 2.43.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/24105 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KW7... 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/24105 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KW7...
participants (2)
-
patchwork bot -
superdcc97@163.com