diff options
author | John Levon <john.levon@nutanix.com> | 2021-11-24 23:59:24 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-24 23:59:24 +0000 |
commit | 02174878b1f7a70d3ac09c50c12799df0a1f9406 (patch) | |
tree | 62cdd8b99de889d310a65ddbdf2ad5b5257f403d /lib | |
parent | d8a08f1a18370bcad4fa99a16bdbfc63dbbd35ad (diff) | |
download | libvfio-user-02174878b1f7a70d3ac09c50c12799df0a1f9406.zip libvfio-user-02174878b1f7a70d3ac09c50c12799df0a1f9406.tar.gz libvfio-user-02174878b1f7a70d3ac09c50c12799df0a1f9406.tar.bz2 |
verify region is mapped before acquiring dirty bitmap (#627)
DMA regions not mapped by the server are not dirty tracked (the client must
track changes via handling VFIO_USER_DMA_WRITE), but we weren't correctly
enforcing this, which could segfault when ->dirty_bitmap was NULL.
Found via AFL++.
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/dma.c | 12 |
1 files changed, 12 insertions, 0 deletions
@@ -285,6 +285,8 @@ get_bitmap_size(size_t region_size, size_t pgsize) static int dirty_page_logging_start_on_region(dma_memory_region_t *region, size_t pgsize) { + assert(region->fd != -1); + ssize_t size = get_bitmap_size(region->info.iova.iov_len, pgsize); if (size < 0) { return size; @@ -511,6 +513,11 @@ dma_controller_dirty_page_logging_start(dma_controller_t *dma, size_t pgsize) for (i = 0; i < (size_t)dma->nregions; i++) { dma_memory_region_t *region = &dma->regions[i]; + + if (region->fd == -1) { + continue; + } + if (dirty_page_logging_start_on_region(region, pgsize) < 0) { int _errno = errno; size_t j; @@ -594,6 +601,11 @@ dma_controller_dirty_page_get(dma_controller_t *dma, vfu_dma_addr_t addr, region = &dma->regions[sg.region]; + if (region->fd == -1) { + vfu_log(dma->vfu_ctx, LOG_ERR, "region %d is not mapped", sg.region); + return ERROR_INT(EINVAL); + } + /* * TODO race condition between resetting bitmap and user calling * vfu_map_sg/vfu_unmap_sg(). |