virtio_gpu_queue_ctrl_sgs() and virtio_gpu_queue_cursor() use wait_event() without timeout when waiting for virtqueue space. If the host device stops processing commands, these waits block indefinitely. Since callers may hold DRM locks, this can make the entire system unresponsive.
Replace wait_event() with wait_event_timeout() using a 5-second timeout, consistent with the existing timeout pattern in the driver. On timeout, clean up and return -ENODEV, following the same error path as drm_dev_enter() failure. Reported-by: syzbot+d6dd6f86d3aaf7eebe7406e45c1c6e549453f...@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224 Reported-by: syzbot+908bd910da5dd79b88de4cf7baf376cc873a9...@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e Signed-off-by: Ryosuke Yasuoka <[email protected]> --- drivers/gpu/drm/virtio/virtgpu_vq.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 67865810a2e7..05e816a0ae0b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -396,7 +396,16 @@ static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, if (vq->num_free < elemcnt) { spin_unlock(&vgdev->ctrlq.qlock); virtio_gpu_notify(vgdev); - wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= elemcnt); + if (!wait_event_timeout(vgdev->ctrlq.ack_queue, + vq->num_free >= elemcnt, + 5 * HZ)) { + /* The device did not respond */ + if (fence && vbuf->objs) + virtio_gpu_array_unlock_resv(vbuf->objs); + free_vbuf(vgdev, vbuf); + drm_dev_exit(idx); + return -ENODEV; + } goto again; } @@ -566,7 +575,14 @@ static void virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev, ret = virtqueue_add_sgs(vq, sgs, outcnt, 0, vbuf, GFP_ATOMIC); if (ret == -ENOSPC) { spin_unlock(&vgdev->cursorq.qlock); - wait_event(vgdev->cursorq.ack_queue, vq->num_free >= outcnt); + if (!wait_event_timeout(vgdev->cursorq.ack_queue, + vq->num_free >= outcnt, + 5 * HZ)) { + /* The device did not respond */ + free_vbuf(vgdev, vbuf); + drm_dev_exit(idx); + return; + } spin_lock(&vgdev->cursorq.qlock); goto retry; } else { --- base-commit: 5d6919055dec134de3c40167a490f33c74c12581 change-id: 20260512-virtio-gpu_wait_event-e0cdf8675b7c Best regards, -- Ryosuke Yasuoka <[email protected]>

