aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorswapnili <swapnil.ingle@nutanix.com>2021-01-21 15:38:24 +0100
committerGitHub <noreply@github.com>2021-01-21 15:38:24 +0100
commite899af8f842c9ba2d48fb44b507e90187f2fab47 (patch)
tree3987cf106c923ad52b9605c6486b7868ac3c2cbe /lib
parent4f3ad36fc3956d9c1ca926615301e40134b75d58 (diff)
downloadlibvfio-user-e899af8f842c9ba2d48fb44b507e90187f2fab47.zip
libvfio-user-e899af8f842c9ba2d48fb44b507e90187f2fab47.tar.gz
libvfio-user-e899af8f842c9ba2d48fb44b507e90187f2fab47.tar.bz2
Misc fixes for DMA_MAP region prot (#233)
* Misc fixes for DMA_MAP region prot 1. Validate prot passed in vfu_addr_to_sg() 2. Let user know region prot via vfu_unmap_dma_cb_t Signed-off-by: Swapnil Ingle <swapnil.ingle@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/dma.c10
-rw-r--r--lib/dma.h22
-rw-r--r--lib/libvfio-user.c4
3 files changed, 29 insertions, 7 deletions
diff --git a/lib/dma.c b/lib/dma.c
index 1d6b505..c860154 100644
--- a/lib/dma.c
+++ b/lib/dma.c
@@ -344,6 +344,8 @@ dma_map_region(dma_memory_region_t *region, int prot, size_t offset, size_t len)
mmap_round(&mmap_offset, &mmap_size, region->page_size);
// Do the mmap.
+ // Note: As per mmap(2) manpage, on some hardware architectures
+ // (e.g., i386), PROT_WRITE implies PROT_READ
mmap_base = mmap(NULL, mmap_size, prot, MAP_SHARED,
region->fd, mmap_offset);
if (mmap_base == MAP_FAILED) {
@@ -369,7 +371,7 @@ _dma_addr_sg_split(const dma_controller_t *dma,
dma_sg_t *sg, int max_sg, int prot)
{
int idx;
- int cnt = 0;
+ int cnt = 0, ret;
bool found = true; // Whether the current region is found.
while (found && len > 0) {
@@ -382,7 +384,10 @@ _dma_addr_sg_split(const dma_controller_t *dma,
size_t region_len = MIN(region_end - dma_addr, len);
if (cnt < max_sg) {
- dma_init_sg(dma, sg, dma_addr, region_len, prot, idx);
+ ret = dma_init_sg(dma, sg, dma_addr, region_len, prot, idx);
+ if (ret < 0) {
+ return ret;
+ }
}
cnt++;
@@ -408,6 +413,7 @@ out:
} else if (cnt > max_sg) {
cnt = -cnt - 1;
}
+ errno = 0;
return cnt;
}
diff --git a/lib/dma.h b/lib/dma.h
index d8ff38c..35cda83 100644
--- a/lib/dma.h
+++ b/lib/dma.h
@@ -184,11 +184,17 @@ _dma_mark_dirty(const dma_controller_t *dma, const dma_memory_region_t *region,
}
}
-static inline void
+static inline int
dma_init_sg(const dma_controller_t *dma, dma_sg_t *sg, dma_addr_t dma_addr,
uint32_t len, int prot, int region_index)
{
const dma_memory_region_t *const region = &dma->regions[region_index];
+
+ if ((prot & PROT_WRITE) && !(region->prot & PROT_WRITE)) {
+ errno = EACCES;
+ return -1;
+ }
+
sg->dma_addr = region->dma_addr;
sg->region = region_index;
sg->offset = dma_addr - region->dma_addr;
@@ -197,6 +203,8 @@ dma_init_sg(const dma_controller_t *dma, dma_sg_t *sg, dma_addr_t dma_addr,
_dma_mark_dirty(dma, region, sg);
}
sg->mappable = region->virt_addr != NULL;
+
+ return 0;
}
/* Takes a linear dma address span and returns a sg list suitable for DMA.
@@ -206,7 +214,9 @@ dma_init_sg(const dma_controller_t *dma, dma_sg_t *sg, dma_addr_t dma_addr,
* Returns:
* - On success, number of scatter gather entries created.
* - On failure:
- * -1 if the dma address span is invalid
+ * -1 if
+ * - the DMA address span is invalid
+ * - protection violation (errno=EACCES)
* (-x - 1) if @max_sg is too small, where x is the number of sg entries
* necessary to complete this request.
*/
@@ -216,7 +226,7 @@ dma_addr_to_sg(const dma_controller_t *dma,
dma_sg_t *sg, int max_sg, int prot)
{
static __thread int region_hint;
- int cnt;
+ int cnt, ret;
const dma_memory_region_t *const region = &dma->regions[region_hint];
const dma_addr_t region_end = region->dma_addr + region->size;
@@ -225,7 +235,11 @@ dma_addr_to_sg(const dma_controller_t *dma,
if (likely(max_sg > 0 && len > 0 &&
dma_addr >= region->dma_addr && dma_addr + len <= region_end &&
region_hint < dma->nregions)) {
- dma_init_sg(dma, sg, dma_addr, len, prot, region_hint);
+ ret = dma_init_sg(dma, sg, dma_addr, len, prot, region_hint);
+ if (ret < 0) {
+ return ret;
+ }
+
return 1;
}
// Slow path: search through regions.
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index be310a3..d98994e 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -559,7 +559,8 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map,
return ret;
}
if (vfu_ctx->map_dma != NULL) {
- vfu_ctx->map_dma(vfu_ctx, dma_regions[i].addr, dma_regions[i].size);
+ vfu_ctx->map_dma(vfu_ctx, dma_regions[i].addr, dma_regions[i].size,
+ dma_regions[i].prot);
}
}
return ret;
@@ -1393,6 +1394,7 @@ vfu_addr_to_sg(vfu_ctx_t *vfu_ctx, dma_addr_t dma_addr,
errno = EINVAL;
return -1;
}
+
return dma_addr_to_sg(vfu_ctx->dma, dma_addr, len, sg, max_sg, prot);
}