Skip to content

Commit 044bdde

Browse files
ummakynesmehmetb0
authored andcommitted
netfilter: nf_tables: imbalance in flowtable binding
BugLink: https://bugs.launchpad.net/bugs/2106770 [ Upstream commit 13210fc ] 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 <[email protected]> Tested-by: Phil Sutter <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Manuel Diewald <[email protected]> Signed-off-by: Mehmet Basaran <[email protected]>
1 parent b2acfd4 commit 044bdde

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
@@ -8491,13 +8491,16 @@ static void nft_unregister_flowtable_hook(struct net *net,
84918491
}
84928492

84938493
static void __nft_unregister_flowtable_net_hooks(struct net *net,
8494+
struct nft_flowtable *flowtable,
84948495
struct list_head *hook_list,
84958496
bool release_netdev)
84968497
{
84978498
struct nft_hook *hook, *next;
84988499

84998500
list_for_each_entry_safe(hook, next, hook_list, list) {
85008501
nf_unregister_net_hook(net, &hook->ops);
8502+
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
8503+
FLOW_BLOCK_UNBIND);
85018504
if (release_netdev) {
85028505
list_del(&hook->list);
85038506
kfree_rcu(hook, rcu);
@@ -8506,9 +8509,10 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net,
85068509
}
85078510

85088511
static void nft_unregister_flowtable_net_hooks(struct net *net,
8512+
struct nft_flowtable *flowtable,
85098513
struct list_head *hook_list)
85108514
{
8511-
__nft_unregister_flowtable_net_hooks(net, hook_list, false);
8515+
__nft_unregister_flowtable_net_hooks(net, flowtable, hook_list, false);
85128516
}
85138517

85148518
static int nft_register_flowtable_net_hooks(struct net *net,
@@ -9149,8 +9153,6 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
91499153

91509154
flowtable->data.type->free(&flowtable->data);
91519155
list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
9152-
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
9153-
FLOW_BLOCK_UNBIND);
91549156
list_del_rcu(&hook->list);
91559157
kfree_rcu(hook, rcu);
91569158
}
@@ -10515,6 +10517,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1051510517
&nft_trans_flowtable_hooks(trans),
1051610518
trans->msg_type);
1051710519
nft_unregister_flowtable_net_hooks(net,
10520+
nft_trans_flowtable(trans),
1051810521
&nft_trans_flowtable_hooks(trans));
1051910522
} else {
1052010523
list_del_rcu(&nft_trans_flowtable(trans)->list);
@@ -10523,6 +10526,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1052310526
NULL,
1052410527
trans->msg_type);
1052510528
nft_unregister_flowtable_net_hooks(net,
10529+
nft_trans_flowtable(trans),
1052610530
&nft_trans_flowtable(trans)->hook_list);
1052710531
}
1052810532
break;
@@ -10775,11 +10779,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1077510779
case NFT_MSG_NEWFLOWTABLE:
1077610780
if (nft_trans_flowtable_update(trans)) {
1077710781
nft_unregister_flowtable_net_hooks(net,
10782+
nft_trans_flowtable(trans),
1077810783
&nft_trans_flowtable_hooks(trans));
1077910784
} else {
1078010785
nft_use_dec_restore(&trans->ctx.table->use);
1078110786
list_del_rcu(&nft_trans_flowtable(trans)->list);
1078210787
nft_unregister_flowtable_net_hooks(net,
10788+
nft_trans_flowtable(trans),
1078310789
&nft_trans_flowtable(trans)->hook_list);
1078410790
}
1078510791
break;
@@ -11341,7 +11347,8 @@ static void __nft_release_hook(struct net *net, struct nft_table *table)
1134111347
list_for_each_entry(chain, &table->chains, list)
1134211348
__nf_tables_unregister_hook(net, table, chain, true);
1134311349
list_for_each_entry(flowtable, &table->flowtables, list)
11344-
__nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list,
11350+
__nft_unregister_flowtable_net_hooks(net, flowtable,
11351+
&flowtable->hook_list,
1134511352
true);
1134611353
}
1134711354

0 commit comments

Comments
 (0)