mirror of
https://github.com/torvalds/linux.git
synced 2025-08-15 14:11:42 +02:00
netfilter: nf_tables: reject duplicate device on updates
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:78d9f48f7f
("netfilter: nf_tables: add devices to existing flowtable") Fixes:b9703ed44f
("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>
This commit is contained in:
parent
c0a23bbc98
commit
cf5fb87fcd
1 changed files with 30 additions and 0 deletions
|
@ -2803,6 +2803,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
||||||
struct nft_chain *chain = ctx->chain;
|
struct nft_chain *chain = ctx->chain;
|
||||||
struct nft_chain_hook hook = {};
|
struct nft_chain_hook hook = {};
|
||||||
struct nft_stats __percpu *stats = NULL;
|
struct nft_stats __percpu *stats = NULL;
|
||||||
|
struct nftables_pernet *nft_net;
|
||||||
struct nft_hook *h, *next;
|
struct nft_hook *h, *next;
|
||||||
struct nf_hook_ops *ops;
|
struct nf_hook_ops *ops;
|
||||||
struct nft_trans *trans;
|
struct nft_trans *trans;
|
||||||
|
@ -2845,6 +2846,20 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
||||||
if (nft_hook_list_find(&basechain->hook_list, h)) {
|
if (nft_hook_list_find(&basechain->hook_list, h)) {
|
||||||
list_del(&h->list);
|
list_del(&h->list);
|
||||||
nft_netdev_hook_free(h);
|
nft_netdev_hook_free(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 {
|
} else {
|
||||||
|
@ -9060,6 +9075,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
|
||||||
{
|
{
|
||||||
const struct nlattr * const *nla = ctx->nla;
|
const struct nlattr * const *nla = ctx->nla;
|
||||||
struct nft_flowtable_hook flowtable_hook;
|
struct nft_flowtable_hook flowtable_hook;
|
||||||
|
struct nftables_pernet *nft_net;
|
||||||
struct nft_hook *hook, *next;
|
struct nft_hook *hook, *next;
|
||||||
struct nf_hook_ops *ops;
|
struct nf_hook_ops *ops;
|
||||||
struct nft_trans *trans;
|
struct nft_trans *trans;
|
||||||
|
@ -9076,6 +9092,20 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
|
||||||
if (nft_hook_list_find(&flowtable->hook_list, hook)) {
|
if (nft_hook_list_find(&flowtable->hook_list, hook)) {
|
||||||
list_del(&hook->list);
|
list_del(&hook->list);
|
||||||
nft_netdev_hook_free(hook);
|
nft_netdev_hook_free(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue