Messages in this thread Patch in this message |  | | From | Sebastian Alba Vives <> | | Subject | [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() | | Date | Fri, 3 Apr 2026 11:57:18 -0600 |
| |
From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
region->length comes from userspace via the DFL_FPGA_PORT_DMA_MAP ioctl as a __u64 value. While the function checks for page alignment and address overflow, there is no upper bound on the length value. When length >> PAGE_SHIFT exceeds INT_MAX, the downstream call to pin_user_pages_fast() (which takes int nr_pages) receives a truncated value.
Add the length validation alongside the existing input checks in afu_dma_map_region(), where all userspace arguments are validated before being passed deeper into the call chain.
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com> --- Changes in v2: - Move validation from afu_dma_pin_pages() to afu_dma_map_region() to validate at the ioctl entry point as suggested by Greg KH - Keep npages as int in afu_dma_pin_pages() (now always safe) drivers/fpga/dfl-afu-dma-region.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c index 0d1f973..7f434a9 100644 --- a/drivers/fpga/dfl-afu-dma-region.c +++ b/drivers/fpga/dfl-afu-dma-region.c @@ -34,13 +34,10 @@ void afu_dma_region_init(struct dfl_feature_dev_data *fdata) static int afu_dma_pin_pages(struct dfl_feature_dev_data *fdata, struct dfl_afu_dma_region *region) { - unsigned long npages = region->length >> PAGE_SHIFT; + int npages = region->length >> PAGE_SHIFT; struct device *dev = &fdata->dev->dev; int ret, pinned; - if (npages > INT_MAX) - return -EINVAL; - ret = account_locked_vm(current->mm, npages, true); if (ret) return ret; @@ -319,6 +316,10 @@ int afu_dma_map_region(struct dfl_feature_dev_data *fdata, if (user_addr + length < user_addr) return -EINVAL; + /* Ensure length does not exceed what pin_user_pages_fast() can handle */ + if (length >> PAGE_SHIFT > INT_MAX) + return -EINVAL; + region = kzalloc(sizeof(*region), GFP_KERNEL); if (!region) return -ENOMEM; -- 2.43.0
|  |