Message ID | 20240404104334.1627-6-pablo@netfilter.org (mailing list archive) |
---|---|
State | Accepted |
Commit | 24225011d81b471acc0e1e315b7d9905459a6304 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net,1/6] netfilter: nf_tables: release batch on table validation from abort path | expand |
On Thu, Apr 04, 2024 at 12:43:33PM +0200, Pablo Neira Ayuso wrote: > From: Ziyang Xuan <william.xuanziyang@huawei.com> > > nft_unregister_flowtable_type() within nf_flow_inet_module_exit() can > concurrent with __nft_flowtable_type_get() within nf_tables_newflowtable(). > And thhere is not any protection when iterate over nf_tables_flowtables > list in __nft_flowtable_type_get(). Therefore, there is pertential > data-race of nf_tables_flowtables list entry. > > Use list_for_each_entry_rcu() to iterate over nf_tables_flowtables list > in __nft_flowtable_type_get(), and use rcu_read_lock() in the caller > nft_flowtable_type_get() to protect the entire type query process. Applied to nf, thanks
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1eb51bf24fc2..e02d0ae4f436 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8296,11 +8296,12 @@ static int nft_flowtable_parse_hook(const struct nft_ctx *ctx, return err; } +/* call under rcu_read_lock */ static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family) { const struct nf_flowtable_type *type; - list_for_each_entry(type, &nf_tables_flowtables, list) { + list_for_each_entry_rcu(type, &nf_tables_flowtables, list) { if (family == type->family) return type; } @@ -8312,9 +8313,13 @@ nft_flowtable_type_get(struct net *net, u8 family) { const struct nf_flowtable_type *type; + rcu_read_lock(); type = __nft_flowtable_type_get(family); - if (type != NULL && try_module_get(type->owner)) + if (type != NULL && try_module_get(type->owner)) { + rcu_read_unlock(); return type; + } + rcu_read_unlock(); lockdep_nfnl_nft_mutex_not_held(); #ifdef CONFIG_MODULES