[PATCH 09/11] drm/virtio: avoid an infinite loop

Chia-I Wu olvaffe at gmail.com
Wed Feb 5 18:19:53 UTC 2020


Make sure elemcnt does not exceed the maximum element count in
virtio_gpu_queue_ctrl_sgs.  We should improve our error handling or
impose a size limit on execbuffer, which are TODOs.

Signed-off-by: Chia-I Wu <olvaffe at gmail.com>
Cc: David Riley <davidriley at chromium.org>
---
 drivers/gpu/drm/virtio/virtgpu_drv.h   | 1 +
 drivers/gpu/drm/virtio/virtgpu_ioctl.c | 3 +++
 drivers/gpu/drm/virtio/virtgpu_kms.c   | 2 ++
 drivers/gpu/drm/virtio/virtgpu_vq.c    | 2 +-
 4 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 7e69c06e168ea..f7520feb39d4b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -143,6 +143,7 @@ struct virtio_gpu_framebuffer {
 
 struct virtio_gpu_queue {
 	struct virtqueue *vq;
+	unsigned int max_free;
 	spinlock_t qlock;
 	wait_queue_head_t ack_queue;
 	struct work_struct dequeue_work;
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 205ec4abae2b9..0954f61d2000f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -132,6 +132,9 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
 			goto out_unused_fd;
 	}
 
+	/* XXX virtio_gpu_cmd_submit may fail silently when exbuf->size is
+	 * huge
+	 */
 	buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
 	if (IS_ERR(buf)) {
 		ret = PTR_ERR(buf);
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 2f5773e43557c..e7d5840e432dc 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -170,7 +170,9 @@ int virtio_gpu_init(struct drm_device *dev)
 		goto err_vqs;
 	}
 	vgdev->ctrlq.vq = vqs[0];
+	vgdev->ctrlq.max_free = vqs[0]->num_free;
 	vgdev->cursorq.vq = vqs[1];
+	vgdev->cursorq.max_free = vqs[1]->num_free;
 	ret = virtio_gpu_alloc_vbufs(vgdev);
 	if (ret) {
 		DRM_ERROR("failed to alloc vbufs\n");
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 0bf82cff8da37..725cfe93bcef8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -333,7 +333,7 @@ static bool virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev,
 again:
 	spin_lock(&vgdev->ctrlq.qlock);
 
-	if (!vgdev->vqs_ready) {
+	if (unlikely(!vgdev->vqs_ready || elemcnt > vgdev->ctrlq.max_free)) {
 		spin_unlock(&vgdev->ctrlq.qlock);
 
 		if (fence && vbuf->objs)
-- 
2.25.0.341.g760bfbb309-goog



More information about the dri-devel mailing list