[PATCH net] ipv6: use READ_ONCE() for bindv6only default in inet6_create()

Runyu Xiao posted 1 patch 1 week ago
There is a newer version of this series
net/ipv6/af_inet6.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH net] ipv6: use READ_ONCE() for bindv6only default in inet6_create()
Posted by Runyu Xiao 1 week ago
inet6_create() copies net->ipv6.sysctl.bindv6only into sk->sk_ipv6only
without any locking. bindv6only is writable through the IPv6 sysctl
table via proc_dou8vec_minmax(), and adjacent lockless sysctl reads in
the same function already use READ_ONCE().

This read is reachable whenever AF_INET6 sockets are created while
/proc/sys/net/ipv6/bindv6only is being updated. In our QEMU/KCSAN stress
test on Linux v6.18.21, one actor repeatedly toggled
/proc/sys/net/ipv6/bindv6only while four concurrent readers repeatedly
created AF_INET6 stream and datagram sockets and queried IPV6_V6ONLY.
The writer completed 75313 sysctl updates in 45 seconds, and the readers
created more than 360000 IPv6 sockets in the same window.

KCSAN reported the following race:

==================================================================
BUG: KCSAN: data-race in inet6_create / proc_dou8vec_minmax

write (marked) to 0xffffffffaa27bbcd of 1 bytes by task 95 on cpu 1:
 proc_dou8vec_minmax+0x206/0x220
 proc_sys_call_handler+0x21d/0x300
 proc_sys_write+0xe/0x20
 vfs_write+0x559/0x6d0
 ksys_write+0x88/0x110
 __x64_sys_write+0x3c/0x50
 x64_sys_call+0x1016/0x2020
 do_syscall_64+0xb0/0x2c0
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

read to 0xffffffffaa27bbcd of 1 bytes by task 97 on cpu 0:
 inet6_create+0x351/0x700
 __sock_create+0x149/0x280
 __sys_socket+0x9f/0x130
 __x64_sys_socket+0x3b/0x50
 x64_sys_call+0x1c76/0x2020
 do_syscall_64+0xb0/0x2c0
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

value changed: 0x01 -> 0x00
==================================================================

Wrap the bindv6only read in READ_ONCE() to annotate the intentional
lockless access and match the surrounding per-net sysctl reader
contract.

This issue was first flagged by our static analysis tool while scanning
lockless sysctl readers, then manually audited and runtime-reproduced
with QEMU + KCSAN on Linux v6.18.21.

Build-tested by compiling net/ipv6/af_inet6.o on x86_64 netdev/main.
Runtime-tested with a QEMU/KCSAN stress test that concurrently toggled
/proc/sys/net/ipv6/bindv6only and created AF_INET6 sockets.

Fixes: 9fe516ba3fb2 ("inet: move ipv6only in sock_common")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
 net/ipv6/af_inet6.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 0a88b376141d..79fc6ce6ff77 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -211,7 +211,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
 	np->pmtudisc	= IPV6_PMTUDISC_WANT;
 	inet6_assign_bit(REPFLOW, sk, READ_ONCE(net->ipv6.sysctl.flowlabel_reflect) &
 				      FLOWLABEL_REFLECT_ESTABLISHED);
-	sk->sk_ipv6only	= net->ipv6.sysctl.bindv6only;
+	sk->sk_ipv6only	= READ_ONCE(net->ipv6.sysctl.bindv6only);
 	sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash);
 
 	/* Init the ipv4 part of the socket since we can have sockets
-- 
2.34.1
Re: [PATCH net] ipv6: use READ_ONCE() for bindv6only default in inet6_create()
Posted by Eric Dumazet 1 week ago
On Sun, May 31, 2026 at 5:48 AM Runyu Xiao <runyu.xiao@seu.edu.cn> wrote:
>
> inet6_create() copies net->ipv6.sysctl.bindv6only into sk->sk_ipv6only
> without any locking. bindv6only is writable through the IPv6 sysctl
> table via proc_dou8vec_minmax(), and adjacent lockless sysctl reads in
> the same function already use READ_ONCE().
>
> This read is reachable whenever AF_INET6 sockets are created while
> /proc/sys/net/ipv6/bindv6only is being updated. In our QEMU/KCSAN stress
> test on Linux v6.18.21, one actor repeatedly toggled
> /proc/sys/net/ipv6/bindv6only while four concurrent readers repeatedly
> created AF_INET6 stream and datagram sockets and queried IPV6_V6ONLY.
> The writer completed 75313 sysctl updates in 45 seconds, and the readers
> created more than 360000 IPv6 sockets in the same window.
>
> KCSAN reported the following race:
>
> ==================================================================
> BUG: KCSAN: data-race in inet6_create / proc_dou8vec_minmax
>
> write (marked) to 0xffffffffaa27bbcd of 1 bytes by task 95 on cpu 1:
>  proc_dou8vec_minmax+0x206/0x220
>  proc_sys_call_handler+0x21d/0x300
>  proc_sys_write+0xe/0x20
>  vfs_write+0x559/0x6d0
>  ksys_write+0x88/0x110
>  __x64_sys_write+0x3c/0x50
>  x64_sys_call+0x1016/0x2020
>  do_syscall_64+0xb0/0x2c0
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> read to 0xffffffffaa27bbcd of 1 bytes by task 97 on cpu 0:
>  inet6_create+0x351/0x700
>  __sock_create+0x149/0x280
>  __sys_socket+0x9f/0x130
>  __x64_sys_socket+0x3b/0x50
>  x64_sys_call+0x1c76/0x2020
>  do_syscall_64+0xb0/0x2c0
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> value changed: 0x01 -> 0x00
> ==================================================================
>
> Wrap the bindv6only read in READ_ONCE() to annotate the intentional
> lockless access and match the surrounding per-net sysctl reader
> contract.
>
> This issue was first flagged by our static analysis tool while scanning
> lockless sysctl readers, then manually audited and runtime-reproduced
> with QEMU + KCSAN on Linux v6.18.21.
>
> Build-tested by compiling net/ipv6/af_inet6.o on x86_64 netdev/main.
> Runtime-tested with a QEMU/KCSAN stress test that concurrently toggled
> /proc/sys/net/ipv6/bindv6only and created AF_INET6 sockets.
>
> Fixes: 9fe516ba3fb2 ("inet: move ipv6only in sock_common")

Wrong Fixes: tag, lack of READ_ONCE() was before the patch?

Also Fixes: tags are going to trigger extra work for many stable
teams, for no reason.

> Cc: stable@vger.kernel.org

No need to CC stable for this kind of patch.

> Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
> ---
>

Please cut the verbosity, we do not need to copy/paste fifty lines
just to explain the obvious.

I hope you understand there is no serious bug here, KCSAN is a
debugging feature, not a production one.

One or two lines should be enough, you can take a look at
f062e8e25102324364aada61b8283356235bc3c1 ("ipv6: annotate data-races
in net/ipv6/route.c")