diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-02-01 12:49:00 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-02-02 12:26:42 -0500 |
commit | c7f0030b5b67866c588845abde7bf011de25b98a (patch) | |
tree | 88aa5bcfc07581b764d8db201d356a541c92ead3 | |
parent | ba7cd5d95f25cc6005f687dabdb4e7a6063adda9 (diff) |
netfilter: nft_flow_offload: wait for garbage collector to run after cleanup
If netdevice goes down, then flowtable entries are scheduled to be
removed. Wait for garbage collector to have a chance to run so it can
delete them from the hashtable.
The flush call might sleep, so hold the nfnl mutex from
nft_flow_table_iterate() instead of rcu read side lock. The use of the
nfnl mutex is also implicitly fixing races between updates via nfnetlink
and netdevice event.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/netfilter/nf_tables_api.c | 8 | ||||
-rw-r--r-- | net/netfilter/nft_flow_offload.c | 1 |
2 files changed, 5 insertions, 4 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 0791813a1e7d..07dd1fac78a8 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -5006,13 +5006,13 @@ void nft_flow_table_iterate(struct net *net, | |||
5006 | struct nft_flowtable *flowtable; | 5006 | struct nft_flowtable *flowtable; |
5007 | const struct nft_table *table; | 5007 | const struct nft_table *table; |
5008 | 5008 | ||
5009 | rcu_read_lock(); | 5009 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
5010 | list_for_each_entry_rcu(table, &net->nft.tables, list) { | 5010 | list_for_each_entry(table, &net->nft.tables, list) { |
5011 | list_for_each_entry_rcu(flowtable, &table->flowtables, list) { | 5011 | list_for_each_entry(flowtable, &table->flowtables, list) { |
5012 | iter(&flowtable->data, data); | 5012 | iter(&flowtable->data, data); |
5013 | } | 5013 | } |
5014 | } | 5014 | } |
5015 | rcu_read_unlock(); | 5015 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
5016 | } | 5016 | } |
5017 | EXPORT_SYMBOL_GPL(nft_flow_table_iterate); | 5017 | EXPORT_SYMBOL_GPL(nft_flow_table_iterate); |
5018 | 5018 | ||
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 4503b8dcf9c0..1739ff8ca21f 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c | |||
@@ -208,6 +208,7 @@ static void nft_flow_offload_iterate_cleanup(struct nf_flowtable *flowtable, | |||
208 | void *data) | 208 | void *data) |
209 | { | 209 | { |
210 | nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); | 210 | nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); |
211 | flush_delayed_work(&flowtable->gc_work); | ||
211 | } | 212 | } |
212 | 213 | ||
213 | static int flow_offload_netdev_event(struct notifier_block *this, | 214 | static int flow_offload_netdev_event(struct notifier_block *this, |