Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH v7 0/3] fpga: bounds checks and input validation fixes
@ 2026-05-18 16:52 Sebastian Alba Vives
  2026-05-18 16:52 ` [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Sebastian Alba Vives @ 2026-05-18 16:52 UTC (permalink / raw)
  To: yilun.xu, gregkh
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel, stable,
	Sebastian Alba Vives

This series adds three defensive fixes to FPGA drivers:

Patch 1/3 fixes dfh_get_param_size() in the DFL driver where the loop
bounds check is evaluated before incrementing size, potentially returning
an inflated size that exceeds the feature region boundary.

Patch 2/3 validates the DMA mapping length in afu_ioctl_dma_map() at the
ioctl entry point before passing it down the call chain, preventing
implicit integer truncation in pin_user_pages_fast().

Patch 3/3 fixes mpf_ops_parse_header() in the Microchip SPI FPGA manager
where a zero header_size from the bitstream causes a one-byte read before
the buffer start.

Sebastian Alba Vives (3):
  fpga: dfl: add bounds check in dfh_get_param_size()
  fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  fpga: microchip-spi: fix zero header_size OOB read in
    mpf_ops_parse_header()

 drivers/fpga/dfl-afu-main.c  | 3 +++
 drivers/fpga/dfl.c           | 2 ++
 drivers/fpga/microchip-spi.c | 3 +++
 3 files changed, 8 insertions(+)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
  2026-05-18 16:52 [PATCH v7 0/3] fpga: bounds checks and input validation fixes Sebastian Alba Vives
@ 2026-05-18 16:52 ` Sebastian Alba Vives
  2026-05-18 18:51   ` Greg KH
  2026-05-18 16:52 ` [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
  2026-05-18 16:52 ` [PATCH v7 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() Sebastian Alba Vives
  2 siblings, 1 reply; 6+ messages in thread
From: Sebastian Alba Vives @ 2026-05-18 16:52 UTC (permalink / raw)
  To: yilun.xu, gregkh
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel, stable,
	Sebastian Alba Vives

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: 4747ab89b4a6 ("fpga: dfl: add basic support for DFHv1")
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
Changes in v7:
  - Correct the Fixes: tag commit hash (checkpatch).
    Reported by Xu Yilun.
Changes in v6:
  - Rebase onto linux-next. Add cover letter.
    Suggested by Xu Yilun.
Changes in v5:
  - Add blank line after the new bounds check.
    Suggested by Xu Yilun.
Changes in v2:
  - Use (size > max) instead of (size + DFHv1_PARAM_HDR > max).
    Suggested by Xu Yilun.
---
 drivers/fpga/dfl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 4087a36a0..4c63c7c85 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;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  2026-05-18 16:52 [PATCH v7 0/3] fpga: bounds checks and input validation fixes Sebastian Alba Vives
  2026-05-18 16:52 ` [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
@ 2026-05-18 16:52 ` Sebastian Alba Vives
  2026-05-18 18:52   ` Greg KH
  2026-05-18 16:52 ` [PATCH v7 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() Sebastian Alba Vives
  2 siblings, 1 reply; 6+ messages in thread
From: Sebastian Alba Vives @ 2026-05-18 16:52 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 v7:
  - No changes.
Changes in v6:
  - Rebase onto linux-next. Add cover letter.
    Suggested by Xu Yilun.
Changes in v3:
  - Move validation to afu_ioctl_dma_map() at the ioctl entry point.
    Suggested by Greg Kroah-Hartman.
---
 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 3bf8e7338..097a97eee 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] 6+ messages in thread

* [PATCH v7 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header()
  2026-05-18 16:52 [PATCH v7 0/3] fpga: bounds checks and input validation fixes Sebastian Alba Vives
  2026-05-18 16:52 ` [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
  2026-05-18 16:52 ` [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
@ 2026-05-18 16:52 ` Sebastian Alba Vives
  2 siblings, 0 replies; 6+ messages in thread
From: Sebastian Alba Vives @ 2026-05-18 16:52 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 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: 5f8d4a900830 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
Changes in v7:
  - Correct the Fixes: tag commit hash and wrap commit message
    at 75 columns (checkpatch).
Changes in v6:
  - Rebase onto linux-next. Add cover letter.
    Suggested by Xu Yilun.
Changes in v5:
  - Drop redundant count check since initial_header_size = 71 already
    guarantees the buffer covers MPF_HEADER_SIZE_OFFSET.
    Suggested by Xu Yilun.
---
 drivers/fpga/microchip-spi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea86..cc8f6d7bb 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -116,6 +116,9 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	}
 
 	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
+	if (!header_size)
+		return -EINVAL;
+
 	if (header_size > count) {
 		info->header_size = header_size;
 		return -EAGAIN;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
  2026-05-18 16:52 ` [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
@ 2026-05-18 18:51   ` Greg KH
  0 siblings, 0 replies; 6+ messages in thread
From: Greg KH @ 2026-05-18 18:51 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: yilun.xu, linux-fpga, conor.dooley, mdf, linux-kernel, stable

On Mon, May 18, 2026 at 10:52:16AM -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: 4747ab89b4a6 ("fpga: dfl: add basic support for DFHv1")
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
> Changes in v7:
>   - Correct the Fixes: tag commit hash (checkpatch).
>     Reported by Xu Yilun.
> Changes in v6:
>   - Rebase onto linux-next. Add cover letter.
>     Suggested by Xu Yilun.
> Changes in v5:
>   - Add blank line after the new bounds check.
>     Suggested by Xu Yilun.
> Changes in v2:
>   - Use (size > max) instead of (size + DFHv1_PARAM_HDR > max).
>     Suggested by Xu Yilun.
> ---
>  drivers/fpga/dfl.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 4087a36a0..4c63c7c85 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;
> -- 
> 2.43.0
> 
> 

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- You have marked a patch with a "Fixes:" tag for a commit that is in an
  older released kernel, yet you do not have a cc: stable line in the
  signed-off-by area at all, which means that the patch will not be
  applied to any older kernel releases.  To properly fix this, please
  follow the documented rules in the
  Documentation/process/stable-kernel-rules.rst file for how to resolve
  this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  2026-05-18 16:52 ` [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
@ 2026-05-18 18:52   ` Greg KH
  0 siblings, 0 replies; 6+ messages in thread
From: Greg KH @ 2026-05-18 18:52 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: yilun.xu, linux-fpga, conor.dooley, mdf, linux-kernel, stable

On Mon, May 18, 2026 at 10:52:17AM -0600, Sebastian Alba Vives wrote:
> 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 v7:
>   - No changes.

Why no cc: stable?

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-05-18 18:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 16:52 [PATCH v7 0/3] fpga: bounds checks and input validation fixes Sebastian Alba Vives
2026-05-18 16:52 ` [PATCH v7 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
2026-05-18 18:51   ` Greg KH
2026-05-18 16:52 ` [PATCH v7 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
2026-05-18 18:52   ` Greg KH
2026-05-18 16:52 ` [PATCH v7 3/3] fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() Sebastian Alba Vives

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox