Skip to content

Commit 0e566c8

Browse files
paravmellanoxmstsirkin
authored andcommitted
virtio: Protect vqs list access
VQs may be accessed to mark the device broken while they are created/destroyed. Hence protect the access to the vqs list. Fixes: e2dcdfe ("virtio: virtio_break_device() to mark all virtqueues broken.") Signed-off-by: Parav Pandit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 249f255 commit 0e566c8

File tree

3 files changed

+10
-0
lines changed

3 files changed

+10
-0
lines changed

drivers/virtio/virtio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ int register_virtio_device(struct virtio_device *dev)
355355
virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
356356

357357
INIT_LIST_HEAD(&dev->vqs);
358+
spin_lock_init(&dev->vqs_list_lock);
358359

359360
/*
360361
* device_add() causes the bus infrastructure to look for a matching

drivers/virtio/virtio_ring.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,7 +1755,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
17551755
cpu_to_le16(vq->packed.event_flags_shadow);
17561756
}
17571757

1758+
spin_lock(&vdev->vqs_list_lock);
17581759
list_add_tail(&vq->vq.list, &vdev->vqs);
1760+
spin_unlock(&vdev->vqs_list_lock);
17591761
return &vq->vq;
17601762

17611763
err_desc_extra:
@@ -2229,7 +2231,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
22292231
memset(vq->split.desc_state, 0, vring.num *
22302232
sizeof(struct vring_desc_state_split));
22312233

2234+
spin_lock(&vdev->vqs_list_lock);
22322235
list_add_tail(&vq->vq.list, &vdev->vqs);
2236+
spin_unlock(&vdev->vqs_list_lock);
22332237
return &vq->vq;
22342238

22352239
err_extra:
@@ -2291,7 +2295,9 @@ void vring_del_virtqueue(struct virtqueue *_vq)
22912295
{
22922296
struct vring_virtqueue *vq = to_vvq(_vq);
22932297

2298+
spin_lock(&vq->vq.vdev->vqs_list_lock);
22942299
list_del(&_vq->list);
2300+
spin_unlock(&vq->vq.vdev->vqs_list_lock);
22952301

22962302
if (vq->we_own_ring) {
22972303
if (vq->packed_ring) {
@@ -2386,12 +2392,14 @@ void virtio_break_device(struct virtio_device *dev)
23862392
{
23872393
struct virtqueue *_vq;
23882394

2395+
spin_lock(&dev->vqs_list_lock);
23892396
list_for_each_entry(_vq, &dev->vqs, list) {
23902397
struct vring_virtqueue *vq = to_vvq(_vq);
23912398

23922399
/* Pairs with READ_ONCE() in virtqueue_is_broken(). */
23932400
WRITE_ONCE(vq->broken, true);
23942401
}
2402+
spin_unlock(&dev->vqs_list_lock);
23952403
}
23962404
EXPORT_SYMBOL_GPL(virtio_break_device);
23972405

include/linux/virtio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct virtio_device {
110110
bool config_enabled;
111111
bool config_change_pending;
112112
spinlock_t config_lock;
113+
spinlock_t vqs_list_lock; /* Protects VQs list access */
113114
struct device dev;
114115
struct virtio_device_id id;
115116
const struct virtio_config_ops *config;

0 commit comments

Comments
 (0)