Skip to content

Commit 97e1db0

Browse files
q2venPaolo Abeni
authored and
Paolo Abeni
committed
af_unix: Annotate data-race around unix_sk(sk)->addr.
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 SamirMulani#12 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 Fixes: 1da177e4c3f4 ("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]>
1 parent 21a22ed commit 97e1db0

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

net/unix/af_unix.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ static int unix_listen(struct socket *sock, int backlog)
731731
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
732732
goto out; /* Only stream/seqpacket sockets accept */
733733
err = -EINVAL;
734-
if (!u->addr)
734+
if (!READ_ONCE(u->addr))
735735
goto out; /* No listens on an unbound socket */
736736
unix_state_lock(sk);
737737
if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
@@ -1369,7 +1369,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
13691369

13701370
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
13711371
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1372-
!unix_sk(sk)->addr) {
1372+
!READ_ONCE(unix_sk(sk)->addr)) {
13731373
err = unix_autobind(sk);
13741374
if (err)
13751375
goto out;
@@ -1481,7 +1481,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
14811481
goto out;
14821482

14831483
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
1484-
test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
1484+
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1485+
!READ_ONCE(u->addr)) {
14851486
err = unix_autobind(sk);
14861487
if (err)
14871488
goto out;
@@ -1950,7 +1951,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
19501951
}
19511952

19521953
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
1953-
test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
1954+
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
1955+
!READ_ONCE(u->addr)) {
19541956
err = unix_autobind(sk);
19551957
if (err)
19561958
goto out;

0 commit comments

Comments
 (0)