• Wei Wang's avatar
    tcp: avoid fastopen API to be used on AF_UNSPEC · ba615f67
    Wei Wang authored
    Fastopen API should be used to perform fastopen operations on the TCP
    socket. It does not make sense to use fastopen API to perform disconnect
    by calling it with AF_UNSPEC. The fastopen data path is also prone to
    race conditions and bugs when using with AF_UNSPEC.
    
    One issue reported and analyzed by Vegard Nossum is as follows:
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Thread A:                            Thread B:
    ------------------------------------------------------------------------
    sendto()
     - tcp_sendmsg()
         - sk_stream_memory_free() = 0
             - goto wait_for_sndbuf
    	     - sk_stream_wait_memory()
    	        - sk_wait_event() // sleep
              |                          sendto(flags=MSG_FASTOPEN, dest_addr=AF_UNSPEC)
    	  |                           - tcp_sendmsg()
    	  |                              - tcp_sendmsg_fastopen()
    	  |                                 - __inet_stream_connect()
    	  |                                    - tcp_disconnect() //because of AF_UNSPEC
    	  |                                       - tcp_transmit_skb()// send RST
    	  |                                    - return 0; // no reconnect!
    	  |                           - sk_stream_wait_connect()
    	  |                                 - sock_error()
    	  |                                    - xchg(&sk->sk_err, 0)
    	  |                                    - return -ECONNRESET
    	- ... // wake up, see sk->sk_err == 0
        - skb_entail() on TCP_CLOSE socket
    
    If the connection is reopened then we will send a brand new SYN packet
    after thread A has already queued a buffer. At this point I think the
    socket internal state (sequence numbers etc.) becomes messed up.
    
    When the new connection is closed, the FIN-ACK is rejected because the
    sequence number is outside the window. The other side tries to
    retransmit,
    but __tcp_retransmit_skb() calls tcp_trim_head() on an empty skb which
    corrupts the skb data length and hits a BUG() in copy_and_csum_bits().
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    Hence, this patch adds a check for AF_UNSPEC in the fastopen data path
    and return EOPNOTSUPP to user if such case happens.
    
    Fixes: cf60af03 ("tcp: Fast Open client - sendmsg(MSG_FASTOPEN)")
    Reported-by: default avatarVegard Nossum <vegard.nossum@oracle.com>
    Signed-off-by: default avatarWei Wang <weiwan@google.com>
    Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    ba615f67
Name
Last commit
Last update
Documentation Loading commit data...
arch Loading commit data...
block Loading commit data...
certs Loading commit data...
crypto Loading commit data...
drivers Loading commit data...
firmware Loading commit data...
fs Loading commit data...
include Loading commit data...
init Loading commit data...
ipc Loading commit data...
kernel Loading commit data...
lib Loading commit data...
mm Loading commit data...
net Loading commit data...
samples Loading commit data...
scripts Loading commit data...
security Loading commit data...
sound Loading commit data...
tools Loading commit data...
usr Loading commit data...
virt Loading commit data...
.cocciconfig Loading commit data...
.get_maintainer.ignore Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
.mailmap Loading commit data...
COPYING Loading commit data...
CREDITS Loading commit data...
Kbuild Loading commit data...
Kconfig Loading commit data...
MAINTAINERS Loading commit data...
Makefile Loading commit data...
README Loading commit data...