netfilter: nf_tables_offload: unbind if multi-device binding fails
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 24 Oct 2019 08:30:19 +0000 (10:30 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 26 Oct 2019 10:36:44 +0000 (12:36 +0200)
nft_flow_block_chain() needs to unbind in case of error when performing
the multi-device binding.

Fixes: d54725cd11a5 ("netfilter: nf_tables: support for multiple devices per netdev hook")
Reported-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_offload.c

index d51728affa1c9b690ce930a5e33c506b3cb8a3c2..4e0625cce647eaa70199070a7b3501292ad8beb6 100644 (file)
@@ -336,7 +336,7 @@ static int nft_flow_block_chain(struct nft_base_chain *basechain,
 {
        struct net_device *dev;
        struct nft_hook *hook;
-       int err;
+       int err, i = 0;
 
        list_for_each_entry(hook, &basechain->hook_list, list) {
                dev = hook->ops.dev;
@@ -344,11 +344,26 @@ static int nft_flow_block_chain(struct nft_base_chain *basechain,
                        continue;
 
                err = nft_chain_offload_cmd(basechain, dev, cmd);
-               if (err < 0)
+               if (err < 0 && cmd == FLOW_BLOCK_BIND) {
+                       if (!this_dev)
+                               goto err_flow_block;
+
                        return err;
+               }
+               i++;
        }
 
        return 0;
+
+err_flow_block:
+       list_for_each_entry(hook, &basechain->hook_list, list) {
+               if (i-- <= 0)
+                       break;
+
+               dev = hook->ops.dev;
+               nft_chain_offload_cmd(basechain, dev, FLOW_BLOCK_UNBIND);
+       }
+       return err;
 }
 
 static int nft_flow_offload_chain(struct nft_chain *chain, u8 *ppolicy,