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: [no followups] expand[flat|nested] mbox.gz Atom feed
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox