Re: [PATCH] ACPI: NFIT: validate subtable extents before parsing

Alison Schofield <[email protected]> Wed, 5 Aug 2026 17:43:17 -0700
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.nvdimm
Message-ID <[email protected]>
On Wed, Jul 22, 2026 at 04:31:02AM +0000, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> 
> New issues:
> - [High] Rejecting the capability table if `highest_capability > 31` fails the entire NFIT driver probe, breaking forward compatibility.

Agreed w this one. See my direct response.

> 
> Pre-existing issues:
> - [High] Missing bounds check in `sizeof_dcr` leads to potential out-of-bounds read when parsing the Control Region subtable.

I think this is true but not something that belongs in this patch.


> - [High] `sizeof_spa` incorrectly assumes that the SPA length is determined by the `LOCATION_COOKIE_VALID` flag, rejecting valid ACPI 6.4+ System Physical Address tables.

This one is not obviously true. I think the question is should sizeof_spa()
take structure size from header.length rather than LOCATION_COOKIE_VALID?
I wonder if ACPI 6.4 permits a 64-byte SPA with LOCATION_COOKIE_VALID clear,
in which case the current logic would reject an otherwise valid table.
I didn't look into this, but I think you need to figure that out in
case this patch needs to change.

-- Alison


> --
> 
> --- Patch [1]: [PATCH] ACPI: NFIT: validate subtable extents before parsing ---
> commit d7436f5d72f81006ac23c35fc1e7248c7a9fe254
> Author: Pengpeng Hou <[email protected]>
> 
> ACPI: NFIT: validate subtable extents before parsing
> 
> add_table() reads an NFIT subtable header after checking only that the
> cursor is before the end of the table. It then advances by the advertised
> subtable length without proving that either the header or the full
> subtable is present. This patch validates the fixed header and advertised
> length before dispatch, and ensures variable arrays fit their subtables.
> 
> > diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> > index cb771d9cadb2a..711ab639cb147 100644
> > --- a/drivers/acpi/nfit/core.c
> > +++ b/drivers/acpi/nfit/core.c
> > @@ -705,6 +705,10 @@ int nfit_spa_type(struct acpi_nfit_system_address *spa)
> >  
> >  static size_t sizeof_spa(struct acpi_nfit_system_address *spa)
> >  {
> > +	if (spa->header.length <
> > +	    offsetof(struct acpi_nfit_system_address, reserved))
> > +		return 0;
> > +
> >  	if (spa->flags & ACPI_NFIT_LOCATION_COOKIE_VALID)
> >  		return sizeof(*spa);
> >  	return sizeof(*spa) - 8;
> >  }
> 
> [Severity: High]
> This is a pre-existing issue, but does this logic risk rejecting valid
> ACPI 6.4+ System Physical Address tables?
> 
> If a compliant ACPI 6.4 firmware presents a 64-byte SPA table with the
> LOCATION_COOKIE_VALID flag unset, sizeof_spa() will assume the length
> should be 56.
> 
> In add_spa() in drivers/acpi/nfit/core.c, the exact length equality check
> will then fail:
> 
> add_spa() {
>     ...
>     if (spa->header.length != sizeof_spa(spa))
>         return false;
>     ...
> }
> 
> Will this bubble up as ERR_PTR(-ENOMEM) and abort the entire driver probe
> on compliant platforms?
> 
> [Severity: High]
> This is also a pre-existing issue, but while we're adding bounds checks,
> does sizeof_dcr() in drivers/acpi/nfit/core.c have a similar missing check
> that could lead to an out-of-bounds read?
> 
> When an ACPI table provides a DCR subtable with header.length exactly enough
> to include the windows field (e.g., 32) and windows > 0, sizeof_dcr() calculates
> the required size as 80 bytes:
> 
> sizeof_dcr() {
>     ...
>     if (dcr->windows)
>         return sizeof(*dcr);
>     ...
> }
> 
> add_table() only verifies that 32 bytes remain in the mapped ACPI table. The
> memcpy() in add_dcr() then reads 80 bytes:
> 
> add_dcr() {
>     ...
>     memcpy(nfit_dcr->dcr, dcr, sizeof_dcr(dcr));
>     ...
> }
> 
> Could this extend 48 bytes past the end of the subtable, potentially reading
> unmapped memory and causing a kernel panic?
> 
> [ ... ]
> 
> > @@ -951,7 +969,16 @@ static bool add_platform_cap(struct acpi_nfit_desc *acpi_desc,
> >  	struct device *dev = acpi_desc->dev;
> >  	u32 mask;
> >  
> > -	mask = (1 << (pcap->highest_capability + 1)) - 1;
> > +	if (pcap->header.length < sizeof(*pcap))
> > +		return false;
> > +	if (pcap->highest_capability > 31)
> > +		return false;
> 
> [Severity: High]
> Does returning false here break forward compatibility with future ACPI
> firmware?
> 
> If a future firmware revision sets highest_capability > 31 to indicate support
> for new features, this check will return false.
> 
> Since add_table() handles this by returning ERR_PTR(-ENOMEM):
> 
> add_table() {
>     ...
>     case ACPI_NFIT_TYPE_CAPABILITIES:
>         if (!add_platform_cap(acpi_desc, table))
>             return err;
>     ...
> }
> 
> Would this cause the entire NFIT driver probe to fail, rather than just
> gracefully capping or ignoring the unknown capability bits?
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
>