From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59A7D3B2D0D for ; Thu, 30 Jul 2026 06:38:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785393502; cv=none; b=cogvdWVvyGbpKCUORy7Pug3lS7wC/NoVQ8jSyXR5t7b5cpwQvjENJbs7oe92Gd+seIY1itUe9Pqz7TzbkoBZwaZ/Qudl4NV/Sw6l0k5urpSbNiNkx7pHPNvtZlSYm9vijWoIZbhGxEb/ypr9G0JA96412PpBnlySiCle/klR/Rk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785393502; c=relaxed/simple; bh=ccS/vynfAjtPWGb8cQXbw2Ma7u9Kc2So5zt5lpzwcaM=; h=Mime-Version:Content-Type:Date:Message-Id:From:To:Cc:Subject: References:In-Reply-To; b=YMUw114/uAERyU3qsEabi4s1DVeY37wpVmqC/ie59Yxx8yPYZDspCUav1VETv1tTelce4cKXuV+TAxTxPFeryS2wswtXABGdQsIqig/fuJADWEL9u4Q12D3FIgaWSfaM66y/WMWXv9kAzBXjkdVAzHPu6kHaaQDHDxY/mL2JZcs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=etsalapatis.com; spf=pass smtp.mailfrom=etsalapatis.com; dkim=pass (2048-bit key) header.d=etsalapatis-com.20251104.gappssmtp.com header.i=@etsalapatis-com.20251104.gappssmtp.com header.b=pHZHCR7C; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=etsalapatis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=etsalapatis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=etsalapatis-com.20251104.gappssmtp.com header.i=@etsalapatis-com.20251104.gappssmtp.com header.b="pHZHCR7C" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2cf50c6f235so19774235ad.0 for ; Wed, 29 Jul 2026 23:38:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=etsalapatis-com.20251104.gappssmtp.com; s=20251104; t=1785393500; x=1785998300; darn=vger.kernel.org; h=in-reply-to:references:subject:cc:to:from:message-id:date :content-type:content-transfer-encoding:mime-version:from:to:cc :subject:date:message-id:reply-to:content-type; bh=gGidP0vHSPV0NPul0Vyzr/cFRYrRFVowQdSQZFiXkIw=; b=pHZHCR7C3tPT3Z0r4VooonpWF4QZlEuUJnGudgBKFC2RitXrAmnzkSPkhrhLlF2fKs mLHD1MaDmhd1yr1tGy4JyXW3FhZ1dO88b04iMaW76E+hURKiq0Eu8DNLqtYVF+SpZ5+G gRPSWAhWz5L7D/SLEhZjJip+i+OlQTPK+NRpxxTQokfvn/lCbBmcILN7fqI88WBDcv54 TPUQnkIZpb6pI2vwh4FIAoCWPSFWStSLMz7MZkB8F8KmMZhs8GpUy/Wyow/DEpy3aZL8 T7s9YAVkd/I74rwyfPjcTpImFB7z3fJ+ysE2CVA/Eh9Hrl7Xi61z72WwOSWu6bAj/RmP Mjtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785393500; x=1785998300; h=in-reply-to:references:subject:cc:to:from:message-id:date :content-type:content-transfer-encoding:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=gGidP0vHSPV0NPul0Vyzr/cFRYrRFVowQdSQZFiXkIw=; b=ZOIUuCZIpiihQ5U2mWwiW3O/GzVkbQe9STPyaQxI5AuxJrwBnQEhb5X9ArUPVBKiFW 376HLLva9UKIQb2clIMS5RuDIrMsJZEnEH7dC3Jr3BPNUddUEUA1ZYnuFfNnYz6M+/EH lhQLrVskf+YjevtHp4v6AK6YpaOg54hRXo7RwvcmQaSjAl3kYire2n4CP9k6nnrpGSIT WEt4yXZmCoLmPlYMETsNHyCtW5I23PwazvGj9BvdQjm6hIlqToxy6q6fHh/RVUCSg/0T BSDs++fUGMHnHlLyMMLAui5T3cUnQsv9uEgI4baaF8J1sgdVxnNQd0q9wf/W1cb+EdSG eqXg== X-Forwarded-Encrypted: i=1; AHgh+RrUPD/t0DDBJ/cpqSW+G8Ce2GT6Dzvf9VDczC17FTmFCAWyvZtTMEcNtc8V7ZWyyyE0RdovxH+N87BcCsQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwG+QENLDpiuyETtZ4mmKAm8bXSiK/jRYxPvHXm3G/vsRkoXL9I 2uSc17CQxkO1xkOFKVoNkotmQw6JNA0Ij/vgUf9Hpw/GVtGitJWx5RP/DBNR7ED/fEM= X-Gm-Gg: AR+sD12KgqfgF4aAOqwhv2KE8MIrbCUtvF1yjyYfbXhEwnnp7GFg1sYUkuYogZ158Og 1JbpDH6ivZUQEOEXHvMwOS+wx4fy+bDFpn1sX9rb53UQ4iFT/07lR0LayZp7ieqvpkNZR2sYDoS SvfDsH4xMkpxFsqpJAiUVvwUFMqk4LodCXvXTAMFbsM0xVWTRwgh7WqBNM9tI+ZAMKCHTIQ3kXi vdPBHlKPRHhqK0gWGc8prYCl6VwB4Q9G/gHq2KHNSIc08obhFHKW4ZL0c1QIx1uxd4FghTh1Cv5 qJV/xhjBUsAn6LmBoz7UaQ1eafDYKqIhkZ1knN7bFQLY8SYHzUqyPf/rD5vrCDOGNI2uW2m6bGP PUFjCQp00xgoTxPMUB0WykQpoosv3kdrSsE/r65+Qi4HUzp1tF85Pw4TtRYb3HpeObowJdqxqDQ uPXRUlhW+bHGfRU1ZFemVnjTsbRsn0Nis74Ygxf3rIaMZDZHX9sCnhD2z+mw4H19fF1FUBoeLJz zW+MIwEpO2jvUph/A== X-Received: by 2002:a17:903:1a2f:b0:2ce:8e70:3210 with SMTP id d9443c01a7336-2d035bdde67mr15176115ad.16.1785393499622; Wed, 29 Jul 2026 23:38:19 -0700 (PDT) Received: from localhost (107-190-31-17.cpe.teksavvy.com. [107.190.31.17]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d022a15303sm21373135ad.3.2026.07.29.23.38.18 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 29 Jul 2026 23:38:19 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 Date: Thu, 30 Jul 2026 02:38:18 -0400 Message-Id: From: "Emil Tsalapatis" To: "Chengfeng Ye" , "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: , , , , Subject: Re: [PATCH bpf] bpf: Fix netns reference imbalance in conntrack kfuncs X-Mailer: aerc 0.21.0-0-g5549850facc2 References: <20260729163141.213611-1-nicoyip.dev@gmail.com> In-Reply-To: <20260729163141.213611-1-nicoyip.dev@gmail.com> On Wed Jul 29, 2026 at 12:31 PM EDT, Chengfeng Ye wrote: > 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}_c= t_lookup") > Fixes: d7e79c97c00c ("net: netfilter: Add kfuncs to allocate and insert C= T") > Signed-off-by: Chengfeng Ye Sashiko is right on this regarding all other fields of opts having the same issue. While they can't lead to a crash, let's still snapshot them at the beginning of the function so they don't change from under us. This is still far from ideal - we may read an inconsistent snapshot of the struct - but it's backed by BPF program-controlled memory so AFAICT this is the best we can do. pw-bot: cr > --- > 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_conntrac= k_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_s= ock_tuple *bpf_tuple, > struct nf_conntrack_tuple otuple, rtuple; > struct nf_conntrack_zone ct_zone; > struct nf_conn *ct; > + s32 netns_id; > int err; > =20 > if (!(opts_len =3D=3D NF_BPF_CT_OPTS_SZ || opts_len =3D=3D 12)) > @@ -134,7 +135,8 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_s= ock_tuple *bpf_tuple, > return ERR_PTR(-EINVAL); > } > =20 > - if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) > + netns_id =3D READ_ONCE(opts->netns_id); > + if (unlikely(netns_id < BPF_F_CURRENT_NETNS)) > return ERR_PTR(-EINVAL); > =20 > err =3D 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_s= ock_tuple *bpf_tuple, > if (err < 0) > return ERR_PTR(err); > =20 > - if (opts->netns_id >=3D 0) { > - net =3D get_net_ns_by_id(net, opts->netns_id); > + if (netns_id >=3D 0) { > + net =3D 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_s= ock_tuple *bpf_tuple, > __nf_ct_set_timeout(ct, timeout * HZ); > =20 > out: > - if (opts->netns_id >=3D 0) > + if (netns_id >=3D 0) > put_net(net); > =20 > 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; > =20 > if (!opts || !bpf_tuple) > @@ -201,7 +204,8 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net = *net, > } > if (unlikely(opts->l4proto !=3D IPPROTO_TCP && opts->l4proto !=3D IPPRO= TO_UDP)) > return ERR_PTR(-EPROTO); > - if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) > + netns_id =3D READ_ONCE(opts->netns_id); > + if (unlikely(netns_id < BPF_F_CURRENT_NETNS)) > return ERR_PTR(-EINVAL); > =20 > err =3D 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); > =20 > - if (opts->netns_id >=3D 0) { > - net =3D get_net_ns_by_id(net, opts->netns_id); > + if (netns_id >=3D 0) { > + net =3D 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, > } > =20 > hash =3D nf_conntrack_find_get(net, &ct_zone, &tuple); > - if (opts->netns_id >=3D 0) > + if (netns_id >=3D 0) > put_net(net); > if (!hash) > return ERR_PTR(-ENOENT);