* [PATCH v5 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
2026-05-04 12:13 [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
@ 2026-05-04 12:13 ` Sebastian Alba Vives
2026-05-04 12:13 ` [PATCH v5 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() Sebastian Alba Vives
2026-05-11 15:19 ` [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Xu Yilun
2 siblings, 0 replies; 4+ messages in thread
From: Sebastian Alba Vives @ 2026-05-04 12:13 UTC (permalink / raw)
To: yilun.xu, gregkh
Cc: linux-fpga, conor.dooley, mdf, linux-kernel, stable,
Sebastian Alba Vives
afu_ioctl_dma_map() accepts a 64-bit length from userspace via
DFL_FPGA_PORT_DMA_MAP ioctl without an upper bound check. The value
is passed to afu_dma_pin_pages() where npages is derived as
length >> PAGE_SHIFT and passed to pin_user_pages_fast() which takes
int nr_pages, causing implicit truncation if length is very large.
Validate map.length at the ioctl entry point before calling
afu_dma_map_region(), rejecting values whose page count exceeds
INT_MAX.
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
Changes in v5:
- Resubmit as full series with v5 corrections to patches 1/3 and 3/3.
No changes to this patch.
Changes in v4:
- Resubmit as full series per maintainer request.
Changes in v3:
- Move validation to afu_ioctl_dma_map() at the ioctl entry point,
before crossing the userspace/kernel boundary, instead of deep in
afu_dma_pin_pages(). Suggested by Greg Kroah-Hartman.
Changes in v2:
- Added cap at INT_MAX in afu_dma_pin_pages() (superseded by v3).
---
drivers/fpga/dfl-afu-main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 3bf8e73..097a97e 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -723,6 +723,9 @@ afu_ioctl_dma_map(struct dfl_feature_dev_data *fdata, void __user *arg)
if (map.argsz < minsz || map.flags)
return -EINVAL;
+ if (map.length >> PAGE_SHIFT > (u64)INT_MAX)
+ return -EINVAL;
+
ret = afu_dma_map_region(fdata, map.user_addr, map.length, &map.iova);
if (ret)
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v5 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header()
2026-05-04 12:13 [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
2026-05-04 12:13 ` [PATCH v5 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
@ 2026-05-04 12:13 ` Sebastian Alba Vives
2026-05-11 15:19 ` [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Xu Yilun
2 siblings, 0 replies; 4+ messages in thread
From: Sebastian Alba Vives @ 2026-05-04 12:13 UTC (permalink / raw)
To: yilun.xu, gregkh
Cc: linux-fpga, conor.dooley, mdf, linux-kernel, stable,
Sebastian Alba Vives
mpf_ops_parse_header() reads header_size from the bitstream at
MPF_HEADER_SIZE_OFFSET (24). When header_size is zero, the expression
*(buf + header_size - 1) reads one byte before the buffer start.
Since initial_header_size is set to 71 in mpf_ops, the fpga-mgr core
guarantees the buffer is always large enough to reach MPF_HEADER_SIZE_OFFSET.
The only real gap is the zero header_size case, which cannot be resolved
by providing a larger buffer, so return -EINVAL.
Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
Changes in v5:
- Drop the count < MPF_HEADER_SIZE_OFFSET + 1 check. Since
initial_header_size = 71 is set in mpf_ops, the fpga-mgr core
already guarantees the buffer covers MPF_HEADER_SIZE_OFFSET.
Only the zero header_size case remains as a genuine bug.
Suggested by Xu Yilun.
Changes in v4:
- Reduce to two minimal fixes: minimum count check and -EINVAL for
zero header_size (superseded by v5).
Changes in v3:
- Add overflow check for 32-bit in component size loop.
Changes in v2:
- Return -EINVAL for header_size == 0, -EAGAIN in block loop,
add count check before MPF_HEADER_SIZE_OFFSET read.
---
drivers/fpga/microchip-spi.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index dca1a5d..cc8f6d7 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -115,9 +115,6 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
return -EINVAL;
}
- if (count < MPF_HEADER_SIZE_OFFSET + 1)
- return -EINVAL;
-
header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
if (!header_size)
return -EINVAL;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
2026-05-04 12:13 [PATCH v5 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
2026-05-04 12:13 ` [PATCH v5 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
2026-05-04 12:13 ` [PATCH v5 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() Sebastian Alba Vives
@ 2026-05-11 15:19 ` Xu Yilun
2 siblings, 0 replies; 4+ messages in thread
From: Xu Yilun @ 2026-05-11 15:19 UTC (permalink / raw)
To: Sebastian Alba Vives
Cc: gregkh, linux-fpga, conor.dooley, mdf, linux-kernel, stable
On Mon, May 04, 2026 at 06:13:30AM -0600, Sebastian Alba Vives wrote:
> dfh_get_param_size() can return a parameter size larger than the feature
> region because the loop bounds check is evaluated before incrementing
> size. If the EOP (End of Parameters) bit is set in the same iteration,
> the inflated size is returned without re-validation against max.
>
> This can cause create_feature_instance() to call memcpy_fromio() with a
> size exceeding the ioremap'd region when a malicious FPGA device provides
> crafted DFHv1 parameter headers.
>
> Add a bounds check after the size increment to ensure the accumulated
> size never exceeds the feature boundary.
>
> Fixes: a80a4b2b2e4f ("fpga: dfl: add support for DFHv1")
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
> Changes in v5:
> - Add blank line after the new bounds check.
> Suggested by Xu Yilun.
> Changes in v4:
> - Resubmit as full series per maintainer request.
> Changes in v2:
> - Use (size > max) instead of (size + DFHv1_PARAM_HDR > max).
> Suggested by Xu Yilun.
> ---
> drivers/fpga/dfl.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 81d7a68..4c63c7c 100644
> --- a/drivers/fpga/dfl.c
> +++ b/drivers/fpga/dfl.c
> @@ -1134,6 +1134,7 @@ static int dfh_get_param_size(void __iomem *dfh_base, resource_size_t max)
> size += next * sizeof(u64);
> if (size > max)
> return -EINVAL;
> +
Hey, please provide a patch that can apply to linux-next. I can do
nothing to your series. Please read Documentation/process/ before
submit.
Also, please make a cover-letter (Patch #0) when you make the patch
series.
> if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v))
> return size;
> }
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread