diff options
author | John Levon <john.levon@nutanix.com> | 2021-11-12 14:44:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-12 14:44:11 +0000 |
commit | 353fee1349a1917e01bda8f225554e7f71939364 (patch) | |
tree | bb746205d79c8e3e5146b89fd30eac18b3e89973 | |
parent | 56842967566dcf4b89514949a6e88ba89eeaf268 (diff) | |
download | libvfio-user-353fee1349a1917e01bda8f225554e7f71939364.zip libvfio-user-353fee1349a1917e01bda8f225554e7f71939364.tar.gz libvfio-user-353fee1349a1917e01bda8f225554e7f71939364.tar.bz2 |
don't assert in dev_get_caps() (#621)
As clients control ->client_max_fds, we should return an error, not assert, if
we can't represent a region's mmap_areas.
Found via AFL++.
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Swapnil Ingle <swapnil.ingle@nutanix.com>
-rw-r--r-- | lib/libvfio-user.c | 11 | ||||
-rw-r--r-- | test/py/test_device_get_region_info.py | 30 |
2 files changed, 36 insertions, 5 deletions
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index 3bbad42..94a3419 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -138,11 +138,12 @@ dev_get_caps(vfu_ctx_t *vfu_ctx, vfu_reg_info_t *vfu_reg, bool is_migr_reg, sparse = (struct vfio_region_info_cap_sparse_mmap*)header; } - /* - * FIXME need to figure out how to break message into smaller messages - * so that we don't exceed client_max_fds - */ - assert(nr_mmap_areas <= vfu_ctx->client_max_fds); + if (nr_mmap_areas > vfu_ctx->client_max_fds) { + vfu_log(vfu_ctx, LOG_DEBUG, "%s: region has nr_mmap_areas=%d, " + "but client only supports %d fds", __func__, + nr_mmap_areas, vfu_ctx->client_max_fds); + return ERROR_INT(ENOSPC); + } *fds = malloc(nr_mmap_areas * sizeof(int)); if (*fds == NULL) { diff --git a/test/py/test_device_get_region_info.py b/test/py/test_device_get_region_info.py index cea3e98..a99f42c 100644 --- a/test/py/test_device_get_region_info.py +++ b/test/py/test_device_get_region_info.py @@ -58,6 +58,25 @@ def test_device_get_region_info_setup(): assert ret == 0 f = tempfile.TemporaryFile() + f.truncate(65536) + + mmap_areas = [(0x1000, 0x1000), + (0x2000, 0x1000), + (0x3000, 0x1000), + (0x4000, 0x1000), + (0x5000, 0x1000), + (0x6000, 0x1000), + (0x7000, 0x1000), + (0x8000, 0x1000), + (0x9000, 0x1000)] + + ret = vfu_setup_region(ctx, index=VFU_PCI_DEV_BAR3_REGION_IDX, + size=0x10000, + flags=(VFU_REGION_FLAG_RW | VFU_REGION_FLAG_MEM), + mmap_areas=mmap_areas, fd=f.fileno(), offset=0x0) + assert ret == 0 + + f = tempfile.TemporaryFile() f.truncate(0x2000) mmap_areas = [(0x1000, 0x1000)] @@ -101,6 +120,17 @@ def test_device_get_region_info_bad_index(): expect=errno.EINVAL) +# python tests use max client fds of 8, but this region has 9 mmap areas. +def test_device_get_region_info_caps_too_few_fds(): + payload = vfio_region_info(argsz=192, flags=0, + index=VFU_PCI_DEV_BAR3_REGION_IDX, cap_offset=0, + size=0, offset=0) + payload = bytes(payload) + b'\0' * (192 - 32) + + msg(ctx, sock, VFIO_USER_DEVICE_GET_REGION_INFO, payload, + expect=errno.ENOSPC) + + def test_device_get_region_info_larger_argsz(): payload = vfio_region_info(argsz=argsz + 8, flags=0, |