From e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 7 Sep 2026 21:04:05 +0200 Subject: 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 --- net/netfilter/nf_flow_table_core.c | 12 ++++++++++-- 1 file 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); -- cgit v1.2.3