Handling NETDEV_CHANGENAME events has to traverse all chains/flowtables twice, prepare for this. No functional change intended. Signed-off-by: Phil Sutter <phil@xxxxxx> --- Changes since v4: - New patch. --- net/netfilter/nf_tables_api.c | 34 ++++++++++++++++++---------- net/netfilter/nft_chain_filter.c | 38 ++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 74df6048a892..77d0efbad641 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -9363,13 +9363,28 @@ static int nft_flowtable_event(unsigned long event, struct net_device *dev, return 0; } +static int __nf_tables_flowtable_event(unsigned long event, + struct net_device *dev) +{ + struct nftables_pernet *nft_net = nft_pernet(dev_net(dev)); + struct nft_flowtable *flowtable; + struct nft_table *table; + + list_for_each_entry(table, &nft_net->tables, list) { + list_for_each_entry(flowtable, &table->flowtables, list) { + if (nft_flowtable_event(event, dev, flowtable)) + return 1; + } + } + return 0; +} + static int nf_tables_flowtable_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); - struct nft_flowtable *flowtable; struct nftables_pernet *nft_net; - struct nft_table *table; + int ret = NOTIFY_DONE; struct net *net; if (event != NETDEV_REGISTER && @@ -9379,17 +9394,12 @@ static int nf_tables_flowtable_event(struct notifier_block *this, net = dev_net(dev); nft_net = nft_pernet(net); mutex_lock(&nft_net->commit_mutex); - list_for_each_entry(table, &nft_net->tables, list) { - list_for_each_entry(flowtable, &table->flowtables, list) { - if (nft_flowtable_event(event, dev, flowtable)) { - mutex_unlock(&nft_net->commit_mutex); - return NOTIFY_BAD; - } - } - } - mutex_unlock(&nft_net->commit_mutex); - return NOTIFY_DONE; + if (__nf_tables_flowtable_event(event, dev)) + ret = NOTIFY_BAD; + + mutex_unlock(&nft_net->commit_mutex); + return ret; } static struct notifier_block nf_tables_flowtable_notifier = { diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c index b1aa2d469776..073bafdf56c0 100644 --- a/net/netfilter/nft_chain_filter.c +++ b/net/netfilter/nft_chain_filter.c @@ -361,21 +361,14 @@ static int nft_netdev_event(unsigned long event, struct net_device *dev, return 0; } -static int nf_tables_netdev_event(struct notifier_block *this, - unsigned long event, void *ptr) +static int __nf_tables_netdev_event(unsigned long event, struct net_device *dev) { - struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct nft_base_chain *basechain; struct nftables_pernet *nft_net; struct nft_chain *chain; struct nft_table *table; - if (event != NETDEV_REGISTER && - event != NETDEV_UNREGISTER) - return NOTIFY_DONE; - nft_net = nft_pernet(dev_net(dev)); - mutex_lock(&nft_net->commit_mutex); list_for_each_entry(table, &nft_net->tables, list) { if (table->family != NFPROTO_NETDEV && table->family != NFPROTO_INET) @@ -390,15 +383,32 @@ static int nf_tables_netdev_event(struct notifier_block *this, basechain->ops.hooknum != NF_INET_INGRESS) continue; - if (nft_netdev_event(event, dev, basechain)) { - mutex_unlock(&nft_net->commit_mutex); - return NOTIFY_BAD; - } + if (nft_netdev_event(event, dev, basechain)) + return 1; } } - mutex_unlock(&nft_net->commit_mutex); + return 0; +} + +static int nf_tables_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct nftables_pernet *nft_net; + int ret = NOTIFY_DONE; + + if (event != NETDEV_REGISTER && + event != NETDEV_UNREGISTER) + return NOTIFY_DONE; - return NOTIFY_DONE; + nft_net = nft_pernet(dev_net(dev)); + mutex_lock(&nft_net->commit_mutex); + + if (__nf_tables_netdev_event(event, dev)) + ret = NOTIFY_BAD; + + mutex_unlock(&nft_net->commit_mutex); + return ret; } static struct notifier_block nf_tables_netdev_notifier = { -- 2.43.0