Skip to content

Commit 884615a

Browse files
q2venpelwell
authored andcommitted
af_unix: Annotate data-race around unix_sk(sk)->addr.
[ Upstream commit 97e1db0 ] Once unix_sk(sk)->addr is assigned under net->unx.table.locks and unix_sk(sk)->bindlock, *(unix_sk(sk)->addr) and unix_sk(sk)->path are fully set up, and unix_sk(sk)->addr is never changed. unix_getname() and unix_copy_addr() access the two fields locklessly, and commit ae3b564 ("missing barriers in some of unix_sock ->addr and ->path accesses") added smp_store_release() and smp_load_acquire() pairs. In other functions, we still read unix_sk(sk)->addr locklessly to check if the socket is bound, and KCSAN complains about it. [0] Given these functions have no dependency for *(unix_sk(sk)->addr) and unix_sk(sk)->path, READ_ONCE() is enough to annotate the data-race. Note that it is safe to access unix_sk(sk)->addr locklessly if the socket is found in the hash table. For example, the lockless read of otheru->addr in unix_stream_connect() is safe. Note also that newu->addr there is of the child socket that is still not accessible from userspace, and smp_store_release() publishes the address in case the socket is accept()ed and unix_getname() / unix_copy_addr() is called. [0]: BUG: KCSAN: data-race in unix_bind / unix_listen write (marked) to 0xffff88805f8d1840 of 8 bytes by task 13723 on cpu 0: __unix_set_addr_hash net/unix/af_unix.c:329 [inline] unix_bind_bsd net/unix/af_unix.c:1241 [inline] unix_bind+0x881/0x1000 net/unix/af_unix.c:1319 __sys_bind+0x194/0x1e0 net/socket.c:1847 __do_sys_bind net/socket.c:1858 [inline] __se_sys_bind net/socket.c:1856 [inline] __x64_sys_bind+0x40/0x50 net/socket.c:1856 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x4f/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x46/0x4e read to 0xffff88805f8d1840 of 8 bytes by task 13724 on cpu 1: unix_listen+0x72/0x180 net/unix/af_unix.c:734 __sys_listen+0xdc/0x160 net/socket.c:1881 __do_sys_listen net/socket.c:1890 [inline] __se_sys_listen net/socket.c:1888 [inline] __x64_sys_listen+0x2e/0x40 net/socket.c:1888 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x4f/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x46/0x4e value changed: 0x0000000000000000 -> 0xffff88807b5b1b40 Reported by Kernel Concurrency Sanitizer on: CPU: 1 PID: 13724 Comm: syz-executor.4 Not tainted 6.8.0-12822-gcd51db110a7e #12 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 Fixes: 1da177e ("Linux-2.6.12-rc2") Reported-by: syzkaller <[email protected]> Signed-off-by: Kuniyuki Iwashima <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 10c77e7 commit 884615a

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

net/unix/af_unix.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ static int unix_listen(struct socket *sock, int backlog)
732732
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
733733
goto out; /* Only stream/seqpacket sockets accept */
734734
err = -EINVAL;
735-
if (!u->addr)
735+
if (!READ_ONCE(u->addr))
736736
goto out; /* No listens on an unbound socket */
737737
unix_state_lock(sk);
738738
if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
@@ -1379,7 +1379,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
13791379

13801380
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
13811381
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1382-
!unix_sk(sk)->addr) {
1382+
!READ_ONCE(unix_sk(sk)->addr)) {
13831383
err = unix_autobind(sk);
13841384
if (err)
13851385
goto out;
@@ -1487,7 +1487,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
14871487
goto out;
14881488

14891489
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
1490-
test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
1490+
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1491+
!READ_ONCE(u->addr)) {
14911492
err = unix_autobind(sk);
14921493
if (err)
14931494
goto out;
@@ -1927,7 +1928,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
19271928
}
19281929

19291930
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
1930-
test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
1931+
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1932+
!READ_ONCE(u->addr)) {
19311933
err = unix_autobind(sk);
19321934
if (err)
19331935
goto out;

0 commit comments

Comments
 (0)