Hi Greg, Sasha,
This batch contains backported fixes for 6.12 -stable.
The following list shows the backported patches:
1) Partial revert of commit dbe85d3115c7e6b5124c8b028f4f602856ea51dd in -stable 6.12, this patch does not exist upstream. This unbreaks old nft userspace binaries which cannot parse this shortened deletion event.
2) cf5fb87fcdaa ("netfilter: nf_tables: reject duplicate device on updates")
Please, apply, Thanks.
Pablo Neira Ayuso (2): Revert "netfilter: nf_tables: Reintroduce shortened deletion notifications" netfilter: nf_tables: reject duplicate device on updates
net/netfilter/nf_tables_api.c | 66 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 34 deletions(-)
This is a partial revert of commit dbe85d3115c7e6b5124c8b028f4f602856ea51dd.
This update breaks old nftables userspace because monitor parser cannot handle this shortened deletion, this patch was added as a Stable-dep:, let's revert it.
Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org --- net/netfilter/nf_tables_api.c | 36 ++--------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3028d388b293..2f3684dcbef8 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1032,12 +1032,6 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, NFTA_TABLE_PAD)) goto nla_put_failure;
- if (event == NFT_MSG_DELTABLE || - event == NFT_MSG_DESTROYTABLE) { - nlmsg_end(skb, nlh); - return 0; - } - if (nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags & NFT_TABLE_F_MASK))) goto nla_put_failure; @@ -1893,13 +1887,6 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, NFTA_CHAIN_PAD)) goto nla_put_failure;
- if (!hook_list && - (event == NFT_MSG_DELCHAIN || - event == NFT_MSG_DESTROYCHAIN)) { - nlmsg_end(skb, nlh); - return 0; - } - if (nft_is_base_chain(chain)) { const struct nft_base_chain *basechain = nft_base_chain(chain); struct nft_stats __percpu *stats; @@ -4685,12 +4672,6 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, NFTA_SET_PAD)) goto nla_put_failure;
- if (event == NFT_MSG_DELSET || - event == NFT_MSG_DESTROYSET) { - nlmsg_end(skb, nlh); - return 0; - } - if (set->flags != 0) if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) goto nla_put_failure; @@ -8021,18 +8002,12 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) || nla_put_string(skb, NFTA_OBJ_NAME, obj->key.name) || - nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), NFTA_OBJ_PAD)) goto nla_put_failure;
- if (event == NFT_MSG_DELOBJ || - event == NFT_MSG_DESTROYOBJ) { - nlmsg_end(skb, nlh); - return 0; - } - - if (nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || + if (nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || + nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) goto nla_put_failure;
@@ -9048,13 +9023,6 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, NFTA_FLOWTABLE_PAD)) goto nla_put_failure;
- if (!hook_list && - (event == NFT_MSG_DELFLOWTABLE || - event == NFT_MSG_DESTROYFLOWTABLE)) { - nlmsg_end(skb, nlh); - return 0; - } - if (nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags))) goto nla_put_failure;
This patch has been queued up for the 6.12 stable tree.
Subject: Revert "netfilter: nf_tables: Reintroduce shortened deletion notifications" Queue: 6.12
Thanks for the backport!
commit cf5fb87fcdaaaafec55dcc0dc5a9e15ead343973 upstream.
A chain/flowtable update with duplicated devices in the same batch is possible. Unfortunately, netdev event path only removes the first device that is found, leaving unregistered the hook of the duplicated device.
Check if a duplicated device exists in the transaction batch, bail out with EEXIST in such case.
WARNING is hit when unregistering the hook:
[49042.221275] WARNING: CPU: 4 PID: 8425 at net/netfilter/core.c:340 nf_hook_entry_head+0xaa/0x150 [49042.221375] CPU: 4 UID: 0 PID: 8425 Comm: nft Tainted: G S 6.16.0+ #170 PREEMPT(full) [...] [49042.221382] RIP: 0010:nf_hook_entry_head+0xaa/0x150
Fixes: 78d9f48f7f44 ("netfilter: nf_tables: add devices to existing flowtable") Fixes: b9703ed44ffb ("netfilter: nf_tables: support for adding new devices to an existing netdev chain") Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Florian Westphal fw@strlen.de --- net/netfilter/nf_tables_api.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2f3684dcbef8..e1c617b48888 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2642,6 +2642,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, struct nft_chain *chain = ctx->chain; struct nft_chain_hook hook = {}; struct nft_stats *stats = NULL; + struct nftables_pernet *nft_net; struct nft_hook *h, *next; struct nf_hook_ops *ops; struct nft_trans *trans; @@ -2682,6 +2683,20 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, if (nft_hook_list_find(&basechain->hook_list, h)) { list_del(&h->list); kfree(h); + continue; + } + + nft_net = nft_pernet(ctx->net); + list_for_each_entry(trans, &nft_net->commit_list, list) { + if (trans->msg_type != NFT_MSG_NEWCHAIN || + trans->table != ctx->table || + !nft_trans_chain_update(trans)) + continue; + + if (nft_hook_list_find(&nft_trans_chain_hooks(trans), h)) { + nft_chain_release_hook(&hook); + return -EEXIST; + } } } } else { @@ -8686,6 +8701,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh, { const struct nlattr * const *nla = ctx->nla; struct nft_flowtable_hook flowtable_hook; + struct nftables_pernet *nft_net; struct nft_hook *hook, *next; struct nft_trans *trans; bool unregister = false; @@ -8701,6 +8717,20 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh, if (nft_hook_list_find(&flowtable->hook_list, hook)) { list_del(&hook->list); kfree(hook); + continue; + } + + nft_net = nft_pernet(ctx->net); + list_for_each_entry(trans, &nft_net->commit_list, list) { + if (trans->msg_type != NFT_MSG_NEWFLOWTABLE || + trans->table != ctx->table || + !nft_trans_flowtable_update(trans)) + continue; + + if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook)) { + err = -EEXIST; + goto err_flowtable_update_hook; + } } }
This patch has been queued up for the 6.12 stable tree.
Subject: netfilter: nf_tables: reject duplicate device on updates Queue: 6.12
Thanks for the backport!
linux-stable-mirror@lists.linaro.org