linux/net/tipc
Tuong Lien 5391a87751 tipc: fix successful connect() but timed out
In commit 9546a0b7ce ("tipc: fix wrong connect() return code"), we
fixed the issue with the 'connect()' that returns zero even though the
connecting has failed by waiting for the connection to be 'ESTABLISHED'
really. However, the approach has one drawback in conjunction with our
'lightweight' connection setup mechanism that the following scenario
can happen:

          (server)                        (client)

   +- accept()|                      |             wait_for_conn()
   |          |                      |connect() -------+
   |          |<-------[SYN]---------|                 > sleeping
   |          |                      *CONNECTING       |
   |--------->*ESTABLISHED           |                 |
              |--------[ACK]-------->*ESTABLISHED      > wakeup()
        send()|--------[DATA]------->|\                > wakeup()
        send()|--------[DATA]------->| |               > wakeup()
          .   .          .           . |-> recvq       .
          .   .          .           . |               .
        send()|--------[DATA]------->|/                > wakeup()
       close()|--------[FIN]-------->*DISCONNECTING    |
              *DISCONNECTING         |                 |
              |                      ~~~~~~~~~~~~~~~~~~> schedule()
                                                       | wait again
                                                       .
                                                       .
                                                       | ETIMEDOUT

Upon the receipt of the server 'ACK', the client becomes 'ESTABLISHED'
and the 'wait_for_conn()' process is woken up but not run. Meanwhile,
the server starts to send a number of data following by a 'close()'
shortly without waiting any response from the client, which then forces
the client socket to be 'DISCONNECTING' immediately. When the wait
process is switched to be running, it continues to wait until the timer
expires because of the unexpected socket state. The client 'connect()'
will finally get ‘-ETIMEDOUT’ and force to release the socket whereas
there remains the messages in its receive queue.

Obviously the issue would not happen if the server had some delay prior
to its 'close()' (or the number of 'DATA' messages is large enough),
but any kind of delay would make the connection setup/shutdown "heavy".
We solve this by simply allowing the 'connect()' returns zero in this
particular case. The socket is already 'DISCONNECTING', so any further
write will get '-EPIPE' but the socket is still able to read the
messages existing in its receive queue.

Note: This solution doesn't break the previous one as it deals with a
different situation that the socket state is 'DISCONNECTING' but has no
error (i.e. sk->sk_err = 0).

Fixes: 9546a0b7ce ("tipc: fix wrong connect() return code")
Acked-by: Ying Xue <ying.xue@windriver.com>
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-02-10 10:23:00 +01:00
..
addr.c tipc: initialise addr_trail_end when setting node addresses 2019-08-11 21:40:04 -07:00
addr.h
bcast.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2019-12-22 15:15:05 -08:00
bcast.h tipc: update replicast capability for broadcast send link 2019-11-22 09:29:50 -08:00
bearer.c tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
bearer.h tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
core.c tipc: fix ordering of tipc module init and exit routine 2019-12-06 12:01:09 -08:00
core.h Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2019-11-16 21:51:42 -08:00
crypto.c net/tipc: Replace rcu_swap_protected() with rcu_replace_pointer() 2019-12-12 10:19:40 -08:00
crypto.h tipc: introduce TIPC encryption & authentication 2019-11-08 14:01:59 -08:00
diag.c
discover.c tipc: fix use-after-free in tipc_disc_rcv() 2019-12-10 17:45:04 -08:00
discover.h
eth_media.c tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
group.c tipc: clean up skb list lock handling on send path 2019-08-18 14:01:07 -07:00
group.h
ib_media.c tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
Kconfig tipc: introduce TIPC encryption & authentication 2019-11-08 14:01:59 -08:00
link.c tipc: don't send gap blocks in ACK messages 2019-12-17 14:16:56 -08:00
link.h tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
Makefile tipc: remove meaningless assignment in Makefile 2020-01-08 12:38:54 -08:00
monitor.c tipc: update mon's self addr when node addr generated 2019-11-12 19:45:45 -08:00
monitor.h tipc: update mon's self addr when node addr generated 2019-11-12 19:45:45 -08:00
msg.c tipc: introduce TIPC encryption & authentication 2019-11-08 14:01:59 -08:00
msg.h tipc: introduce TIPC encryption & authentication 2019-11-08 14:01:59 -08:00
name_distr.c tipc: improve throughput between nodes in netns 2019-10-29 17:55:38 -07:00
name_distr.h
name_table.c tipc: fix name table rbtree issues 2019-12-10 17:45:04 -08:00
name_table.h tipc: support in-order name publication events 2019-11-22 09:29:50 -08:00
net.c tipc: make legacy address flag readable over netlink 2019-12-20 21:18:42 -08:00
net.h tipc: make legacy address flag readable over netlink 2019-12-20 21:18:42 -08:00
netlink_compat.c tipc: eliminate KMSAN: uninit-value in __tipc_nl_compat_dumpit error 2020-01-06 13:24:31 -08:00
netlink.c tipc: make legacy address flag readable over netlink 2019-12-20 21:18:42 -08:00
netlink.h net: tipc: allocate attrs locally instead of using genl_family_attrbuf in compat_dumpit() 2019-10-06 15:44:47 +02:00
node.c tipc: make three functions static 2020-02-10 10:23:00 +01:00
node.h tipc: add support for AEAD key setting via netlink 2019-11-08 14:01:59 -08:00
socket.c tipc: fix successful connect() but timed out 2020-02-10 10:23:00 +01:00
socket.h tipc: add trace_events for tipc socket 2018-12-19 11:49:24 -08:00
subscr.c
subscr.h tipc: fix modprobe tipc failed after switch order of device registration 2019-05-20 10:45:43 -07:00
sysctl.c tipc: introduce TIPC encryption & authentication 2019-11-08 14:01:59 -08:00
topsrv.c tipc: add loopback device tracking 2019-08-08 22:11:39 -07:00
topsrv.h
trace.c tipc: remove unneeded semicolon in trace.c 2019-01-17 22:04:43 -08:00
trace.h tipc: add trace_events for tipc bearer 2018-12-19 11:49:25 -08:00
udp_media.c tipc: introduce variable window congestion control 2019-12-10 17:31:15 -08:00
udp_media.h