public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
@ 2026-04-02 12:54 Sebastian Alba Vives
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-02 12:54 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives

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;
+
 		if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v))
 			return size;
 	}
-- 
2.43.0


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

* [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
  2026-04-02 12:54 [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
@ 2026-04-02 12:54 ` Sebastian Alba Vives
  2026-04-02 16:07   ` Greg KH
                     ` (2 more replies)
  2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-02 12:54 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

In afu_dma_pin_pages(), npages is declared as int but is assigned from
region->length >> PAGE_SHIFT where region->length is u64. This causes
implicit truncation on 64-bit systems when length is large.

The truncated value is then passed to account_locked_vm() (which takes
unsigned long) with implicit sign extension, and to pin_user_pages_fast()
which takes int nr_pages, potentially causing incorrect VM accounting.

Change npages to unsigned long and add a cap to prevent values exceeding
INT_MAX from reaching pin_user_pages_fast().

Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
 drivers/fpga/dfl-afu-dma-region.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
index 87652d5..0d1f973 100644
--- a/drivers/fpga/dfl-afu-dma-region.c
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -34,10 +34,13 @@ 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)
 {
-	int npages = region->length >> PAGE_SHIFT;
+	unsigned long 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;
-- 
2.43.0


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

* [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 12:54 [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
@ 2026-04-02 12:54 ` Sebastian Alba Vives
  2026-04-02 15:03   ` Conor Dooley
                     ` (2 more replies)
  2026-04-07  8:51 ` [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Xu Yilun
  2026-04-07 14:05 ` [PATCH v2 " Sebastian Alba Vives
  3 siblings, 3 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-02 12:54 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

mpf_ops_parse_header() reads several fields from the bitstream file
and uses them as offsets and sizes without validating them against the
buffer size, leading to multiple out-of-bounds read vulnerabilities:

1. When header_size (u8 from file) is 0, the expression
   *(buf + header_size - 1) reads one byte before the buffer.

2. In the block lookup loop, block_id_offset and block_start_offset
   advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
   blocks_num (u8) controlling the count. With a small buffer, these
   offsets exceed count, causing OOB reads via get_unaligned_le32().

3. components_size_start (from file) and component_size_byte_num
   (derived from components_num, u16 from file) are used as offsets
   into buf without validation, allowing arbitrary OOB reads.

Add bounds checks for all three cases: reject header_size of 0,
validate offsets in the block lookup loop, and validate the component
size read offset.

Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
 drivers/fpga/microchip-spi.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea..7954dd0 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -116,7 +116,7 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	}
 
 	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
-	if (header_size > count) {
+	if (!header_size || header_size > count) {
 		info->header_size = header_size;
 		return -EAGAIN;
 	}
@@ -139,6 +139,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	bitstream_start = 0;
 
 	while (blocks_num--) {
+		if (block_id_offset >= count ||
+		    block_start_offset + sizeof(u32) > count)
+			return -EINVAL;
+
 		block_id = *(buf + block_id_offset);
 		block_start = get_unaligned_le32(buf + block_start_offset);
 
@@ -183,6 +187,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 		component_size_byte_off =
 			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
 
+		if (components_size_start + component_size_byte_num +
+		    sizeof(u32) > count)
+			return -EINVAL;
+
 		component_size = get_unaligned_le32(buf +
 						    components_size_start +
 						    component_size_byte_num);
-- 
2.43.0


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

* Re: [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
@ 2026-04-02 15:03   ` Conor Dooley
  2026-04-02 15:16     ` Conor Dooley
  2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
  2026-04-02 16:23   ` [PATCH v3] " Sebastian Alba Vives
  2 siblings, 1 reply; 21+ messages in thread
From: Conor Dooley @ 2026-04-02 15:03 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3213 bytes --]

On Thu, Apr 02, 2026 at 06:54:46AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> mpf_ops_parse_header() reads several fields from the bitstream file
> and uses them as offsets and sizes without validating them against the
> buffer size, leading to multiple out-of-bounds read vulnerabilities:
> 
> 1. When header_size (u8 from file) is 0, the expression
>    *(buf + header_size - 1) reads one byte before the buffer.
> 
> 2. In the block lookup loop, block_id_offset and block_start_offset
>    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
>    blocks_num (u8) controlling the count. With a small buffer, these
>    offsets exceed count, causing OOB reads via get_unaligned_le32().
> 
> 3. components_size_start (from file) and component_size_byte_num
>    (derived from components_num, u16 from file) are used as offsets
>    into buf without validation, allowing arbitrary OOB reads.
> 
> Add bounds checks for all three cases: reject header_size of 0,
> validate offsets in the block lookup loop, and validate the component
> size read offset.
> 
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>

Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
CC: stable@vger.kernel.org

> ---
>  drivers/fpga/microchip-spi.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
> index 6134cea..7954dd0 100644
> --- a/drivers/fpga/microchip-spi.c
> +++ b/drivers/fpga/microchip-spi.c
> @@ -116,7 +116,7 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	}
>  
>  	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
> -	if (header_size > count) {
> +	if (!header_size || header_size > count) {
>  		info->header_size = header_size;
>  		return -EAGAIN;

Hmm, looking at this while feeling less ill, is this actually right?
The function returns EAGAIN to retry with a bigger buffer, but if
header_size is zero, increasing the buffer size will not change that
fact, and it'll go around forever? See the user in
fpga_mgr_parse_header_sg()

>  	}
> @@ -139,6 +139,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	bitstream_start = 0;
>  
>  	while (blocks_num--) {
> +		if (block_id_offset >= count ||
> +		    block_start_offset + sizeof(u32) > count)
> +			return -EINVAL;

And here, why doesn't it return EAGAIN? Isn't the provided section of
the image just too small, so we want to be provided more of it to
actually complete header parsing?

Cheers,
Conor.

> +
>  		block_id = *(buf + block_id_offset);
>  		block_start = get_unaligned_le32(buf + block_start_offset);
>  
> @@ -183,6 +187,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  		component_size_byte_off =
>  			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
>  
> +		if (components_size_start + component_size_byte_num +
> +		    sizeof(u32) > count)
> +			return -EINVAL;
> +
>  		component_size = get_unaligned_le32(buf +
>  						    components_size_start +
>  						    component_size_byte_num);
> -- 
> 2.43.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 15:03   ` Conor Dooley
@ 2026-04-02 15:16     ` Conor Dooley
  0 siblings, 0 replies; 21+ messages in thread
From: Conor Dooley @ 2026-04-02 15:16 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3636 bytes --]

On Thu, Apr 02, 2026 at 04:03:19PM +0100, Conor Dooley wrote:
> On Thu, Apr 02, 2026 at 06:54:46AM -0600, Sebastian Alba Vives wrote:
> > From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> > 
> > mpf_ops_parse_header() reads several fields from the bitstream file
> > and uses them as offsets and sizes without validating them against the
> > buffer size, leading to multiple out-of-bounds read vulnerabilities:
> > 
> > 1. When header_size (u8 from file) is 0, the expression
> >    *(buf + header_size - 1) reads one byte before the buffer.
> > 
> > 2. In the block lookup loop, block_id_offset and block_start_offset
> >    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
> >    blocks_num (u8) controlling the count. With a small buffer, these
> >    offsets exceed count, causing OOB reads via get_unaligned_le32().
> > 
> > 3. components_size_start (from file) and component_size_byte_num
> >    (derived from components_num, u16 from file) are used as offsets
> >    into buf without validation, allowing arbitrary OOB reads.
> > 
> > Add bounds checks for all three cases: reject header_size of 0,
> > validate offsets in the block lookup loop, and validate the component
> > size read offset.
> > 
> > Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> 
> Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
> CC: stable@vger.kernel.org
> 
> > ---
> >  drivers/fpga/microchip-spi.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
> > index 6134cea..7954dd0 100644
> > --- a/drivers/fpga/microchip-spi.c
> > +++ b/drivers/fpga/microchip-spi.c
> > @@ -116,7 +116,7 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
> >  	}
> >  
> >  	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
> > -	if (header_size > count) {
> > +	if (!header_size || header_size > count) {
> >  		info->header_size = header_size;
> >  		return -EAGAIN;
> 
> Hmm, looking at this while feeling less ill, is this actually right?
> The function returns EAGAIN to retry with a bigger buffer, but if
> header_size is zero, increasing the buffer size will not change that
> fact, and it'll go around forever? See the user in
> fpga_mgr_parse_header_sg()

Also, can we trust that count is even big enough for us to read at an
offset of MPF_HEADER_SIZE_OFFSET (24)? Should that be checked before we
even attempt looking at header_size?

> 
> >  	}
> > @@ -139,6 +139,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
> >  	bitstream_start = 0;
> >  
> >  	while (blocks_num--) {
> > +		if (block_id_offset >= count ||
> > +		    block_start_offset + sizeof(u32) > count)
> > +			return -EINVAL;
> 
> And here, why doesn't it return EAGAIN? Isn't the provided section of
> the image just too small, so we want to be provided more of it to
> actually complete header parsing?
> 
> Cheers,
> Conor.
> 
> > +
> >  		block_id = *(buf + block_id_offset);
> >  		block_start = get_unaligned_le32(buf + block_start_offset);
> >  
> > @@ -183,6 +187,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
> >  		component_size_byte_off =
> >  			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
> >  
> > +		if (components_size_start + component_size_byte_num +
> > +		    sizeof(u32) > count)
> > +			return -EINVAL;
> > +
> >  		component_size = get_unaligned_le32(buf +
> >  						    components_size_start +
> >  						    component_size_byte_num);
> > -- 
> > 2.43.0
> > 



[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* [PATCH v2] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
  2026-04-02 15:03   ` Conor Dooley
@ 2026-04-02 15:37   ` Sebastian Alba Vives
  2026-04-02 16:03     ` Greg KH
                       ` (2 more replies)
  2026-04-02 16:23   ` [PATCH v3] " Sebastian Alba Vives
  2 siblings, 3 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-02 15:37 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives, stable

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

mpf_ops_parse_header() reads several fields from the bitstream file
and uses them as offsets and sizes without validating them against the
buffer size, leading to multiple out-of-bounds read vulnerabilities:

1. There is no check that count is large enough to read header_size
   at MPF_HEADER_SIZE_OFFSET (24). Add a minimum count check.

2. When header_size (u8 from file) is 0, the expression
   *(buf + header_size - 1) reads one byte before the buffer.
   Return -EINVAL since retrying with a larger buffer cannot fix
   a zero header_size.

3. In the block lookup loop, block_id_offset and block_start_offset
   advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
   blocks_num (u8) controlling the count. With a small buffer, these
   offsets exceed count, causing OOB reads via get_unaligned_le32().
   Return -EAGAIN since a larger buffer may resolve the issue.

4. components_size_start (from file) and component_size_byte_num
   (derived from components_num, u16 from file) are used as offsets
   into buf without validation, allowing arbitrary OOB reads.

Add bounds checks for all four cases.

Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
 drivers/fpga/microchip-spi.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea..00fa2d6 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -115,7 +115,13 @@ 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;
+
 	if (header_size > count) {
 		info->header_size = header_size;
 		return -EAGAIN;
@@ -139,6 +145,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	bitstream_start = 0;
 
 	while (blocks_num--) {
+		if (block_id_offset >= count ||
+		    block_start_offset + sizeof(u32) > count)
+			return -EAGAIN;
+
 		block_id = *(buf + block_id_offset);
 		block_start = get_unaligned_le32(buf + block_start_offset);
 
@@ -183,6 +193,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 		component_size_byte_off =
 			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
 
+		if (components_size_start + component_size_byte_num +
+		    sizeof(u32) > count)
+			return -EINVAL;
+
 		component_size = get_unaligned_le32(buf +
 						    components_size_start +
 						    component_size_byte_num);
-- 
2.43.0


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

* Re: [PATCH v2] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
@ 2026-04-02 16:03     ` Greg KH
  2026-04-02 16:06     ` Greg KH
  2026-04-02 16:16     ` Conor Dooley
  2 siblings, 0 replies; 21+ messages in thread
From: Greg KH @ 2026-04-02 16:03 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel, stable

On Thu, Apr 02, 2026 at 09:37:52AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> mpf_ops_parse_header() reads several fields from the bitstream file
> and uses them as offsets and sizes without validating them against the
> buffer size, leading to multiple out-of-bounds read vulnerabilities:
> 
> 1. There is no check that count is large enough to read header_size
>    at MPF_HEADER_SIZE_OFFSET (24). Add a minimum count check.
> 
> 2. When header_size (u8 from file) is 0, the expression
>    *(buf + header_size - 1) reads one byte before the buffer.
>    Return -EINVAL since retrying with a larger buffer cannot fix
>    a zero header_size.
> 
> 3. In the block lookup loop, block_id_offset and block_start_offset
>    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
>    blocks_num (u8) controlling the count. With a small buffer, these
>    offsets exceed count, causing OOB reads via get_unaligned_le32().
>    Return -EAGAIN since a larger buffer may resolve the issue.
> 
> 4. components_size_start (from file) and component_size_byte_num
>    (derived from components_num, u16 from file) are used as offsets
>    into buf without validation, allowing arbitrary OOB reads.
> 
> Add bounds checks for all four cases.
> 
> Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
>  drivers/fpga/microchip-spi.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
> index 6134cea..00fa2d6 100644
> --- a/drivers/fpga/microchip-spi.c
> +++ b/drivers/fpga/microchip-spi.c
> @@ -115,7 +115,13 @@ 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;
> +
>  	if (header_size > count) {
>  		info->header_size = header_size;
>  		return -EAGAIN;
> @@ -139,6 +145,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	bitstream_start = 0;
>  
>  	while (blocks_num--) {
> +		if (block_id_offset >= count ||
> +		    block_start_offset + sizeof(u32) > count)
> +			return -EAGAIN;
> +
>  		block_id = *(buf + block_id_offset);
>  		block_start = get_unaligned_le32(buf + block_start_offset);
>  
> @@ -183,6 +193,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  		component_size_byte_off =
>  			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
>  
> +		if (components_size_start + component_size_byte_num +
> +		    sizeof(u32) > count)
> +			return -EINVAL;
> +
>  		component_size = get_unaligned_le32(buf +
>  						    components_size_start +
>  						    component_size_byte_num);
> -- 
> 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:

- This looks like a new version of a previously submitted patch, but you
  did not list below the --- line any changes from the previous version.
  Please read the section entitled "The canonical patch format" in the
  kernel file, Documentation/process/submitting-patches.rst for what
  needs to be done here to properly describe 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] 21+ messages in thread

* Re: [PATCH v2] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
  2026-04-02 16:03     ` Greg KH
@ 2026-04-02 16:06     ` Greg KH
  2026-04-02 16:16     ` Conor Dooley
  2 siblings, 0 replies; 21+ messages in thread
From: Greg KH @ 2026-04-02 16:06 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel, stable

On Thu, Apr 02, 2026 at 09:37:52AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> mpf_ops_parse_header() reads several fields from the bitstream file
> and uses them as offsets and sizes without validating them against the
> buffer size, leading to multiple out-of-bounds read vulnerabilities:

Note, bitstream files are "trusted" so this really isn't a
"vulnerability" just a "someone with hardware permissions sent a stupid
file to the kernel" issue :)

> 1. There is no check that count is large enough to read header_size
>    at MPF_HEADER_SIZE_OFFSET (24). Add a minimum count check.
> 
> 2. When header_size (u8 from file) is 0, the expression
>    *(buf + header_size - 1) reads one byte before the buffer.
>    Return -EINVAL since retrying with a larger buffer cannot fix
>    a zero header_size.
> 
> 3. In the block lookup loop, block_id_offset and block_start_offset
>    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
>    blocks_num (u8) controlling the count. With a small buffer, these
>    offsets exceed count, causing OOB reads via get_unaligned_le32().
>    Return -EAGAIN since a larger buffer may resolve the issue.
> 
> 4. components_size_start (from file) and component_size_byte_num
>    (derived from components_num, u16 from file) are used as offsets
>    into buf without validation, allowing arbitrary OOB reads.
> 
> Add bounds checks for all four cases.
> 
> Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
>  drivers/fpga/microchip-spi.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)

Please look at these review comments:
	https://sashiko.dev/#/patchset/20260402153752.3793055-1-sebasjosue84%40gmail.com
this driver is "odd", but some of those comments seem correct.

thansk,

greg k-h

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

* Re: [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
@ 2026-04-02 16:07   ` Greg KH
       [not found]     ` <CAJD=UNc06upxLFo5eNrvy-UvP1Cu6CEBt-csCgECxAK94pa8mg@mail.gmail.com>
  2026-04-03 17:57   ` [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
  2026-04-07 14:17   ` [PATCH v3 2/3] " Sebastian Alba Vives
  2 siblings, 1 reply; 21+ messages in thread
From: Greg KH @ 2026-04-02 16:07 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel

On Thu, Apr 02, 2026 at 06:54:45AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> In afu_dma_pin_pages(), npages is declared as int but is assigned from
> region->length >> PAGE_SHIFT where region->length is u64. This causes
> implicit truncation on 64-bit systems when length is large.

How can length be that large?  You are shifting down, not up.

> 
> The truncated value is then passed to account_locked_vm() (which takes
> unsigned long) with implicit sign extension, and to pin_user_pages_fast()
> which takes int nr_pages, potentially causing incorrect VM accounting.
> 
> Change npages to unsigned long and add a cap to prevent values exceeding
> INT_MAX from reaching pin_user_pages_fast().
> 
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
>  drivers/fpga/dfl-afu-dma-region.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
> index 87652d5..0d1f973 100644
> --- a/drivers/fpga/dfl-afu-dma-region.c
> +++ b/drivers/fpga/dfl-afu-dma-region.c
> @@ -34,10 +34,13 @@ 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)
>  {
> -	int npages = region->length >> PAGE_SHIFT;
> +	unsigned long npages = region->length >> PAGE_SHIFT;
>  	struct device *dev = &fdata->dev->dev;
>  	int ret, pinned;
>  
> +	if (npages > INT_MAX)
> +		return -EINVAL;

Why INT_MAX?  SHouldn't this be much smaller?

thanks,

greg k-h

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

* Re: [PATCH v2] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
  2026-04-02 16:03     ` Greg KH
  2026-04-02 16:06     ` Greg KH
@ 2026-04-02 16:16     ` Conor Dooley
  2 siblings, 0 replies; 21+ messages in thread
From: Conor Dooley @ 2026-04-02 16:16 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel, stable

[-- Attachment #1: Type: text/plain, Size: 3126 bytes --]

On Thu, Apr 02, 2026 at 09:37:52AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> mpf_ops_parse_header() reads several fields from the bitstream file
> and uses them as offsets and sizes without validating them against the
> buffer size, leading to multiple out-of-bounds read vulnerabilities:
> 
> 1. There is no check that count is large enough to read header_size
>    at MPF_HEADER_SIZE_OFFSET (24). Add a minimum count check.
> 
> 2. When header_size (u8 from file) is 0, the expression
>    *(buf + header_size - 1) reads one byte before the buffer.
>    Return -EINVAL since retrying with a larger buffer cannot fix
>    a zero header_size.
> 
> 3. In the block lookup loop, block_id_offset and block_start_offset
>    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
>    blocks_num (u8) controlling the count. With a small buffer, these
>    offsets exceed count, causing OOB reads via get_unaligned_le32().
>    Return -EAGAIN since a larger buffer may resolve the issue.
> 
> 4. components_size_start (from file) and component_size_byte_num
>    (derived from components_num, u16 from file) are used as offsets
>    into buf without validation, allowing arbitrary OOB reads.
> 
> Add bounds checks for all four cases.
> 
> Fixes: 5f8d4a9008307 ("fpga: microchip-spi: add Microchip MPF FPGA manager")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
> ---
>  drivers/fpga/microchip-spi.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
> index 6134cea..00fa2d6 100644
> --- a/drivers/fpga/microchip-spi.c
> +++ b/drivers/fpga/microchip-spi.c
> @@ -115,7 +115,13 @@ 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;
> +
>  	if (header_size > count) {
>  		info->header_size = header_size;
>  		return -EAGAIN;
> @@ -139,6 +145,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	bitstream_start = 0;
>  
>  	while (blocks_num--) {
> +		if (block_id_offset >= count ||
> +		    block_start_offset + sizeof(u32) > count)
> +			return -EAGAIN;
> +
>  		block_id = *(buf + block_id_offset);
>  		block_start = get_unaligned_le32(buf + block_start_offset);
>  
> @@ -183,6 +193,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  		component_size_byte_off =
>  			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
>  
> +		if (components_size_start + component_size_byte_num +
> +		    sizeof(u32) > count)
> +			return -EINVAL;

I didn't mention it explicitly, but it kinda follows from the other
comment, do we not just want to ask for a bigger buffer here too?

> +
>  		component_size = get_unaligned_le32(buf +
>  						    components_size_start +
>  						    component_size_byte_num);
> -- 
> 2.43.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* [PATCH v3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
  2026-04-02 15:03   ` Conor Dooley
  2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
@ 2026-04-02 16:23   ` Sebastian Alba Vives
  2026-04-07 10:44     ` Xu Yilun
  2 siblings, 1 reply; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-02 16:23 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives, stable

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

mpf_ops_parse_header() reads several fields from the bitstream file
and uses them as offsets and sizes without validating them against the
buffer size, leading to multiple out-of-bounds read vulnerabilities:

1. There is no check that count is large enough to read header_size
   at MPF_HEADER_SIZE_OFFSET (24). Add a minimum count check.

2. When header_size (u8 from file) is 0, the expression
   *(buf + header_size - 1) reads one byte before the buffer.
   Return -EINVAL since retrying with a larger buffer cannot fix
   a zero header_size.

3. In the block lookup loop, block_id_offset and block_start_offset
   advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
   blocks_num (u8) controlling the count. With a small buffer, these
   offsets exceed count, causing OOB reads via get_unaligned_le32().
   Return -EAGAIN with updated header_size so the retry mechanism
   can request a larger buffer.

4. components_num is read from MPF_DATA_SIZE_OFFSET without checking
   that the offset is within bounds. Add a bounds check.

5. components_size_start (from file) and component_size_byte_num
   (derived from components_num, u16 from file) are used as offsets
   into buf without validation. On 32-bit architectures, their sum
   could overflow, bypassing the bounds check. Add an overflow check
   before the bounds comparison.

Add bounds checks for all five cases.

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 v3:
  - Add overflow check for 32-bit architectures in component size loop
  - Add bounds check for MPF_DATA_SIZE_OFFSET read
  - Update info->header_size before returning -EAGAIN in block loop
    so the retry mechanism can request a larger buffer

Changes in v2:
  - Return -EINVAL instead of -EAGAIN for header_size == 0
  - Return -EAGAIN instead of -EINVAL in block lookup loop
  - Add count check before reading at MPF_HEADER_SIZE_OFFSET
 drivers/fpga/microchip-spi.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea..10be986 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -115,7 +115,13 @@ 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;
+
 	if (header_size > count) {
 		info->header_size = header_size;
 		return -EAGAIN;
@@ -139,6 +145,12 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	bitstream_start = 0;
 
 	while (blocks_num--) {
+		if (block_id_offset >= count ||
+		    block_start_offset + sizeof(u32) > count) {
+			info->header_size = block_start_offset + sizeof(u32);
+			return -EAGAIN;
+		}
+
 		block_id = *(buf + block_id_offset);
 		block_start = get_unaligned_le32(buf + block_start_offset);
 
@@ -175,6 +187,9 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	 * to each other. Image header should be extended by now up to where
 	 * actual bitstream starts, so no need for overflow check anymore.
 	 */
+	if (MPF_DATA_SIZE_OFFSET + sizeof(u16) > count)
+		return -EINVAL;
+
 	components_num = get_unaligned_le16(buf + MPF_DATA_SIZE_OFFSET);
 
 	for (i = 0; i < components_num; i++) {
@@ -183,6 +198,11 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 		component_size_byte_off =
 			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
 
+		if (components_size_start + component_size_byte_num < components_size_start ||
+		    components_size_start + component_size_byte_num +
+		    sizeof(u32) > count)
+			return -EINVAL;
+
 		component_size = get_unaligned_le32(buf +
 						    components_size_start +
 						    component_size_byte_num);
-- 
2.43.0


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

* Re: [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
       [not found]     ` <CAJD=UNc06upxLFo5eNrvy-UvP1Cu6CEBt-csCgECxAK94pa8mg@mail.gmail.com>
@ 2026-04-03 11:16       ` Greg KH
  0 siblings, 0 replies; 21+ messages in thread
From: Greg KH @ 2026-04-03 11:16 UTC (permalink / raw)
  To: Sebastián Alba; +Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel

Please reply inline with the real message, not just at the top...

On Thu, Apr 02, 2026 at 10:25:14AM -0600, Sebastián Alba wrote:
> On Thu, Apr 02, 2026 at 10:07:00AM, Greg KH wrote:
> > How can length be that large?  You are shifting down, not up.
> 
> region->length comes from userspace via the DFL_FPGA_PORT_DMA_MAP
> ioctl (struct dfl_fpga_port_dma_map.length, __u64). The only
> validation in afu_dma_map_region() is PAGE_ALIGNED and an overflow
> check (user_addr + length < user_addr), but there is no upper bound.
> So length >> PAGE_SHIFT can still exceed INT_MAX.
> 
> > Why INT_MAX?  SHouldn't this be much smaller?
> 
> INT_MAX because pin_user_pages_fast() takes int nr_pages. But you
> are right, a practical limit should be much smaller. Happy to use a
> tighter cap if you have a preferred value, or I can base it on
> totalram_pages().

Ok, I think you should move back up the call chain, and for every ioctl,
properly validate ALL arguments before calling 3 levels deep into the
kernel afterwards, and just hope that the values you are passing around
then are actually valid.

Same for the firmware verification, that should all be done in one
place, before you start poking around in the image.  Try to treat all
data coming from userspace, or a firmware image, as "unverified" and it
must be verified before it can cross the boundry to being trusted to do
anything with it.

I'm guessing you have access to some "bad" firmware images to test this
out with?   This is a very odd driver, I doubt that anyone has thrown
any untrusted data at it before.

thanks,

greg k-h

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

* [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
  2026-04-02 16:07   ` Greg KH
@ 2026-04-03 17:57   ` Sebastian Alba Vives
  2026-04-04  7:01     ` Greg KH
  2026-04-07 14:17   ` [PATCH v3 2/3] " Sebastian Alba Vives
  2 siblings, 1 reply; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-03 17:57 UTC (permalink / raw)
  To: linux-fpga
  Cc: yilun.xu, conor.dooley, mdf, linux-kernel, gregkh,
	Sebastian Josue Alba Vives

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


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

* Re: [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  2026-04-03 17:57   ` [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
@ 2026-04-04  7:01     ` Greg KH
  0 siblings, 0 replies; 21+ messages in thread
From: Greg KH @ 2026-04-04  7:01 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: linux-fpga, yilun.xu, conor.dooley, mdf, linux-kernel

On Fri, Apr 03, 2026 at 11:57:18AM -0600, Sebastian Alba Vives wrote:
> 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

This isn't the ioctl entry point, why not put it in afu_ioctl_dma_map()
with the other checks?

thanks,

greg k-h

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

* Re: [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
  2026-04-02 12:54 [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
  2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
@ 2026-04-07  8:51 ` Xu Yilun
  2026-04-07 14:05 ` [PATCH v2 " Sebastian Alba Vives
  3 siblings, 0 replies; 21+ messages in thread
From: Xu Yilun @ 2026-04-07  8:51 UTC (permalink / raw)
  To: Sebastian Alba Vives; +Cc: linux-fpga, conor.dooley, mdf, linux-kernel

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

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

* Re: [PATCH v3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-02 16:23   ` [PATCH v3] " Sebastian Alba Vives
@ 2026-04-07 10:44     ` Xu Yilun
  0 siblings, 0 replies; 21+ messages in thread
From: Xu Yilun @ 2026-04-07 10:44 UTC (permalink / raw)
  To: Sebastian Alba Vives; +Cc: linux-fpga, conor.dooley, mdf, linux-kernel, stable

> @@ -139,6 +145,12 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	bitstream_start = 0;
>  
>  	while (blocks_num--) {
> +		if (block_id_offset >= count ||
> +		    block_start_offset + sizeof(u32) > count) {
> +			info->header_size = block_start_offset + sizeof(u32);
> +			return -EAGAIN;
> +		}
> +

The image header has already been extended up to all look-up table for
blocks, is it?

	header_size += blocks_num * MPF_LOOKUP_TABLE_RECORD_SIZE;
	if (header_size > count) {
		info->header_size = header_size;
		return -EAGAIN;
	}

>  		block_id = *(buf + block_id_offset);
>  		block_start = get_unaligned_le32(buf + block_start_offset);
>  
> @@ -175,6 +187,9 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  	 * to each other. Image header should be extended by now up to where
>  	 * actual bitstream starts, so no need for overflow check anymore.
>  	 */
> +	if (MPF_DATA_SIZE_OFFSET + sizeof(u16) > count)
> +		return -EINVAL;
> +

Do you notice the comments above? IIUC it says all these header info
should be before actual bitstream starts, if we could ensure this, we
don't need to check the addresses inside the header byte by byte.

I think it is important we understand the structure of the image file
first then meaningfully check the boundaries chunk by chunk, rather than
byte by byte, which makes code unreadable.

Thanks,
Yilun

>  	components_num = get_unaligned_le16(buf + MPF_DATA_SIZE_OFFSET);
>  
>  	for (i = 0; i < components_num; i++) {
> @@ -183,6 +198,11 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
>  		component_size_byte_off =
>  			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
>  
> +		if (components_size_start + component_size_byte_num < components_size_start ||
> +		    components_size_start + component_size_byte_num +
> +		    sizeof(u32) > count)
> +			return -EINVAL;
> +
>  		component_size = get_unaligned_le32(buf +
>  						    components_size_start +
>  						    component_size_byte_num);
> -- 
> 2.43.0
> 

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

* [PATCH v2 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
  2026-04-02 12:54 [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
                   ` (2 preceding siblings ...)
  2026-04-07  8:51 ` [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Xu Yilun
@ 2026-04-07 14:05 ` Sebastian Alba Vives
  2026-04-07 14:06   ` [PATCH v2 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
  2026-04-07 14:06   ` [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
  3 siblings, 2 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-07 14:05 UTC (permalink / raw)
  To: yilun.xu
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel, 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: a80a4b2b2e4f ("fpga: dfl: add support for DFHv1")
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
Changes in v2:
  - Use (size > max) instead of (size + DFHv1_PARAM_HDR > max).
    The previous check unnecessarily guarded against the next parameter
    header, which is not relevant at this point in the loop.
    Suggested by Xu Yilun.
---
 drivers/fpga/dfl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 4087a36..81d7a68 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -1132,7 +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] 21+ messages in thread

* [PATCH v2 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
  2026-04-07 14:05 ` [PATCH v2 " Sebastian Alba Vives
@ 2026-04-07 14:06   ` Sebastian Alba Vives
  2026-04-07 14:06   ` [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
  1 sibling, 0 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-07 14:06 UTC (permalink / raw)
  To: yilun.xu
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

In afu_dma_pin_pages(), npages is declared as int but is assigned from
region->length >> PAGE_SHIFT where region->length is u64. This causes
implicit truncation on 64-bit systems when length is large.

The truncated value is then passed to account_locked_vm() (which takes
unsigned long) with implicit sign extension, and to pin_user_pages_fast()
which takes int nr_pages, potentially causing incorrect VM accounting.

Change npages to unsigned long and add a cap to prevent values exceeding
INT_MAX from reaching pin_user_pages_fast().

Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
 drivers/fpga/dfl-afu-dma-region.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
index 87652d5..0d1f973 100644
--- a/drivers/fpga/dfl-afu-dma-region.c
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -34,10 +34,13 @@ 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)
 {
-	int npages = region->length >> PAGE_SHIFT;
+	unsigned long 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;
-- 
2.43.0


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

* [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-07 14:05 ` [PATCH v2 " Sebastian Alba Vives
  2026-04-07 14:06   ` [PATCH v2 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
@ 2026-04-07 14:06   ` Sebastian Alba Vives
  2026-04-07 16:43     ` Conor Dooley
  1 sibling, 1 reply; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-07 14:06 UTC (permalink / raw)
  To: yilun.xu
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel,
	Sebastian Josue Alba Vives

From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>

mpf_ops_parse_header() reads several fields from the bitstream file
and uses them as offsets and sizes without validating them against the
buffer size, leading to multiple out-of-bounds read vulnerabilities:

1. When header_size (u8 from file) is 0, the expression
   *(buf + header_size - 1) reads one byte before the buffer.

2. In the block lookup loop, block_id_offset and block_start_offset
   advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
   blocks_num (u8) controlling the count. With a small buffer, these
   offsets exceed count, causing OOB reads via get_unaligned_le32().

3. components_size_start (from file) and component_size_byte_num
   (derived from components_num, u16 from file) are used as offsets
   into buf without validation, allowing arbitrary OOB reads.

Add bounds checks for all three cases: reject header_size of 0,
validate offsets in the block lookup loop, and validate the component
size read offset.

Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
---
 drivers/fpga/microchip-spi.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea..7954dd0 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -116,7 +116,7 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	}
 
 	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
-	if (header_size > count) {
+	if (!header_size || header_size > count) {
 		info->header_size = header_size;
 		return -EAGAIN;
 	}
@@ -139,6 +139,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 	bitstream_start = 0;
 
 	while (blocks_num--) {
+		if (block_id_offset >= count ||
+		    block_start_offset + sizeof(u32) > count)
+			return -EINVAL;
+
 		block_id = *(buf + block_id_offset);
 		block_start = get_unaligned_le32(buf + block_start_offset);
 
@@ -183,6 +187,10 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
 		component_size_byte_off =
 			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;
 
+		if (components_size_start + component_size_byte_num +
+		    sizeof(u32) > count)
+			return -EINVAL;
+
 		component_size = get_unaligned_le32(buf +
 						    components_size_start +
 						    component_size_byte_num);
-- 
2.43.0


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

* [PATCH v3 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
  2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
  2026-04-02 16:07   ` Greg KH
  2026-04-03 17:57   ` [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
@ 2026-04-07 14:17   ` Sebastian Alba Vives
  2 siblings, 0 replies; 21+ messages in thread
From: Sebastian Alba Vives @ 2026-04-07 14:17 UTC (permalink / raw)
  To: gregkh, yilun.xu
  Cc: linux-fpga, conor.dooley, mdf, linux-kernel, 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 v3:
  - Move the upper-bound check on map.length to afu_ioctl_dma_map()
    at the ioctl entry point, before crossing the userspace/kernel
    boundary, instead of deep in afu_dma_pin_pages(). Revert changes
    to dfl-afu-dma-region.c from v1/v2.
    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] 21+ messages in thread

* Re: [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
  2026-04-07 14:06   ` [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
@ 2026-04-07 16:43     ` Conor Dooley
  0 siblings, 0 replies; 21+ messages in thread
From: Conor Dooley @ 2026-04-07 16:43 UTC (permalink / raw)
  To: Sebastian Alba Vives
  Cc: yilun.xu, linux-fpga, conor.dooley, mdf, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3583 bytes --]

On Tue, Apr 07, 2026 at 08:06:01AM -0600, Sebastian Alba Vives wrote:
> From: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> 
> mpf_ops_parse_header() reads several fields from the bitstream file
> and uses them as offsets and sizes without validating them against the
> buffer size, leading to multiple out-of-bounds read vulnerabilities:
> 
> 1. When header_size (u8 from file) is 0, the expression
>    *(buf + header_size - 1) reads one byte before the buffer.
> 
> 2. In the block lookup loop, block_id_offset and block_start_offset
>    advance by MPF_LOOKUP_TABLE_RECORD_SIZE (9) each iteration with
>    blocks_num (u8) controlling the count. With a small buffer, these
>    offsets exceed count, causing OOB reads via get_unaligned_le32().
> 
> 3. components_size_start (from file) and component_size_byte_num
>    (derived from components_num, u16 from file) are used as offsets
>    into buf without validation, allowing arbitrary OOB reads.
> 
> Add bounds checks for all three cases: reject header_size of 0,
> validate offsets in the block lookup loop, and validate the component
> size read offset.
> 
> Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>

Acked-by: Conor Dooley <conor.dooley@microchip.com>

If there's more revisions, please stop sending new versions in response
to old, this is what I see in my mailbox and it is very confusing:

|   1 N   Apr 02 Greg KH         (  43)   ┌─>Re: [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
|   2 N   Apr 04 Greg KH         (  26)   │ ┌─>
|   3 N   Apr 03 Sebastian Alba  (  55)   ├─>[PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
|   4 N   Apr 07 Sebastian Alba  (  41)   ├─>[PATCH v3 2/3] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
|   5 N   Apr 02 Sebastian Alba  (  40) ┌─>[PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
|   6 NsF Apr 02 To Sebastian Al ( 116) │   ┌─>
|   7 NsF Apr 02 To Sebastian Al ( 107) │ ┌─>Re: [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
|   8 N   Apr 02 Greg KH         ( 106) │ │ ┌─>
|   9 N   Apr 02 Greg KH         (  45) │ │ ├─>
|  10 NsF Apr 02 To Sebastian Al ( 104) │ │ ├─>
|  11 N   Apr 02 Sebastian Alba  (  76) │ ├─>[PATCH v2] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
|  12 N   Apr 07 Xu Yilun        (  60) │ │ ┌─>
|  13 N   Apr 02 Sebastian Alba  ( 105) │ ├─>[PATCH v3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
|  14 N   Apr 02 Sebastian Alba  (  65) ├─>[PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
|  15 N   Apr 07 Xu Yilun        (  61) ├─>Re: [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
|  16 N   Apr 07 Sebastian Alba  (  40) │ ┌─>[PATCH v2 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages()
|  17 N   Apr 07 Sebastian Alba  (  65) │ ├─>[PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header()
|  18 N   Apr 07 Sebastian Alba  (  41) ├─>[PATCH v2 1/3] fpga: dfl: add bounds check in dfh_get_param_size()
|  19 N   Apr 02 Sebastian Alba  (  37) [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size()

If one patch needs changing, you unfortunately need to resubmit the
whole series. If you look here there's multiple v2s of the
microchip-spi patch because of the partial resending.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2026-04-07 16:43 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-02 12:54 [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Sebastian Alba Vives
2026-04-02 12:54 ` [PATCH 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
2026-04-02 16:07   ` Greg KH
     [not found]     ` <CAJD=UNc06upxLFo5eNrvy-UvP1Cu6CEBt-csCgECxAK94pa8mg@mail.gmail.com>
2026-04-03 11:16       ` Greg KH
2026-04-03 17:57   ` [PATCH v2] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Sebastian Alba Vives
2026-04-04  7:01     ` Greg KH
2026-04-07 14:17   ` [PATCH v3 2/3] " Sebastian Alba Vives
2026-04-02 12:54 ` [PATCH 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
2026-04-02 15:03   ` Conor Dooley
2026-04-02 15:16     ` Conor Dooley
2026-04-02 15:37   ` [PATCH v2] " Sebastian Alba Vives
2026-04-02 16:03     ` Greg KH
2026-04-02 16:06     ` Greg KH
2026-04-02 16:16     ` Conor Dooley
2026-04-02 16:23   ` [PATCH v3] " Sebastian Alba Vives
2026-04-07 10:44     ` Xu Yilun
2026-04-07  8:51 ` [PATCH 1/3] fpga: dfl: add bounds check in dfh_get_param_size() Xu Yilun
2026-04-07 14:05 ` [PATCH v2 " Sebastian Alba Vives
2026-04-07 14:06   ` [PATCH v2 2/3] fpga: dfl-afu: fix integer truncation of npages in afu_dma_pin_pages() Sebastian Alba Vives
2026-04-07 14:06   ` [PATCH v2 3/3] fpga: microchip-spi: add bounds checks in mpf_ops_parse_header() Sebastian Alba Vives
2026-04-07 16:43     ` Conor Dooley

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