Re: [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size()

Xu Yilun
2026-04-07T09:13:29Z

On Thu, Apr 02, 2026 at 06:54:44AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
>
> 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 re-check after the size increment to ensure the returned
> size never exceeds the feature boundary.
>
> Fixes: a80a4b2b2e4f ("fpga: dfl: add support for DFHv1")
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
> drivers/fpga/dfl.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 4087a36..0f0889a 100644
> --- a/drivers/fpga/dfl.c
> +++ b/drivers/fpga/dfl.c
> @@ -1133,6 +1133,9 @@ static int dfh_get_param_size(void __iomem *dfh_base, resource_size_t max)
>
> size += next * sizeof(u64);
>
> + if (size + DFHv1_PARAM_HDR > max)
> + return -EINVAL;

Seems (size + DFHv1_PARAM_HDR > max) is to ensure we don't handle the
next overflowed parameter header. But here we only need to ensure the
current parameter block within boundary. If we end up at this block,
should not care about next parameter header.

> +
> if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v))
> return size;
> }

------8<------

diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 4087a36a0571..ac958b80c8cd 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -1132,6 +1132,8 @@ static int dfh_get_param_size(void __iomem *dfh_base, resource_size_t max)
return -EINVAL;

size += next * sizeof(u64);
+ if (size > max)
+ return -EINVAL;

if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v))
return size;

Thanks,
Yilun