Patch "unix: Fix race in SOCK_SEQPACKET's unix_dgram_sendmsg()" has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    unix: Fix race in SOCK_SEQPACKET's unix_dgram_sendmsg()

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     unix-fix-race-in-sock_seqpacket-s-unix_dgram_sendmsg.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f0a3198e8160bccec7acfe4b0e665bd9db878797
Author: Kirill Tkhai <tkhai@xxxxx>
Date:   Tue Dec 13 00:05:53 2022 +0300

    unix: Fix race in SOCK_SEQPACKET's unix_dgram_sendmsg()
    
    [ Upstream commit 3ff8bff704f4de125dca2262e5b5b963a3da1d87 ]
    
    There is a race resulting in alive SOCK_SEQPACKET socket
    may change its state from TCP_ESTABLISHED to TCP_CLOSE:
    
    unix_release_sock(peer)                  unix_dgram_sendmsg(sk)
      sock_orphan(peer)
        sock_set_flag(peer, SOCK_DEAD)
                                               sock_alloc_send_pskb()
                                                 if !(sk->sk_shutdown & SEND_SHUTDOWN)
                                                   OK
                                               if sock_flag(peer, SOCK_DEAD)
                                                 sk->sk_state = TCP_CLOSE
      sk->sk_shutdown = SHUTDOWN_MASK
    
    After that socket sk remains almost normal: it is able to connect, listen, accept
    and recvmsg, while it can't sendmsg.
    
    Since this is the only possibility for alive SOCK_SEQPACKET to change
    the state in such way, we should better fix this strange and potentially
    danger corner case.
    
    Note, that we will return EPIPE here like this is normally done in sock_alloc_send_pskb().
    Originally used ECONNREFUSED looks strange, since it's strange to return
    a specific retval in dependence of race in kernel, when user can't affect on this.
    
    Also, move TCP_CLOSE assignment for SOCK_DGRAM sockets under state lock
    to fix race with unix_dgram_connect():
    
    unix_dgram_connect(other)            unix_dgram_sendmsg(sk)
                                           unix_peer(sk) = NULL
                                           unix_state_unlock(sk)
      unix_state_double_lock(sk, other)
      sk->sk_state  = TCP_ESTABLISHED
      unix_peer(sk) = other
      unix_state_double_unlock(sk, other)
                                           sk->sk_state  = TCP_CLOSED
    
    This patch fixes both of these races.
    
    Fixes: 83301b5367a9 ("af_unix: Set TCP_ESTABLISHED for datagram sockets too")
    Signed-off-by: Kirill Tkhai <tkhai@xxxxx>
    Link: https://lore.kernel.org/r/135fda25-22d5-837a-782b-ceee50e19844@xxxxx
    Signed-off-by: Paolo Abeni <pabeni@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 02fad8e8f4cd..48cc8223b06b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1969,13 +1969,20 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
 			unix_state_lock(sk);
 
 		err = 0;
-		if (unix_peer(sk) == other) {
+		if (sk->sk_type == SOCK_SEQPACKET) {
+			/* We are here only when racing with unix_release_sock()
+			 * is clearing @other. Never change state to TCP_CLOSE
+			 * unlike SOCK_DGRAM wants.
+			 */
+			unix_state_unlock(sk);
+			err = -EPIPE;
+		} else if (unix_peer(sk) == other) {
 			unix_peer(sk) = NULL;
 			unix_dgram_peer_wake_disconnect_wakeup(sk, other);
 
+			sk->sk_state = TCP_CLOSE;
 			unix_state_unlock(sk);
 
-			sk->sk_state = TCP_CLOSE;
 			unix_dgram_disconnected(sk, other);
 			sock_put(other);
 			err = -ECONNREFUSED;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux