diff options
| author | Pablo Neira Ayuso <pablo@netfilter.org> | 2026-09-07 21:04:05 +0200 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2026-09-11 13:04:15 +0200 |
| commit | e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d (patch) | |
| tree | b27502ad6dd62dcdc759c94e08279b3ca4f54123 | |
| parent | cbdd39ce42530a193c56beb206a3356cb6d01016 (diff) | |
| download | linux-next-e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d.tar.gz linux-next-e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d.zip | |
netfilter: flowtable: hold reference on ct until flow is released
nf_ct_put() releases the ct->ext area inmediately, the rcu typesafe
semantics also allow to refer to the wrong conntrack from the flowtable
datapath. Hold reference on ct until flow is released after rcu grace
period.
Add rcu_barrier() on module exit path, to ensure pending flow entries
are release before module goes away.
Fixes: 0ff90b6c2034 ("netfilter: nf_flow_offload: fix use-after-free and a resource leak")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
| -rw-r--r-- | net/netfilter/nf_flow_table_core.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 03241d4bfd5e..934c6151f558 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -258,6 +258,14 @@ static void flow_offload_route_release(struct flow_offload *flow) nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_REPLY); } +static void flow_offload_free_rcu(struct rcu_head *rcu_head) +{ + struct flow_offload *flow = container_of(rcu_head, struct flow_offload, rcu_head); + + nf_ct_put(flow->ct); + kfree(flow); +} + void flow_offload_free(struct flow_offload *flow) { switch (flow->type) { @@ -267,8 +275,7 @@ void flow_offload_free(struct flow_offload *flow) default: break; } - nf_ct_put(flow->ct); - kfree_rcu(flow, rcu_head); + call_rcu(&flow->rcu_head, flow_offload_free_rcu); } EXPORT_SYMBOL_GPL(flow_offload_free); @@ -854,6 +861,7 @@ out_pernet: static void __exit nf_flow_table_module_exit(void) { + rcu_barrier(); nf_flow_table_offload_exit(); unregister_pernet_subsys(&nf_flow_table_net_ops); kmem_cache_destroy(flow_offload_cachep); |
