Commit a9bf9c7d authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni
Browse files

af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().



As small optimisation, unix_stream_connect() prefetches the client's
sk->sk_state without unix_state_lock() and checks if it's TCP_CLOSE.

Later, sk->sk_state is checked again under unix_state_lock().

Let's use READ_ONCE() for the first check and TCP_CLOSE directly for
the second check.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent eb0718fb
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -1481,7 +1481,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
	struct sk_buff *skb = NULL;
	long timeo;
	int err;
	int st;

	err = unix_validate_addr(sunaddr, addr_len);
	if (err)
@@ -1571,9 +1570,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,

	   Well, and we have to recheck the state after socket locked.
	 */
	st = sk->sk_state;

	switch (st) {
	switch (READ_ONCE(sk->sk_state)) {
	case TCP_CLOSE:
		/* This is ok... continue with connect */
		break;
@@ -1588,7 +1585,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,

	unix_state_lock_nested(sk, U_LOCK_SECOND);

	if (sk->sk_state != st) {
	if (sk->sk_state != TCP_CLOSE) {
		unix_state_unlock(sk);
		unix_state_unlock(other);
		sock_put(other);