diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-11-15 11:36:35 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-11-15 23:44:54 +0100 |
commit | ff4bf2f42a40e7dff28379f085b64df322c70b45 (patch) | |
tree | 11c5faa93078b1aa66bd9e1738282821e341a356 /net | |
parent | d7c03a9f5c2577b29a7699bbaa1c1cbcfb56afd3 (diff) | |
download | linux-ff4bf2f42a40e7dff28379f085b64df322c70b45.tar.bz2 |
netfilter: nf_tables: add nft_unregister_flowtable_hook()
Unbind flowtable callback if hook is unregistered.
This patch is implicitly fixing the error path of
nf_tables_newflowtable() and nft_flowtable_event().
Fixes: 8bb69f3b2918 ("netfilter: nf_tables: add flowtable offload control plane")
Reported-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_tables_api.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 9340b976d85c..ff04cdc87f76 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5975,16 +5975,22 @@ nft_flowtable_type_get(struct net *net, u8 family) return ERR_PTR(-ENOENT); } +static void nft_unregister_flowtable_hook(struct net *net, + struct nft_flowtable *flowtable, + struct nft_hook *hook) +{ + nf_unregister_net_hook(net, &hook->ops); + flowtable->data.type->setup(&flowtable->data, hook->ops.dev, + FLOW_BLOCK_UNBIND); +} + static void nft_unregister_flowtable_net_hooks(struct net *net, struct nft_flowtable *flowtable) { struct nft_hook *hook; - list_for_each_entry(hook, &flowtable->hook_list, list) { - nf_unregister_net_hook(net, &hook->ops); - flowtable->data.type->setup(&flowtable->data, hook->ops.dev, - FLOW_BLOCK_UNBIND); - } + list_for_each_entry(hook, &flowtable->hook_list, list) + nft_unregister_flowtable_hook(net, flowtable, hook); } static int nft_register_flowtable_net_hooks(struct net *net, @@ -6030,9 +6036,7 @@ err_unregister_net_hooks: if (i-- <= 0) break; - nf_unregister_net_hook(net, &hook->ops); - flowtable->data.type->setup(&flowtable->data, hook->ops.dev, - FLOW_BLOCK_UNBIND); + nft_unregister_flowtable_hook(net, flowtable, hook); list_del_rcu(&hook->list); kfree_rcu(hook, rcu); } @@ -6139,7 +6143,7 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, return 0; err5: list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { - nf_unregister_net_hook(net, &hook->ops); + nft_unregister_flowtable_hook(net, flowtable, hook); list_del_rcu(&hook->list); kfree_rcu(hook, rcu); } @@ -6484,7 +6488,7 @@ static void nft_flowtable_event(unsigned long event, struct net_device *dev, if (hook->ops.dev != dev) continue; - nf_unregister_net_hook(dev_net(dev), &hook->ops); + nft_unregister_flowtable_hook(dev_net(dev), flowtable, hook); list_del_rcu(&hook->list); kfree_rcu(hook, rcu); break; |