Commit b465518d authored by Stefano Garzarella's avatar Stefano Garzarella Committed by David S. Miller

vsock/loopback: use only sk_buff_head.lock to protect the packet queue

pkt_list_lock was used before commit 71dc9ec9 ("virtio/vsock:
replace virtio_vsock_pkt with sk_buff") to protect the packet queue.
After that commit we switched to sk_buff and we are using
sk_buff_head.lock in almost every place to protect the packet queue
except in vsock_loopback_work() when we call skb_queue_splice_init().

As reported by syzbot, this caused unlocked concurrent access to the
packet queue between vsock_loopback_work() and
vsock_loopback_cancel_pkt() since it is not holding pkt_list_lock.

With the introduction of sk_buff_head, pkt_list_lock is redundant and
can cause confusion, so let's remove it and use sk_buff_head.lock
everywhere to protect the packet queue access.

Fixes: 71dc9ec9 ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
Cc: bobby.eshleman@bytedance.com
Reported-and-tested-by: syzbot+befff0a9536049e7902e@syzkaller.appspotmail.com
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Reviewed-by: default avatarBobby Eshleman <bobby.eshleman@bytedance.com>
Reviewed-by: default avatarArseniy Krasnov <AVKrasnov@sberdevices.ru>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 62203584
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
struct vsock_loopback { struct vsock_loopback {
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
spinlock_t pkt_list_lock; /* protects pkt_list */
struct sk_buff_head pkt_queue; struct sk_buff_head pkt_queue;
struct work_struct pkt_work; struct work_struct pkt_work;
}; };
...@@ -32,9 +31,7 @@ static int vsock_loopback_send_pkt(struct sk_buff *skb) ...@@ -32,9 +31,7 @@ static int vsock_loopback_send_pkt(struct sk_buff *skb)
struct vsock_loopback *vsock = &the_vsock_loopback; struct vsock_loopback *vsock = &the_vsock_loopback;
int len = skb->len; int len = skb->len;
spin_lock_bh(&vsock->pkt_list_lock);
skb_queue_tail(&vsock->pkt_queue, skb); skb_queue_tail(&vsock->pkt_queue, skb);
spin_unlock_bh(&vsock->pkt_list_lock);
queue_work(vsock->workqueue, &vsock->pkt_work); queue_work(vsock->workqueue, &vsock->pkt_work);
...@@ -113,9 +110,9 @@ static void vsock_loopback_work(struct work_struct *work) ...@@ -113,9 +110,9 @@ static void vsock_loopback_work(struct work_struct *work)
skb_queue_head_init(&pkts); skb_queue_head_init(&pkts);
spin_lock_bh(&vsock->pkt_list_lock); spin_lock_bh(&vsock->pkt_queue.lock);
skb_queue_splice_init(&vsock->pkt_queue, &pkts); skb_queue_splice_init(&vsock->pkt_queue, &pkts);
spin_unlock_bh(&vsock->pkt_list_lock); spin_unlock_bh(&vsock->pkt_queue.lock);
while ((skb = __skb_dequeue(&pkts))) { while ((skb = __skb_dequeue(&pkts))) {
virtio_transport_deliver_tap_pkt(skb); virtio_transport_deliver_tap_pkt(skb);
...@@ -132,7 +129,6 @@ static int __init vsock_loopback_init(void) ...@@ -132,7 +129,6 @@ static int __init vsock_loopback_init(void)
if (!vsock->workqueue) if (!vsock->workqueue)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&vsock->pkt_list_lock);
skb_queue_head_init(&vsock->pkt_queue); skb_queue_head_init(&vsock->pkt_queue);
INIT_WORK(&vsock->pkt_work, vsock_loopback_work); INIT_WORK(&vsock->pkt_work, vsock_loopback_work);
...@@ -156,9 +152,7 @@ static void __exit vsock_loopback_exit(void) ...@@ -156,9 +152,7 @@ static void __exit vsock_loopback_exit(void)
flush_work(&vsock->pkt_work); flush_work(&vsock->pkt_work);
spin_lock_bh(&vsock->pkt_list_lock);
virtio_vsock_skb_queue_purge(&vsock->pkt_queue); virtio_vsock_skb_queue_purge(&vsock->pkt_queue);
spin_unlock_bh(&vsock->pkt_list_lock);
destroy_workqueue(vsock->workqueue); destroy_workqueue(vsock->workqueue);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment