From: Florian Westphal <fw@strlen.de>
To: <netdev@vger.kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
<netfilter-devel@vger.kernel.org>,
pablo@netfilter.org
Subject: [PATCH net 09/10] netfilter: ctnetlink: fix use-after-free of exp->master in expectation dump
Date: Mon, 9 Mar 2026 22:08:44 +0100 [thread overview]
Message-ID: <20260309210845.15657-10-fw@strlen.de> (raw)
In-Reply-To: <20260309210845.15657-1-fw@strlen.de>
From: Hyunwoo Kim <imv4bel@gmail.com>
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:
BUG: KASAN: slab-use-after-free in ctnetlink_exp_dump_expect+0x584/0x660
Read of size 1 at addr ffff888102b4ab00 by task poc2/135
CPU: 1 UID: 0 PID: 135 Comm: poc2 Not tainted 7.0.0-rc2+ #5 PREEMPTLAZY
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
Call Trace:
ctnetlink_exp_dump_expect+0x584/0x660
ctnetlink_exp_fill_info.constprop.0+0xf9/0x180
ctnetlink_exp_dump_table+0x24a/0x2e0
netlink_dump+0x333/0x880
__netlink_dump_start+0x391/0x450
ctnetlink_get_expect+0x393/0x3f0
nfnetlink_rcv_msg+0x48e/0x510
netlink_rcv_skb+0xc9/0x1f0
nfnetlink_rcv+0xdb/0x220
netlink_unicast+0x3ec/0x590
netlink_sendmsg+0x397/0x690
__sys_sendmsg+0xf4/0x180
Allocated by task 132:
krealloc_node_align_noprof+0x124/0x3c0
nf_ct_ext_add+0xd8/0x1a0
ctnetlink_create_conntrack+0x38d/0x900
ctnetlink_new_conntrack+0x3cf/0x7d0
nfnetlink_rcv_msg+0x48e/0x510
netlink_rcv_skb+0xc9/0x1f0
nfnetlink_rcv+0xdb/0x220
netlink_unicast+0x3ec/0x590
netlink_sendmsg+0x397/0x690
__sys_sendmsg+0xf4/0x180
do_syscall_64+0xc3/0x6e0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
Freed by task 132:
kfree+0x1ca/0x430
nf_conntrack_free+0xb2/0x140
ctnetlink_del_conntrack+0x4c4/0x520
nfnetlink_rcv_msg+0x48e/0x510
netlink_rcv_skb+0xc9/0x1f0
nfnetlink_rcv+0xdb/0x220
netlink_unicast+0x3ec/0x590
netlink_sendmsg+0x397/0x690
__sys_sendmsg+0xf4/0x180
do_syscall_64+0xc3/0x6e0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
The buggy address belongs to the object at ffff888102b4ab00
which belongs to the cache kmalloc-128 of size 128
The buggy address is located 0 bytes inside of
freed 128-byte region [ffff888102b4ab00, ffff888102b4ab80)
Fixes: c1d10adb4a52 ("[NETFILTER]: Add ctnetlink port for nf_conntrack")
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
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 10a9b98368f4..96e342147de8 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.52.0
next prev parent reply other threads:[~2026-03-09 21:09 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 21:08 [PATCH net 00/10] netfilter: updates for net Florian Westphal
2026-03-09 21:08 ` [PATCH net 01/10] netfilter: nf_tables: Fix for duplicate device in netdev hooks Florian Westphal
2026-03-09 21:08 ` [PATCH net 02/10] netfilter: nf_tables: always walk all pending catchall elements Florian Westphal
2026-03-09 21:08 ` [PATCH net 03/10] netfilter: nft_set_pipapo: fix stack out-of-bounds read in pipapo_drop() Florian Westphal
2026-03-09 21:08 ` [PATCH net 04/10] netfilter: x_tables: guard option walkers against 1-byte tail reads Florian Westphal
2026-03-09 21:08 ` [PATCH net 05/10] netfilter: nfnetlink_queue: fix entry leak in bridge verdict error path Florian Westphal
2026-03-09 21:08 ` [PATCH net 06/10] netfilter: nfnetlink_cthelper: fix OOB read in nfnl_cthelper_dump_table() Florian Westphal
2026-03-09 21:08 ` [PATCH net 07/10] netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct() Florian Westphal
2026-03-09 21:08 ` [PATCH net 08/10] netfilter: ctnetlink: fix use-after-free of exp->master in single expectation GET Florian Westphal
2026-03-09 21:08 ` Florian Westphal [this message]
2026-03-09 21:08 ` [PATCH net 10/10] netfilter: xt_IDLETIMER: reject rev0 reuse of ALARM timer labels Florian Westphal
2026-03-10 10:56 ` [PATCH net 00/10] netfilter: updates for net Pablo Neira Ayuso
2026-03-10 12:33 ` Florian Westphal
2026-03-10 12:41 ` Pablo Neira Ayuso
2026-03-10 12:48 ` Florian Westphal
2026-03-10 13:02 ` Florian Westphal
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=20260309210845.15657-10-fw@strlen.de \
--to=fw@strlen.de \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox