Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9a59636 authored by Parav Pandit's avatar Parav Pandit Committed by Sasha Levin
Browse files

virtio: Protect vqs list access



[ Upstream commit 0e566c8f0f2e8325e35f6f97e13cde5356b41814 ]

VQs may be accessed to mark the device broken while they are
created/destroyed. Hence protect the access to the vqs list.

Fixes: e2dcdfe9 ("virtio: virtio_break_device() to mark all virtqueues broken.")
Signed-off-by: default avatarParav Pandit <parav@nvidia.com>
Link: https://lore.kernel.org/r/20210721142648.1525924-4-parav@nvidia.com


Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b264e37b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -342,6 +342,7 @@ int register_virtio_device(struct virtio_device *dev)
	virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);

	INIT_LIST_HEAD(&dev->vqs);
	spin_lock_init(&dev->vqs_list_lock);

	/*
	 * device_add() causes the bus infrastructure to look for a matching
+8 −0
Original line number Diff line number Diff line
@@ -1668,7 +1668,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
			cpu_to_le16(vq->packed.event_flags_shadow);
	}

	spin_lock(&vdev->vqs_list_lock);
	list_add_tail(&vq->vq.list, &vdev->vqs);
	spin_unlock(&vdev->vqs_list_lock);
	return &vq->vq;

err_desc_extra:
@@ -2126,7 +2128,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
	memset(vq->split.desc_state, 0, vring.num *
			sizeof(struct vring_desc_state_split));

	spin_lock(&vdev->vqs_list_lock);
	list_add_tail(&vq->vq.list, &vdev->vqs);
	spin_unlock(&vdev->vqs_list_lock);
	return &vq->vq;
}
EXPORT_SYMBOL_GPL(__vring_new_virtqueue);
@@ -2210,7 +2214,9 @@ void vring_del_virtqueue(struct virtqueue *_vq)
	}
	if (!vq->packed_ring)
		kfree(vq->split.desc_state);
	spin_lock(&vq->vq.vdev->vqs_list_lock);
	list_del(&_vq->list);
	spin_unlock(&vq->vq.vdev->vqs_list_lock);
	kfree(vq);
}
EXPORT_SYMBOL_GPL(vring_del_virtqueue);
@@ -2274,10 +2280,12 @@ void virtio_break_device(struct virtio_device *dev)
{
	struct virtqueue *_vq;

	spin_lock(&dev->vqs_list_lock);
	list_for_each_entry(_vq, &dev->vqs, list) {
		struct vring_virtqueue *vq = to_vvq(_vq);
		vq->broken = true;
	}
	spin_unlock(&dev->vqs_list_lock);
}
EXPORT_SYMBOL_GPL(virtio_break_device);

+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct virtio_device {
	bool config_enabled;
	bool config_change_pending;
	spinlock_t config_lock;
	spinlock_t vqs_list_lock; /* Protects VQs list access */
	struct device dev;
	struct virtio_device_id id;
	const struct virtio_config_ops *config;