All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: netdev@vger.kernel.org, paul@paul-moore.com
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>, Huw Davies <huw@codeweavers.com>,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH net] ipv6, calipso: fix data-race in calipso_cache_add() bucketsize check
Date: Sun, 15 Nov 2026 22:45:07 +0800	[thread overview]
Message-ID: <20261115144508.71543-1-jiayuan.chen@linux.dev> (raw)

Issue found by sashiko when reviewing my data-races patch [1]. This is
not a plain READ_ONCE() annotation like the rest of that series but a
real fix, so it is sent separately.

calipso_cache_add() reads calipso_cache_bucketsize twice: the "<= 0"
guard on entry, then the "size < bucketsize" test after taking the
bucket lock. A writer can flip it to 0 in between:

  CPU0                                    CPU1
  calipso_cache_add()
    calipso_cache_bucketsize == 10 (> 0)
                                          proc_dointvec()
                                            calipso_cache_bucketsize = 0
    spin_lock_bh(&bucket.lock)
    size(0) < calipso_cache_bucketsize(0) -> false
    -> else branch, but the bucket is empty

On an empty bucket the else branch takes list.prev (the list head
itself), list_del()s it and then list_add()s through the now poisoned
head:

 Oops: general protection fault, probably for non-canonical address
 0xdead000000000108
 RIP: 0010:calipso_cache_add+0x2f0/0x380
 Call Trace:
  <IRQ>
  calipso_cache_add+0x4c/0x70
  netlbl_cache_add+0x4a/0xa0
  selinux_netlbl_skbuff_getsid+0x1ac/0x280
  selinux_skb_peerlbl_sid+0x7d/0x100
  selinux_socket_sock_rcv_skb+0x2d3/0x460
  security_sock_rcv_skb+0x86/0x150
  sk_filter_trim_cap+0x56/0x730
  sock_queue_rcv_skb_reason+0x1e/0x80
  rawv6_rcv+0x679/0xb20
  raw6_local_deliver+0x1f0/0x5b0
  ip6_protocol_deliver_rcu+0x215/0x9a0
  ip6_input_finish+0xb0/0x1b0
  ip6_input+0xa8/0x250
  ipv6_rcv+0x14b/0x1c0
  __netif_receive_skb_one_core+0x8f/0xe0
  __netif_receive_skb+0x23/0xb0
  process_backlog+0x27a/0x950
  __napi_poll.constprop.0+0x61/0x2c0
  net_rx_action+0x372/0x800
  handle_softirqs+0x109/0x570
  __do_softirq+0x10/0x18
  do_softirq.part.0+0x47/0xd0
  </IRQ>
  <TASK>
  __local_bh_enable_ip+0xf0/0x120
  __dev_queue_xmit+0x578/0x23f0
  neigh_resolve_output+0x278/0x3c0
  ip6_finish_output2+0x4b1/0xcb0
  ip6_finish_output+0x2b6/0x6b0
  ip6_output+0x122/0x400
  ip6_local_out+0x61/0xb0
  ip6_send_skb+0xa0/0x260
  ip6_push_pending_frames+0x2b/0x40
  rawv6_sendmsg+0x1b7a/0x2750
  inet_sendmsg+0xa1/0xb0
  __sys_sendto+0x2fe/0x350
  __x64_sys_sendto+0x7f/0xb0
  do_syscall_64+0xe1/0x450
  entry_SYSCALL_64_after_hwframe+0x76/0x7e

Snapshot the sysctl into a local once and use it for both tests, like
cipso_v4_cache_add() has since commit dd44f04b9214 ("cipso: Fix
data-races around sysctl.").

[1] https://lore.kernel.org/netdev/179428999963.994134.16904544500890053668@kernel.org/

Fixes: 4fee5242bf41 ("calipso: Add a label cache.")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
 net/ipv6/calipso.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index e399a42e3083..fb79eccafc02 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -263,13 +263,14 @@ static int calipso_cache_check(const unsigned char *key,
 static int calipso_cache_add(const unsigned char *calipso_ptr,
 			     const struct netlbl_lsm_secattr *secattr)
 {
+	int bkt_size = READ_ONCE(calipso_cache_bucketsize);
 	int ret_val = -EPERM;
 	u32 bkt;
 	struct calipso_map_cache_entry *entry = NULL;
 	struct calipso_map_cache_entry *old_entry = NULL;
 	u32 calipso_ptr_len;
 
-	if (!calipso_cache_enabled || calipso_cache_bucketsize <= 0)
+	if (!calipso_cache_enabled || bkt_size <= 0)
 		return 0;
 
 	calipso_ptr_len = calipso_ptr[1];
@@ -289,7 +290,7 @@ static int calipso_cache_add(const unsigned char *calipso_ptr,
 
 	bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1);
 	spin_lock_bh(&calipso_cache[bkt].lock);
-	if (calipso_cache[bkt].size < calipso_cache_bucketsize) {
+	if (calipso_cache[bkt].size < bkt_size) {
 		list_add(&entry->list, &calipso_cache[bkt].list);
 		calipso_cache[bkt].size += 1;
 	} else {
-- 
2.43.0


             reply	other threads:[~2026-11-15 14:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-15 14:45 Jiayuan Chen [this message]
2026-11-15 14:49 ` [PATCH net] ipv6, calipso: fix data-race in calipso_cache_add() bucketsize check sashiko-bot

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=20261115144508.71543-1-jiayuan.chen@linux.dev \
    --to=jiayuan.chen@linux.dev \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=huw@codeweavers.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=paul@paul-moore.com \
    /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.