From: wenxu <wenxu@xxxxxxxxx> In the nft_flow_block_chain some devices bind success, but the subsequent device failed. It should unbind the successful devices. Fixes: bbaef955af6e ("netfilter: nf_tables: support for multiple devices per netdev hook") Signed-off-by: wenxu <wenxu@xxxxxxxxx> --- net/netfilter/nf_tables_offload.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index beeb74f..037c6bd 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -322,8 +322,9 @@ static int nft_flow_block_chain(struct nft_base_chain *basechain, { struct net_device *dev; struct nft_hook *hook; - int err; + int err, i; + i = 0; list_for_each_entry(hook, &basechain->hook_list, list) { dev = hook->ops.dev; if (this_dev && this_dev != dev) @@ -333,12 +334,28 @@ static int nft_flow_block_chain(struct nft_base_chain *basechain, err = nft_block_offload_cmd(basechain, dev, cmd); else err = nft_indr_block_offload_cmd(basechain, dev, cmd); - - if (err < 0) - return err; + + if (err < 0) { + if (this_dev) + return err; + else if (cmd == FLOW_BLOCK_BIND) + goto err_unbind; + } + i++; } return 0; + +err_unbind: + list_for_each_entry(hook, &basechain->hook_list, list) { + if (i-- <= 0) + break; + + dev = hook->ops.dev; + nft_flow_block_chain(basechain, dev, FLOW_BLOCK_UNBIND); + } + + return err; } static int nft_flow_offload_chain(struct nft_chain *chain, u8 *ppolicy, -- 1.8.3.1