From cf96a636dc3f93821ee4579ee25729493c149090 Mon Sep 17 00:00:00 2001 From: John Levon Date: Mon, 2 Oct 2023 14:06:38 +0100 Subject: [PATCH] fix VFIO_USER_DEVICE_GET_REGION_IO_FDS allocation (#785) clang-tidy static analysis identified a zero-sized allocation in the case that no ioregionfds had been configured. Fix this issue and add a test for it. Signed-off-by: John Levon Reviewed-by: Thanos Makatos (cherry picked from commit 8d38e8c57923f736ffc8215b7b237c76d240e3b4) --- lib/libvfio-user.c | 13 +++++++++---- test/py/test_shadow_ioeventfd.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index 94524a2f..c01c59a3 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -654,7 +654,8 @@ handle_device_get_region_io_fds(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg) sizeof(vfio_user_sub_region_ioeventfd_t); msg->out.nr_fds = 0; - if (req->argsz >= reply->argsz) { + + if (max_sent_sub_regions > 0 && req->argsz >= reply->argsz) { msg->out.fds = calloc(sizeof(int), max_sent_sub_regions + nr_shadow_reg); if (msg->out.fds == NULL) { @@ -662,18 +663,22 @@ handle_device_get_region_io_fds(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg) } sub_reg = LIST_FIRST(&vfu_reg->subregions); + for (i = 0; i < max_sent_sub_regions; i++) { + int fdi; ioefd = &reply->sub_regions[i].ioeventfd; ioefd->gpa_offset = sub_reg->gpa_offset; ioefd->size = sub_reg->size; - ioefd->fd_index = add_fd_index(msg->out.fds, &msg->out.nr_fds, - sub_reg->fd); + fdi = add_fd_index(msg->out.fds, &msg->out.nr_fds, sub_reg->fd); + ioefd->fd_index = fdi; if (sub_reg->shadow_fd == -1) { ioefd->type = VFIO_USER_IO_FD_TYPE_IOEVENTFD; } else { ioefd->type = VFIO_USER_IO_FD_TYPE_IOEVENTFD_SHADOW; - ioefd->shadow_mem_fd_index = add_fd_index(msg->out.fds, &msg->out.nr_fds, sub_reg->shadow_fd); + fdi = add_fd_index(msg->out.fds, &msg->out.nr_fds, + sub_reg->shadow_fd); + ioefd->shadow_mem_fd_index = fdi; } ioefd->flags = sub_reg->flags; ioefd->datamatch = sub_reg->datamatch; diff --git a/test/py/test_shadow_ioeventfd.py b/test/py/test_shadow_ioeventfd.py index e64c2538..aafa2f63 100644 --- a/test/py/test_shadow_ioeventfd.py +++ b/test/py/test_shadow_ioeventfd.py @@ -33,6 +33,34 @@ import errno +def test_shadow_ioeventfd_none(): + """Test VFIO_USER_DEVICE_GET_REGION_IO_FDS when none are set up.""" + + # server setup + ctx = vfu_create_ctx(flags=LIBVFIO_USER_FLAG_ATTACH_NB) + assert ctx is not None + ret = vfu_setup_region(ctx, index=VFU_PCI_DEV_BAR0_REGION_IDX, size=0x1000, + flags=VFU_REGION_FLAG_RW) + assert ret == 0 + + ret = vfu_realize_ctx(ctx) + assert ret == 0 + + # client + client = connect_client(ctx) + payload = vfio_user_region_io_fds_request( + argsz=len(vfio_user_region_io_fds_reply()) + + len(vfio_user_sub_region_ioeventfd()), flags=0, + index=VFU_PCI_DEV_BAR0_REGION_IDX, count=0) + newfds, ret = msg_fds(ctx, client.sock, VFIO_USER_DEVICE_GET_REGION_IO_FDS, + payload, expect=0) + assert len(newfds) == 0 + reply, ret = vfio_user_region_io_fds_reply.pop_from_buffer(ret) + assert reply.count == 0 + + vfu_destroy_ctx(ctx) + + def test_shadow_ioeventfd(): """Configure a shadow ioeventfd, have the client trigger it, confirm that the server receives the notification and can see the value."""