hw/display/virtio-gpu: Avoid creating empty udmabuf
The virtio specification allows creating a blob without backing storage attached. However, virtio-gpu attempts to create an empty udmabuf for such a blob. The ioctl fails with EINVAL and emits a spurious warning. Avoid the invalid ioctl. Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob") Fixes: f66767f75c9c ("virtio-gpu: add virtio-gpu/blob vmstate subsection") Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260825-dmabuf-v2-1-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
Akihiko Odaki committed
Aug 25, 2026 at 16:28 UTC
14f2511f5952517a7daae6dc5986e8439f2bbb66
1 file changed
+49
-45
hw/display/virtio-gpu.c
+49
-45
@@ -363,27 +363,29 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
363
res->resource_id = cblob.resource_id;
364
res->blob_size = cblob.size;
365
366
- ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
367
- cmd, &res->addrs, &res->iov,
368
- &res->iov_cnt);
369
- if (ret < 0) {
370
- cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
371
- g_free(res);
372
- return;
373
- }
366
+ if (cblob.nr_entries) {
367
+ ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
368
+ cmd, &res->addrs, &res->iov,
369
+ &res->iov_cnt);
370
+ if (ret < 0) {
371
+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
372
+ g_free(res);
373
+ return;
374
+ }
375
375
- if (res->iov_cnt > 0 &&
376
- iov_size(res->iov, res->iov_cnt) < res->blob_size) {
377
- qemu_log_mask(LOG_GUEST_ERROR,
378
- "%s: backing storage smaller than blob size\n",
379
- __func__);
380
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
381
- virtio_gpu_cleanup_mapping(g, res);
382
- g_free(res);
383
- return;
376
+ if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
377
+ qemu_log_mask(LOG_GUEST_ERROR,
378
+ "%s: backing storage smaller than blob size\n",
379
+ __func__);
380
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
381
+ virtio_gpu_cleanup_mapping(g, res);
382
+ g_free(res);
383
+ return;
384
+ }
385
+
386
+ virtio_gpu_init_udmabuf(res);
387
}
388
386
- virtio_gpu_init_udmabuf(res);
389
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
390
}
391
@@ -1389,8 +1391,6 @@ static bool virtio_gpu_load_restore_mapping(VirtIOGPU *g,
1391
}
1392
}
1393
1392
- QTAILQ_INSERT_HEAD(&g->reslist, res, next);
1393
- g->hostmem += res->hostmem;
1394
return true;
1395
}
1396
@@ -1469,6 +1469,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
1469
return -EINVAL;
1470
}
1471
1472
+ QTAILQ_INSERT_HEAD(&g->reslist, res, next);
1473
+ g->hostmem += hostmem;
1474
resource_id = qemu_get_be32(f);
1475
}
1476
@@ -1528,36 +1530,38 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
1530
res->blob_size = qemu_get_be32(f);
1531
res->iov_cnt = qemu_get_be32(f);
1532
1531
- res->addrs = g_try_new(uint64_t, res->iov_cnt);
1532
- res->iov = g_try_new(struct iovec, res->iov_cnt);
1533
- if (res->iov_cnt && (!res->addrs || !res->iov)) {
1534
- g_free(res->addrs);
1535
- g_free(res->iov);
1536
- g_free(res);
1537
- return -EINVAL;
1538
- }
1533
+ if (res->iov_cnt) {
1534
+ res->addrs = g_try_new(uint64_t, res->iov_cnt);
1535
+ res->iov = g_try_new(struct iovec, res->iov_cnt);
1536
+ if (!res->addrs || !res->iov) {
1537
+ g_free(res->addrs);
1538
+ g_free(res->iov);
1539
+ g_free(res);
1540
+ return -EINVAL;
1541
+ }
1542
1540
- /* read data */
1541
- for (i = 0; i < res->iov_cnt; i++) {
1542
- res->addrs[i] = qemu_get_be64(f);
1543
- res->iov[i].iov_len = qemu_get_be32(f);
1544
- }
1543
+ /* read data */
1544
+ for (i = 0; i < res->iov_cnt; i++) {
1545
+ res->addrs[i] = qemu_get_be64(f);
1546
+ res->iov[i].iov_len = qemu_get_be32(f);
1547
+ }
1548
1546
- if (res->iov_cnt > 0 &&
1547
- iov_size(res->iov, res->iov_cnt) < res->blob_size) {
1548
- g_free(res->addrs);
1549
- g_free(res->iov);
1550
- g_free(res);
1551
- return -EINVAL;
1552
- }
1549
+ if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
1550
+ g_free(res->addrs);
1551
+ g_free(res->iov);
1552
+ g_free(res);
1553
+ return -EINVAL;
1554
+ }
1555
1554
- if (!virtio_gpu_load_restore_mapping(g, res)) {
1555
- g_free(res);
1556
- return -EINVAL;
1557
- }
1556
+ if (!virtio_gpu_load_restore_mapping(g, res)) {
1557
+ g_free(res);
1558
+ return -EINVAL;
1559
+ }
1560
1559
- virtio_gpu_init_udmabuf(res);
1561
+ virtio_gpu_init_udmabuf(res);
1562
+ }
1563
1564
+ QTAILQ_INSERT_HEAD(&g->reslist, res, next);
1565
resource_id = qemu_get_be32(f);
1566
}
1567