Skip to content

Commit 938b1e4

Browse files
committed
netfilter: nf_tables: imbalance in flowtable binding
JIRA: https://issues.redhat.com/browse/RHEL-115630 Upstream Status: commit 13210fc commit 13210fc Author: Pablo Neira Ayuso <pablo@netfilter.org> Date: Thu Jan 2 13:01:13 2025 +0100 netfilter: nf_tables: imbalance in flowtable binding All these cases cause imbalance between BIND and UNBIND calls: - Delete an interface from a flowtable with multiple interfaces - Add a (device to a) flowtable with --check flag - Delete a netns containing a flowtable - In an interactive nft session, create a table with owner flag and flowtable inside, then quit. Fix it by calling FLOW_BLOCK_UNBIND when unregistering hooks, then remove late FLOW_BLOCK_UNBIND call when destroying flowtable. Fixes: ff4bf2f ("netfilter: nf_tables: add nft_unregister_flowtable_hook()") Reported-by: Phil Sutter <phil@nwl.cc> Tested-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent aa60c0b commit 938b1e4

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8117,13 +8117,16 @@ static void nft_unregister_flowtable_hook(struct net *net,
81178117
}
81188118

81198119
static void __nft_unregister_flowtable_net_hooks(struct net *net,
8120+
struct nft_flowtable *flowtable,
81208121
struct list_head *hook_list,
81218122
bool release_netdev)
81228123
{
81238124
struct nft_hook *hook, *next;
81248125

81258126
list_for_each_entry_safe(hook, next, hook_list, list) {
81268127
nf_unregister_net_hook(net, &hook->ops);
8128+
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
8129+
FLOW_BLOCK_UNBIND);
81278130
if (release_netdev) {
81288131
list_del(&hook->list);
81298132
kfree_rcu(hook, rcu);
@@ -8132,9 +8135,10 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net,
81328135
}
81338136

81348137
static void nft_unregister_flowtable_net_hooks(struct net *net,
8138+
struct nft_flowtable *flowtable,
81358139
struct list_head *hook_list)
81368140
{
8137-
__nft_unregister_flowtable_net_hooks(net, hook_list, false);
8141+
__nft_unregister_flowtable_net_hooks(net, flowtable, hook_list, false);
81388142
}
81398143

81408144
static int nft_register_flowtable_net_hooks(struct net *net,
@@ -8760,8 +8764,6 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
87608764

87618765
flowtable->data.type->free(&flowtable->data);
87628766
list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
8763-
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
8764-
FLOW_BLOCK_UNBIND);
87658767
list_del_rcu(&hook->list);
87668768
kfree_rcu(hook, rcu);
87678769
}
@@ -10061,6 +10063,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1006110063
&nft_trans_flowtable_hooks(trans),
1006210064
trans->msg_type);
1006310065
nft_unregister_flowtable_net_hooks(net,
10066+
nft_trans_flowtable(trans),
1006410067
&nft_trans_flowtable_hooks(trans));
1006510068
} else {
1006610069
list_del_rcu(&nft_trans_flowtable(trans)->list);
@@ -10069,6 +10072,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1006910072
&nft_trans_flowtable(trans)->hook_list,
1007010073
trans->msg_type);
1007110074
nft_unregister_flowtable_net_hooks(net,
10075+
nft_trans_flowtable(trans),
1007210076
&nft_trans_flowtable(trans)->hook_list);
1007310077
}
1007410078
break;
@@ -10312,11 +10316,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1031210316
case NFT_MSG_NEWFLOWTABLE:
1031310317
if (nft_trans_flowtable_update(trans)) {
1031410318
nft_unregister_flowtable_net_hooks(net,
10319+
nft_trans_flowtable(trans),
1031510320
&nft_trans_flowtable_hooks(trans));
1031610321
} else {
1031710322
nft_use_dec_restore(&trans->ctx.table->use);
1031810323
list_del_rcu(&nft_trans_flowtable(trans)->list);
1031910324
nft_unregister_flowtable_net_hooks(net,
10325+
nft_trans_flowtable(trans),
1032010326
&nft_trans_flowtable(trans)->hook_list);
1032110327
}
1032210328
break;
@@ -10860,7 +10866,8 @@ static void __nft_release_hook(struct net *net, struct nft_table *table)
1086010866
list_for_each_entry(chain, &table->chains, list)
1086110867
__nf_tables_unregister_hook(net, table, chain, true);
1086210868
list_for_each_entry(flowtable, &table->flowtables, list)
10863-
__nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list,
10869+
__nft_unregister_flowtable_net_hooks(net, flowtable,
10870+
&flowtable->hook_list,
1086410871
true);
1086510872
}
1086610873

0 commit comments

Comments
 (0)