]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: nft_ct: fix use-after-free in timeout object destroy
authorTuan Do <tuan@calif.io>
Fri, 3 Apr 2026 07:33:17 +0000 (00:33 -0700)
committerFlorian Westphal <fw@strlen.de>
Wed, 8 Apr 2026 11:34:16 +0000 (13:34 +0200)
nft_ct_timeout_obj_destroy() frees the timeout object with kfree()
immediately after nf_ct_untimeout(), without waiting for an RCU grace
period. Concurrent packet processing on other CPUs may still hold
RCU-protected references to the timeout object obtained via
rcu_dereference() in nf_ct_timeout_data().

Add an rcu_head to struct nf_ct_timeout and use kfree_rcu() to defer
freeing until after an RCU grace period, matching the approach already
used in nfnetlink_cttimeout.c.

KASAN report:
 BUG: KASAN: slab-use-after-free in nf_conntrack_tcp_packet+0x1381/0x29d0
 Read of size 4 at addr ffff8881035fe19c by task exploit/80

 Call Trace:
  nf_conntrack_tcp_packet+0x1381/0x29d0
  nf_conntrack_in+0x612/0x8b0
  nf_hook_slow+0x70/0x100
  __ip_local_out+0x1b2/0x210
  tcp_sendmsg_locked+0x722/0x1580
  __sys_sendto+0x2d8/0x320

 Allocated by task 75:
  nft_ct_timeout_obj_init+0xf6/0x290
  nft_obj_init+0x107/0x1b0
  nf_tables_newobj+0x680/0x9c0
  nfnetlink_rcv_batch+0xc29/0xe00

 Freed by task 26:
  nft_obj_destroy+0x3f/0xa0
  nf_tables_trans_destroy_work+0x51c/0x5c0
  process_one_work+0x2c4/0x5a0

Fixes: 7e0b2b57f01d ("netfilter: nft_ct: add ct timeout support")
Cc: stable@vger.kernel.org
Signed-off-by: Tuan Do <tuan@calif.io>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/net/netfilter/nf_conntrack_timeout.h
net/netfilter/nft_ct.c

index 9fdaba911de64d05ac38f256d0d8445950d13ec5..3a66d4abb6d6885019fc558063b50671ef4f16af 100644 (file)
@@ -14,6 +14,7 @@
 struct nf_ct_timeout {
        __u16                   l3num;
        const struct nf_conntrack_l4proto *l4proto;
+       struct rcu_head         rcu;
        char                    data[];
 };
 
index 128ff8155b5de143d42c5cde80408d2b53c18300..04c74ccf9b848a847bf37b2cbb4adeff6d84a218 100644 (file)
@@ -1020,7 +1020,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
        nf_queue_nf_hook_drop(ctx->net);
        nf_ct_untimeout(ctx->net, timeout);
        nf_ct_netns_put(ctx->net, ctx->family);
-       kfree(priv->timeout);
+       kfree_rcu(priv->timeout, rcu);
 }
 
 static int nft_ct_timeout_obj_dump(struct sk_buff *skb,