From: "Longpeng(Mike)" longpeng2@huawei.com
stable inclusion from linux-4.19.198 commit 0ea3919ffdb946390669b89e2437e0a70e8581be
--------------------------------
[ Upstream commit c7ff9cff70601ea19245d997bb977344663434c7 ]
The client's sk_state will be set to TCP_ESTABLISHED if the server replay the client's connect request.
However, if the client has pending signal, its sk_state will be set to TCP_CLOSE without notify the server, so the server will hold the corrupt connection.
client server
1. sk_state=TCP_SYN_SENT | 2. call ->connect() | 3. wait reply | | 4. sk_state=TCP_ESTABLISHED | 5. insert to connected list | 6. reply to the client 7. sk_state=TCP_ESTABLISHED | 8. insert to connected list | 9. *signal pending* <--------------------- the user kill client 10. sk_state=TCP_CLOSE | client is exiting... | 11. call ->release() | virtio_transport_close if (!(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_CLOSING)) return true; *return at here, the server cannot notice the connection is corrupt*
So the client should notify the peer in this case.
Cc: David S. Miller davem@davemloft.net Cc: Jakub Kicinski kuba@kernel.org Cc: Jorgen Hansen jhansen@vmware.com Cc: Norbert Slusarek nslusarek@gmx.net Cc: Andra Paraschiv andraprs@amazon.com Cc: Colin Ian King colin.king@canonical.com Cc: David Brazdil dbrazdil@google.com Cc: Alexander Popov alex.popov@linux.com Suggested-by: Stefano Garzarella sgarzare@redhat.com Link: https://lkml.org/lkml/2021/5/17/418 Signed-off-by: lixianming lixianming5@huawei.com Signed-off-by: Longpeng(Mike) longpeng2@huawei.com Reviewed-by: Stefano Garzarella sgarzare@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/vmw_vsock/af_vsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index aceafec612a8f..2d31fce5c2185 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1225,7 +1225,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
if (signal_pending(current)) { err = sock_intr_errno(timeout); - sk->sk_state = TCP_CLOSE; + sk->sk_state = sk->sk_state == TCP_ESTABLISHED ? TCP_CLOSING : TCP_CLOSE; sock->state = SS_UNCONNECTED; vsock_transport_cancel_pkt(vsk); goto out_wait;