@samitouri / QOSamiQemu / commits / 14f2511f59

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