* [PATCH bpf] bpf: Fix netns reference imbalance in conntrack kfuncs
@ 2026-07-29 16:31 Chengfeng Ye
2026-07-29 17:15 ` bot+bpf-ci
0 siblings, 1 reply; 2+ messages in thread
From: Chengfeng Ye @ 2026-07-29 16:31 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Kumar Kartikeya Dwivedi,
Lorenzo Bianconi
Cc: netfilter-devel, coreteam, netdev, linux-kernel, bpf,
Chengfeng Ye
The opts argument of the BPF conntrack kfuncs can point to a shared map
value. __bpf_nf_ct_lookup() and __bpf_nf_ct_alloc_entry() read
opts->netns_id separately when acquiring and releasing the network
namespace reference.
The reference imbalance can occur as follows:
CPU 0 CPU 1
read opts->netns_id (-1)
skip get_net_ns_by_id()
write opts->netns_id (id)
read opts->netns_id (id)
put_net(net) /* no matching get */
The reverse transition leaks the reference. Repeating the unmatched put
can destroy a live namespace and crash later users.
The kernel reported:
Oops: general protection fault, probably for non-canonical address
KASAN: null-ptr-deref in range [0x00000000000000e8-0x00000000000000ef]
RIP: 0010:bpf_prog_test_run_xdp+0x52c/0x1700
Call Trace:
__sys_bpf+0x1662/0x50c0
__x64_sys_bpf+0x73/0xb0
do_syscall_64+0xf9/0x540
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Kernel panic - not syncing: Fatal exception
Read netns_id once with READ_ONCE() and use that value for validation
and the matching get/put pair. Each invocation then consistently uses
either the calling namespace or a referenced namespace.
Fixes: aed8ee7feb44 ("net: netfilter: Deduplicate code in bpf_{xdp,skb}_ct_lookup")
Fixes: d7e79c97c00c ("net: netfilter: Add kfuncs to allocate and insert CT")
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
Please queue this fix for stable kernels.
net/netfilter/nf_conntrack_bpf.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/netfilter/nf_conntrack_bpf.c b/net/netfilter/nf_conntrack_bpf.c
index f98d1d4b42c3..8b540846f299 100644
--- a/net/netfilter/nf_conntrack_bpf.c
+++ b/net/netfilter/nf_conntrack_bpf.c
@@ -122,6 +122,7 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
struct nf_conntrack_tuple otuple, rtuple;
struct nf_conntrack_zone ct_zone;
struct nf_conn *ct;
+ s32 netns_id;
int err;
if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12))
@@ -134,7 +135,8 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
return ERR_PTR(-EINVAL);
}
- if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
+ netns_id = READ_ONCE(opts->netns_id);
+ if (unlikely(netns_id < BPF_F_CURRENT_NETNS))
return ERR_PTR(-EINVAL);
err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto,
@@ -147,8 +149,8 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
if (err < 0)
return ERR_PTR(err);
- if (opts->netns_id >= 0) {
- net = get_net_ns_by_id(net, opts->netns_id);
+ if (netns_id >= 0) {
+ net = get_net_ns_by_id(net, netns_id);
if (unlikely(!net))
return ERR_PTR(-ENONET);
}
@@ -171,7 +173,7 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
__nf_ct_set_timeout(ct, timeout * HZ);
out:
- if (opts->netns_id >= 0)
+ if (netns_id >= 0)
put_net(net);
return ct;
@@ -186,6 +188,7 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
struct nf_conntrack_tuple tuple;
struct nf_conntrack_zone ct_zone;
struct nf_conn *ct;
+ s32 netns_id;
int err;
if (!opts || !bpf_tuple)
@@ -201,7 +204,8 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
}
if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP))
return ERR_PTR(-EPROTO);
- if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
+ netns_id = READ_ONCE(opts->netns_id);
+ if (unlikely(netns_id < BPF_F_CURRENT_NETNS))
return ERR_PTR(-EINVAL);
err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto,
@@ -209,8 +213,8 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
if (err < 0)
return ERR_PTR(err);
- if (opts->netns_id >= 0) {
- net = get_net_ns_by_id(net, opts->netns_id);
+ if (netns_id >= 0) {
+ net = get_net_ns_by_id(net, netns_id);
if (unlikely(!net))
return ERR_PTR(-ENONET);
}
@@ -225,7 +229,7 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
}
hash = nf_conntrack_find_get(net, &ct_zone, &tuple);
- if (opts->netns_id >= 0)
+ if (netns_id >= 0)
put_net(net);
if (!hash)
return ERR_PTR(-ENOENT);
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH bpf] bpf: Fix netns reference imbalance in conntrack kfuncs
2026-07-29 16:31 [PATCH bpf] bpf: Fix netns reference imbalance in conntrack kfuncs Chengfeng Ye
@ 2026-07-29 17:15 ` bot+bpf-ci
0 siblings, 0 replies; 2+ messages in thread
From: bot+bpf-ci @ 2026-07-29 17:15 UTC (permalink / raw)
To: nicoyip.dev, pablo, fw, phil, davem, edumazet, kuba, pabeni,
horms, ast, daniel, hawk, john.fastabend, sdf, memxor, lorenzo
Cc: netfilter-devel, coreteam, netdev, linux-kernel, bpf, nicoyip.dev,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]
> The kernel reported:
>
> Oops: general protection fault, probably for non-canonical address
> KASAN: null-ptr-deref in range [0x00000000000000e8-0x00000000000000ef]
> RIP: 0010:bpf_prog_test_run_xdp+0x52c/0x1700
> Call Trace:
> __sys_bpf+0x1662/0x50c0
> __x64_sys_bpf+0x73/0xb0
> do_syscall_64+0xf9/0x540
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> Kernel panic - not syncing: Fatal exception
This isn't a bug, but could the crash trace be clearer about its
connection to the fix? The trace shows only BPF test-run frames
with no netfilter or conntrack function names visible.
The chain is reconstructible - the extra put_net() frees the
caller's netns, loopback_dev becomes NULL, and bpf_prog_test_run_xdp()
then dereferences it - but a reader has to derive this themselves.
Would it help to add a sentence connecting the trace to the fix, or
include a Reported-by: or Closes: tag for the original report?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/30472145413
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-29 17:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 16:31 [PATCH bpf] bpf: Fix netns reference imbalance in conntrack kfuncs Chengfeng Ye
2026-07-29 17:15 ` bot+bpf-ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox