All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hyunwoo Kim <imv4bel@gmail.com>
To: pablo@netfilter.org, fw@strlen.de, phil@nwl.cc,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org
Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
	netdev@vger.kernel.org, imv4bel@gmail.com
Subject: [PATCH net] netfilter: ctnetlink: fix use-after-free of exp->master in expectation dump
Date: Sun, 8 Mar 2026 02:20:29 +0900	[thread overview]
Message-ID: <aaxeXUnPpqLUURrt@v4bel> (raw)

ctnetlink_exp_dump_table() iterates the expectation hash table under
rcu_read_lock and dereferences exp->master to access the master
conntrack's fields (ct_net, tuplehash, ct->ext).  However, expectations
do not hold a reference on exp->master.  A concurrent conntrack deletion
via NFNL_SUBSYS_CTNETLINK (a different nfnetlink subsystem mutex) can
free the master conntrack while the dump is in progress, leading to
use-after-free on ct->ext which is freed immediately by kfree().

Fix this by taking a reference on exp->master with
refcount_inc_not_zero() before accessing it.  If the master conntrack is
already being destroyed, skip the expectation.

KASAN report:

[    6.517462] ==================================================================
[    6.517694] BUG: KASAN: slab-use-after-free in ctnetlink_exp_dump_expect+0x584/0x660
[    6.517940] Read of size 1 at addr ffff888102b4ab00 by task poc2/135
[    6.518122]
[    6.518176] CPU: 1 UID: 0 PID: 135 Comm: poc2 Not tainted 7.0.0-rc2+ #5 PREEMPTLAZY
[    6.518179] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    6.518182] Call Trace:
[    6.518186]  <TASK>
[    6.518187]  dump_stack_lvl+0x64/0x80
[    6.518198]  print_report+0xce/0x660
[    6.518204]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[    6.518213]  ? __virt_addr_valid+0xef/0x1a0
[    6.518219]  ? ctnetlink_exp_dump_expect+0x584/0x660
[    6.518221]  kasan_report+0xce/0x100
[    6.518224]  ? ctnetlink_exp_dump_expect+0x584/0x660
[    6.518226]  ctnetlink_exp_dump_expect+0x584/0x660
[    6.518228]  ? __pfx_ctnetlink_exp_dump_expect+0x10/0x10
[    6.518232]  ? kasan_save_track+0x14/0x30
[    6.518236]  ? skb_put+0x72/0xb0
[    6.518242]  ? __asan_memset+0x23/0x50
[    6.518246]  ? __nlmsg_put+0x97/0xb0
[    6.518250]  ctnetlink_exp_fill_info.constprop.0+0xf9/0x180
[    6.518253]  ctnetlink_exp_dump_table+0x24a/0x2e0
[    6.518255]  netlink_dump+0x333/0x880
[    6.518259]  ? __pfx_netlink_dump+0x10/0x10
[    6.518262]  ? __asan_memset+0x23/0x50
[    6.518264]  ? __pfx_mutex_lock+0x10/0x10
[    6.518267]  __netlink_dump_start+0x391/0x450
[    6.518269]  ctnetlink_get_expect+0x393/0x3f0
[    6.518271]  ? __pfx_ctnetlink_get_expect+0x10/0x10
[    6.518274]  ? __pfx_ctnetlink_exp_dump_table+0x10/0x10
[    6.518276]  ? __pfx___nla_validate_parse+0x10/0x10
[    6.518283]  ? mutex_lock+0x7e/0xd0
[    6.518285]  ? __pfx_mutex_lock+0x10/0x10
[    6.518288]  nfnetlink_rcv_msg+0x48e/0x510
[    6.518293]  ? __pfx_nfnetlink_rcv_msg+0x10/0x10
[    6.518296]  ? __sys_sendmsg+0xf4/0x180
[    6.518298]  ? do_syscall_64+0xc3/0x6e0
[    6.518302]  ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[    6.518307]  netlink_rcv_skb+0xc9/0x1f0
[    6.518309]  ? __pfx_nfnetlink_rcv_msg+0x10/0x10
[    6.518311]  ? __pfx_netlink_rcv_skb+0x10/0x10
[    6.518313]  ? security_capable+0xda/0x160
[    6.518318]  nfnetlink_rcv+0xdb/0x220
[    6.518321]  ? __pfx___netlink_lookup+0x10/0x10
[    6.518324]  ? __pfx_nfnetlink_rcv+0x10/0x10
[    6.518326]  ? netlink_deliver_tap+0x5f/0x400
[    6.518329]  netlink_unicast+0x3ec/0x590
[    6.518331]  ? __pfx_netlink_unicast+0x10/0x10
[    6.518333]  ? __pfx___alloc_skb+0x10/0x10
[    6.518334]  ? __alloc_frozen_pages_noprof+0x26f/0x560
[    6.518340]  ? __virt_addr_valid+0xef/0x1a0
[    6.518342]  ? __check_object_size+0x25f/0x450
[    6.518347]  netlink_sendmsg+0x397/0x690
[    6.518349]  ? __pfx_netlink_sendmsg+0x10/0x10
[    6.518351]  ? __import_iovec+0x220/0x270
[    6.518355]  ? __check_object_size+0x4b/0x450
[    6.518357]  ____sys_sendmsg+0x538/0x550
[    6.518361]  ? __pfx_____sys_sendmsg+0x10/0x10
[    6.518363]  ? __pfx_copy_msghdr_from_user+0x10/0x10
[    6.518366]  ? __pfx_lru_add+0x10/0x10
[    6.518372]  ___sys_sendmsg+0xfc/0x170
[    6.518374]  ? __pfx____sys_sendmsg+0x10/0x10
[    6.518376]  ? __pfx_do_wp_page+0x10/0x10
[    6.518382]  __sys_sendmsg+0xf4/0x180
[    6.518384]  ? __pfx___sys_sendmsg+0x10/0x10
[    6.518387]  ? do_user_addr_fault+0x3b5/0x750
[    6.518389]  do_syscall_64+0xc3/0x6e0
[    6.518391]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[    6.518393] RIP: 0033:0x4242c4
[    6.518398] Code: c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b5 0f 1f 00 f3 0f 1e fa 80 3d 9d 1d 09 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 20 89 55
[    6.518400] RSP: 002b:00007ffc8ae20558 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
[    6.518406] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00000000004242c4
[    6.518408] RDX: 0000000000000000 RSI: 00007ffc8ae20590 RDI: 0000000000000003
[    6.518409] RBP: 00007ffc8ae205d0 R08: 0000000000000300 R09: 0000000000000002
[    6.518410] R10: 000000001109e380 R11: 0000000000000202 R12: 00007ffc8ae277b8
[    6.518412] R13: 00007ffc8ae277c8 R14: 00000000004b0828 R15: 0000000000000001
[    6.518413]  </TASK>
[    6.518414]
[    6.528830] Allocated by task 132:
[    6.528935]  kasan_save_stack+0x33/0x60
[    6.529053]  kasan_save_track+0x14/0x30
[    6.529169]  __kasan_krealloc+0xf4/0x180
[    6.529287]  krealloc_node_align_noprof+0x124/0x3c0
[    6.529434]  nf_ct_ext_add+0xd8/0x1a0
[    6.529556]  ctnetlink_create_conntrack+0x38d/0x900
[    6.529718]  ctnetlink_new_conntrack+0x3cf/0x7d0
[    6.529870]  nfnetlink_rcv_msg+0x48e/0x510
[    6.529993]  netlink_rcv_skb+0xc9/0x1f0
[    6.530109]  nfnetlink_rcv+0xdb/0x220
[    6.530219]  netlink_unicast+0x3ec/0x590
[    6.530336]  netlink_sendmsg+0x397/0x690
[    6.530453]  ____sys_sendmsg+0x538/0x550
[    6.530575]  ___sys_sendmsg+0xfc/0x170
[    6.530700]  __sys_sendmsg+0xf4/0x180
[    6.530823]  do_syscall_64+0xc3/0x6e0
[    6.530946]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[    6.531100]
[    6.531151] Freed by task 132:
[    6.531244]  kasan_save_stack+0x33/0x60
[    6.531359]  kasan_save_track+0x14/0x30
[    6.531475]  kasan_save_free_info+0x3b/0x60
[    6.531601]  __kasan_slab_free+0x43/0x70
[    6.531731]  kfree+0x1ca/0x430
[    6.531836]  nf_conntrack_free+0xb2/0x140
[    6.531969]  ctnetlink_del_conntrack+0x4c4/0x520
[    6.532113]  nfnetlink_rcv_msg+0x48e/0x510
[    6.532235]  netlink_rcv_skb+0xc9/0x1f0
[    6.532350]  nfnetlink_rcv+0xdb/0x220
[    6.532462]  netlink_unicast+0x3ec/0x590
[    6.532579]  netlink_sendmsg+0x397/0x690
[    6.532702]  ____sys_sendmsg+0x538/0x550
[    6.532831]  ___sys_sendmsg+0xfc/0x170
[    6.532958]  __sys_sendmsg+0xf4/0x180
[    6.533079]  do_syscall_64+0xc3/0x6e0
[    6.533192]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[    6.533341]
[    6.533392] The buggy address belongs to the object at ffff888102b4ab00
[    6.533392]  which belongs to the cache kmalloc-128 of size 128
[    6.533749] The buggy address is located 0 bytes inside of
[    6.533749]  freed 128-byte region [ffff888102b4ab00, ffff888102b4ab80)
[    6.534113]
[    6.534163] The buggy address belongs to the physical page:
[    6.534324] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x102b4a
[    6.534550] flags: 0x200000000000000(node=0|zone=2)
[    6.534696] page_type: f5(slab)
[    6.534794] raw: 0200000000000000 ffff888100041a00 dead000000000122 0000000000000000
[    6.535036] raw: 0000000000000000 0000000800100010 00000000f5000000 0000000000000000
[    6.535284] page dumped because: kasan: bad access detected
[    6.535450]
[    6.535500] Memory state around the buggy address:
[    6.535641]  ffff888102b4aa00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    6.535852]  ffff888102b4aa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    6.536075] >ffff888102b4ab00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[    6.536306]                    ^
[    6.536411]  ffff888102b4ab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    6.536619]  ffff888102b4ac00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    6.536829] ==================================================================

Fixes: c1d10adb4a52 ("[NETFILTER]: Add ctnetlink port for nf_conntrack")
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
---
 net/netfilter/nf_conntrack_netlink.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index c9d725fc2d71..261ff4c67719 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3167,6 +3167,7 @@ static int
 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct net *net = sock_net(skb->sk);
+	struct nf_conn *master;
 	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 	unsigned long last_id = cb->args[1];
@@ -3180,12 +3181,20 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 			if (l3proto && exp->tuple.src.l3num != l3proto)
 				continue;

-			if (!net_eq(nf_ct_net(exp->master), net))
+			master = exp->master;
+			if (!refcount_inc_not_zero(&master->ct_general.use))
 				continue;

+			if (!net_eq(nf_ct_net(master), net)) {
+				nf_ct_put(master);
+				continue;
+			}
+
 			if (cb->args[1]) {
-				if (ctnetlink_exp_id(exp) != last_id)
+				if (ctnetlink_exp_id(exp) != last_id) {
+					nf_ct_put(master);
 					continue;
+				}
 				cb->args[1] = 0;
 			}
 			if (ctnetlink_exp_fill_info(skb,
@@ -3194,8 +3203,11 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 						    IPCTNL_MSG_EXP_NEW,
 						    exp) < 0) {
 				cb->args[1] = ctnetlink_exp_id(exp);
+				nf_ct_put(master);
 				goto out;
 			}
+
+			nf_ct_put(master);
 		}
 		if (cb->args[1]) {
 			cb->args[1] = 0;
--
2.43.0

             reply	other threads:[~2026-03-07 17:20 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-07 17:20 Hyunwoo Kim [this message]
2026-03-26 21:00 ` [PATCH net] netfilter: ctnetlink: fix use-after-free of exp->master in expectation dump Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aaxeXUnPpqLUURrt@v4bel \
    --to=imv4bel@gmail.com \
    --cc=coreteam@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pablo@netfilter.org \
    --cc=phil@nwl.cc \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.