Skip to content

Commit 3a5cc90

Browse files
fstorniolodavem330
authored andcommitted
vsock/virtio: remove socket from connected/bound list on shutdown
If the same remote peer, using the same port, tries to connect to a server on a listening port more than once, the server will reject the connection, causing a "connection reset by peer" error on the remote peer. This is due to the presence of a dangling socket from a previous connection in both the connected and bound socket lists. The inconsistency of the above lists only occurs when the remote peer disconnects and the server remains active. This bug does not occur when the server socket is closed: virtio_transport_release() will eventually schedule a call to virtio_transport_do_close() and the latter will remove the socket from the bound and connected socket lists and clear the sk_buff. However, virtio_transport_do_close() will only perform the above actions if it has been scheduled, and this will not happen if the server is processing the shutdown message from a remote peer. To fix this, introduce a call to vsock_remove_sock() when the server is handling a client disconnect. This is to remove the socket from the bound and connected socket lists without clearing the sk_buff. Fixes: 06a8fc7 ("VSOCK: Introduce virtio_vsock_common.ko") Reported-by: Daan De Meyer <daan.j.demeyer@gmail.com> Tested-by: Daan De Meyer <daan.j.demeyer@gmail.com> Co-developed-by: Luigi Leonardi <luigi.leonardi@outlook.com> Signed-off-by: Luigi Leonardi <luigi.leonardi@outlook.com> Signed-off-by: Filippo Storniolo <f.storniolo95@gmail.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7425627 commit 3a5cc90

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

net/vmw_vsock/virtio_transport_common.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,11 +1369,17 @@ virtio_transport_recv_connected(struct sock *sk,
13691369
vsk->peer_shutdown |= RCV_SHUTDOWN;
13701370
if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
13711371
vsk->peer_shutdown |= SEND_SHUTDOWN;
1372-
if (vsk->peer_shutdown == SHUTDOWN_MASK &&
1373-
vsock_stream_has_data(vsk) <= 0 &&
1374-
!sock_flag(sk, SOCK_DONE)) {
1375-
(void)virtio_transport_reset(vsk, NULL);
1376-
virtio_transport_do_close(vsk, true);
1372+
if (vsk->peer_shutdown == SHUTDOWN_MASK) {
1373+
if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
1374+
(void)virtio_transport_reset(vsk, NULL);
1375+
virtio_transport_do_close(vsk, true);
1376+
}
1377+
/* Remove this socket anyway because the remote peer sent
1378+
* the shutdown. This way a new connection will succeed
1379+
* if the remote peer uses the same source port,
1380+
* even if the old socket is still unreleased, but now disconnected.
1381+
*/
1382+
vsock_remove_sock(vsk);
13771383
}
13781384
if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
13791385
sk->sk_state_change(sk);

0 commit comments

Comments
 (0)