Skip to content

Commit 608172b

Browse files
ummakynesjfvogel
authored andcommitted
netfilter: nf_tables: imbalance in flowtable binding
[ 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]> (cherry picked from commit 2e87c203b72f08e4c49ac3c565ad7995e7689252) Signed-off-by: Jack Vogel <[email protected]>
1 parent 547f7af commit 608172b

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
@@ -8565,13 +8565,16 @@ static void nft_unregister_flowtable_hook(struct net *net,
85658565
}
85668566

85678567
static void __nft_unregister_flowtable_net_hooks(struct net *net,
8568+
struct nft_flowtable *flowtable,
85688569
struct list_head *hook_list,
85698570
bool release_netdev)
85708571
{
85718572
struct nft_hook *hook, *next;
85728573

85738574
list_for_each_entry_safe(hook, next, hook_list, list) {
85748575
nf_unregister_net_hook(net, &hook->ops);
8576+
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
8577+
FLOW_BLOCK_UNBIND);
85758578
if (release_netdev) {
85768579
list_del(&hook->list);
85778580
kfree_rcu(hook, rcu);
@@ -8580,9 +8583,10 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net,
85808583
}
85818584

85828585
static void nft_unregister_flowtable_net_hooks(struct net *net,
8586+
struct nft_flowtable *flowtable,
85838587
struct list_head *hook_list)
85848588
{
8585-
__nft_unregister_flowtable_net_hooks(net, hook_list, false);
8589+
__nft_unregister_flowtable_net_hooks(net, flowtable, hook_list, false);
85868590
}
85878591

85888592
static int nft_register_flowtable_net_hooks(struct net *net,
@@ -9223,8 +9227,6 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
92239227

92249228
flowtable->data.type->free(&flowtable->data);
92259229
list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
9226-
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
9227-
FLOW_BLOCK_UNBIND);
92289230
list_del_rcu(&hook->list);
92299231
kfree_rcu(hook, rcu);
92309232
}
@@ -10622,6 +10624,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1062210624
&nft_trans_flowtable_hooks(trans),
1062310625
trans->msg_type);
1062410626
nft_unregister_flowtable_net_hooks(net,
10627+
nft_trans_flowtable(trans),
1062510628
&nft_trans_flowtable_hooks(trans));
1062610629
} else {
1062710630
list_del_rcu(&nft_trans_flowtable(trans)->list);
@@ -10630,6 +10633,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1063010633
NULL,
1063110634
trans->msg_type);
1063210635
nft_unregister_flowtable_net_hooks(net,
10636+
nft_trans_flowtable(trans),
1063310637
&nft_trans_flowtable(trans)->hook_list);
1063410638
}
1063510639
break;
@@ -10901,11 +10905,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1090110905
case NFT_MSG_NEWFLOWTABLE:
1090210906
if (nft_trans_flowtable_update(trans)) {
1090310907
nft_unregister_flowtable_net_hooks(net,
10908+
nft_trans_flowtable(trans),
1090410909
&nft_trans_flowtable_hooks(trans));
1090510910
} else {
1090610911
nft_use_dec_restore(&table->use);
1090710912
list_del_rcu(&nft_trans_flowtable(trans)->list);
1090810913
nft_unregister_flowtable_net_hooks(net,
10914+
nft_trans_flowtable(trans),
1090910915
&nft_trans_flowtable(trans)->hook_list);
1091010916
}
1091110917
break;
@@ -11498,7 +11504,8 @@ static void __nft_release_hook(struct net *net, struct nft_table *table)
1149811504
list_for_each_entry(chain, &table->chains, list)
1149911505
__nf_tables_unregister_hook(net, table, chain, true);
1150011506
list_for_each_entry(flowtable, &table->flowtables, list)
11501-
__nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list,
11507+
__nft_unregister_flowtable_net_hooks(net, flowtable,
11508+
&flowtable->hook_list,
1150211509
true);
1150311510
}
1150411511

0 commit comments

Comments
 (0)