With the current code, when vsock_dequeue_accept() is removing a sock from the list, nothing prevents vsock_enqueue_accept() from adding a new sock into the list concurrently. We should add a lock to protect the list.
Signed-off-by: Dexuan Cui <de...@microsoft.com> Cc: Andy King <ack...@vmware.com> Cc: Dmitry Torokhov <d...@vmware.com> Cc: George Zhang <georgezh...@vmware.com> Cc: Jorgen Hansen <jhan...@vmware.com> Cc: Reilly Grant <gra...@vmware.com> Cc: Asias He <as...@redhat.com> Cc: Stefan Hajnoczi <stefa...@redhat.com> Cc: Vitaly Kuznetsov <vkuzn...@redhat.com> Cc: Cathy Avery <cav...@redhat.com> Cc: K. Y. Srinivasan <k...@microsoft.com> Cc: Haiyang Zhang <haiya...@microsoft.com> Cc: Stephen Hemminger <sthem...@microsoft.com> --- net/vmw_vsock/af_vsock.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index dfc8c51e..b7b2c66 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -126,6 +126,7 @@ static struct proto vsock_proto = { static const struct vsock_transport *transport; static DEFINE_MUTEX(vsock_register_mutex); +static DEFINE_SPINLOCK(vsock_accept_queue_lock); /**** EXPORTS ****/ @@ -406,7 +407,10 @@ void vsock_enqueue_accept(struct sock *listener, struct sock *connected) sock_hold(connected); sock_hold(listener); + + spin_lock(&vsock_accept_queue_lock); list_add_tail(&vconnected->accept_queue, &vlistener->accept_queue); + spin_unlock(&vsock_accept_queue_lock); } EXPORT_SYMBOL_GPL(vsock_enqueue_accept); @@ -423,7 +427,10 @@ static struct sock *vsock_dequeue_accept(struct sock *listener) vconnected = list_entry(vlistener->accept_queue.next, struct vsock_sock, accept_queue); + spin_lock(&vsock_accept_queue_lock); list_del_init(&vconnected->accept_queue); + spin_unlock(&vsock_accept_queue_lock); + sock_put(listener); /* The caller will need a reference on the connected socket so we let * it call sock_put(). -- 2.7.4