Skip to content

Commit 6416722

Browse files
q2venSasha Levin
authored andcommitted
af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
[ Upstream commit 3a0f38e ] ioctl(SIOCINQ) calls unix_inq_len() that checks sk->sk_state first and returns -EINVAL if it's TCP_LISTEN. Then, for SOCK_STREAM sockets, unix_inq_len() returns the number of bytes in recvq. However, unix_inq_len() does not hold unix_state_lock(), and the concurrent listen() might change the state after checking sk->sk_state. If the race occurs, 0 is returned for the listener, instead of -EINVAL, because the length of skb with embryo is 0. We could hold unix_state_lock() in unix_inq_len(), but it's overkill given the result is true for pre-listen() TCP_CLOSE state. So, let's use READ_ONCE() for sk->sk_state in unix_inq_len(). Fixes: 1da177e ("Linux-2.6.12-rc2") Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 222a5c0 commit 6416722

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

net/unix/af_unix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3068,7 +3068,7 @@ long unix_inq_len(struct sock *sk)
30683068
struct sk_buff *skb;
30693069
long amount = 0;
30703070

3071-
if (sk->sk_state == TCP_LISTEN)
3071+
if (READ_ONCE(sk->sk_state) == TCP_LISTEN)
30723072
return -EINVAL;
30733073

30743074
spin_lock(&sk->sk_receive_queue.lock);

0 commit comments

Comments
 (0)