netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] ipv6, calipso: fix data-race in calipso_cache_add() bucketsize check
@ 2026-11-15 14:45 Jiayuan Chen
  0 siblings, 0 replies; only message in thread
From: Jiayuan Chen @ 2026-11-15 14:45 UTC (permalink / raw)
  To: netdev, paul
  Cc: Jiayuan Chen, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Huw Davies, linux-security-module,
	linux-kernel

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


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-15 14:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-15 14:45 [PATCH net] ipv6, calipso: fix data-race in calipso_cache_add() bucketsize check Jiayuan Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).