Skip to content

Commit

Permalink
fix VFIO_USER_DEVICE_GET_REGION_IO_FDS allocation
Browse files Browse the repository at this point in the history
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 <john.levon@nutanix.com>
  • Loading branch information
jlevon committed Oct 1, 2023
1 parent 7da33b5 commit eec40b0
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
13 changes: 9 additions & 4 deletions lib/libvfio-user.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,26 +622,31 @@ 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) {
return -1;
}

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;
Expand Down
28 changes: 28 additions & 0 deletions test/py/test_shadow_ioeventfd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down

0 comments on commit eec40b0

Please sign in to comment.