Commit 1c5fae9c9a092574398a17facc31c533791ef232

Authored by Stefano Garzarella
Committed by David S. Miller
1 parent 49c2547b82

vsock: fix locking in vsock_shutdown()

In vsock_shutdown() we touched some socket fields without holding the
socket lock, such as 'state' and 'sk_flags'.

Also, after the introduction of multi-transport, we are accessing
'vsk->transport' in vsock_send_shutdown() without holding the lock
and this call can be made while the connection is in progress, so
the transport can change in the meantime.

To avoid issues, we hold the socket lock when we enter in
vsock_shutdown() and release it when we leave.

Among the transports that implement the 'shutdown' callback, only
hyperv_transport acquired the lock. Since the caller now holds it,
we no longer take it.

Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 5 additions and 7 deletions Side-by-side Diff

net/vmw_vsock/af_vsock.c
... ... @@ -943,10 +943,12 @@
943 943 */
944 944  
945 945 sk = sock->sk;
  946 +
  947 + lock_sock(sk);
946 948 if (sock->state == SS_UNCONNECTED) {
947 949 err = -ENOTCONN;
948 950 if (sk->sk_type == SOCK_STREAM)
949   - return err;
  951 + goto out;
950 952 } else {
951 953 sock->state = SS_DISCONNECTING;
952 954 err = 0;
953 955  
... ... @@ -955,10 +957,8 @@
955 957 /* Receive and send shutdowns are treated alike. */
956 958 mode = mode & (RCV_SHUTDOWN | SEND_SHUTDOWN);
957 959 if (mode) {
958   - lock_sock(sk);
959 960 sk->sk_shutdown |= mode;
960 961 sk->sk_state_change(sk);
961   - release_sock(sk);
962 962  
963 963 if (sk->sk_type == SOCK_STREAM) {
964 964 sock_reset_flag(sk, SOCK_DONE);
... ... @@ -966,6 +966,8 @@
966 966 }
967 967 }
968 968  
  969 +out:
  970 + release_sock(sk);
969 971 return err;
970 972 }
971 973  
net/vmw_vsock/hyperv_transport.c
... ... @@ -474,14 +474,10 @@
474 474  
475 475 static int hvs_shutdown(struct vsock_sock *vsk, int mode)
476 476 {
477   - struct sock *sk = sk_vsock(vsk);
478   -
479 477 if (!(mode & SEND_SHUTDOWN))
480 478 return 0;
481 479  
482   - lock_sock(sk);
483 480 hvs_shutdown_lock_held(vsk->trans, mode);
484   - release_sock(sk);
485 481 return 0;
486 482 }
487 483