• Kuniyuki Iwashima's avatar
    af_unix: Set sk->sk_state under unix_state_lock() for truly disconencted peer. · 26bfb8b5
    Kuniyuki Iwashima authored
    When a SOCK_DGRAM socket connect()s to another socket, the both sockets'
    sk->sk_state are changed to TCP_ESTABLISHED so that we can register them
    to BPF SOCKMAP.
    
    When the socket disconnects from the peer by connect(AF_UNSPEC), the state
    is set back to TCP_CLOSE.
    
    Then, the peer's state is also set to TCP_CLOSE, but the update is done
    locklessly and unconditionally.
    
    Let's say socket A connect()ed to B, B connect()ed to C, and A disconnects
    from B.
    
    After the first two connect()s, all three sockets' sk->sk_state are
    TCP_ESTABLISHED:
    
      $ ss -xa
      Netid State  Recv-Q Send-Q  Local Address:Port  Peer Address:PortProcess
      u_dgr ESTAB  0      0       @A 641              * 642
      u_dgr ESTAB  0      0       @B 642              * 643
      u_dgr ESTAB  0      0       @C 643              * 0
    
    And after the disconnect, B's state is TCP_CLOSE even though it's still
    connected to C and C's state is TCP_ESTABLISHED.
    
      $ ss -xa
      Netid State  Recv-Q Send-Q  Local Address:Port  Peer Address:PortProcess
      u_dgr UNCONN 0      0       @A 641              * 0
      u_dgr UNCONN 0      0       @B 642              * 643
      u_dgr ESTAB  0      0       @C 643              * 0
    
    In this case, we cannot register B to SOCKMAP.
    
    So, when a socket disconnects from the peer, we should not set TCP_CLOSE to
    the peer if the peer is connected to yet another socket, and this must be
    done under unix_state_lock().
    
    Note that we use WRITE_ONCE() for sk->sk_state as there are many lockless
    readers.  These data-races will be fixed in the following patches.
    
    Fixes: 83301b53 ("af_unix: Set TCP_ESTABLISHED for datagram sockets too")
    Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
    Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
    26bfb8b5
af_unix.c 86.7 KB