* [PATCH v5 0/2] gpiolib: acpi: Add bounds-checking and address validation @ 2026-06-02 11:32 Marco Scardovi 2026-06-02 11:32 ` [PATCH v5 1/2] gpiolib: acpi: Add robust bounds-checking for GPIO pin resources Marco Scardovi 2026-06-02 11:32 ` [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler Marco Scardovi 0 siblings, 2 replies; 7+ messages in thread From: Marco Scardovi @ 2026-06-02 11:32 UTC (permalink / raw) To: andriy.shevchenko, mika.westerberg Cc: brgl, linusw, linux-acpi, linux-gpio, linux-kernel Hi all, after some thinking and following Mika and Andy's reviews I've come up with a new version of the series. This series adds defensive hardening in the ACPI GPIO path, focusing on bounds checking and safe handling of GPIO resources and ACPI addresses. Drop the previously proposed GPIO connection handling changes in the ACPI OperationRegion path, following review feedback. This also closes the old threads completely and drop my @gmail account as it is not related to my linux stuffs. Changes in v5: * Add bounds checking for GPIO pin resource accesses in ACPI GPIO helpers to prevent out-of-bounds access on malformed or empty pin tables. * Validate ACPI address in acpi_gpio_adr_space_handler() before converting it to a GPIO index, preventing truncation-induced wraparound. * Improve type safety and overflow handling in length calculation and loop bounds in the OperationRegion handler. Changes in v4: * Dropped connection resource leak fix to keep focus on validation. * See v4 series at: https://lore.kernel.org/linux-gpio/20260531120816.17255-1-scardracs@disroot.org/ Changes in v3: * Fixed global over-cleanup bug in OpRegion error path. * See v3 series at: https://lore.kernel.org/linux-gpio/20260520074955.55443-1-mscardovi95@gmail.com/ Changes in v2: * Dropped gpiolib-acpi-core.c modularization (out of scope). * Split series into bounds checking and address truncation fixes. * See v2 series at: https://lore.kernel.org/linux-gpio/20260519070039.9280-1-mscardovi95@gmail.com/ Changes in v1: * Initial ACPI GPIO hardening series. Marco Scardovi (2): gpiolib: acpi: Add robust bounds-checking for GPIO pin resources gpiolib: acpi: prevent address truncation in OperationRegion handler drivers/gpio/gpiolib-acpi-core.c | 40 +++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) -- 2.54.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 1/2] gpiolib: acpi: Add robust bounds-checking for GPIO pin resources 2026-06-02 11:32 [PATCH v5 0/2] gpiolib: acpi: Add bounds-checking and address validation Marco Scardovi @ 2026-06-02 11:32 ` Marco Scardovi 2026-06-02 11:32 ` [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler Marco Scardovi 1 sibling, 0 replies; 7+ messages in thread From: Marco Scardovi @ 2026-06-02 11:32 UTC (permalink / raw) To: andriy.shevchenko, mika.westerberg Cc: brgl, linusw, linux-acpi, linux-gpio, linux-kernel Ensure that the GPIO pin resource arrays are safely bounded before accessing indices. Add bounds checking in acpi_request_own_gpiod(), acpi_gpio_irq_is_wake(), and acpi_gpiochip_alloc_event() to prevent out-of-bounds array reads if the ACPI namespace provides malformed or empty pin tables. Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Marco Scardovi <scardracs@disroot.org> --- drivers/gpio/gpiolib-acpi-core.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c index eb8a40cfb7a9..1cb5f5884ff0 100644 --- a/drivers/gpio/gpiolib-acpi-core.c +++ b/drivers/gpio/gpiolib-acpi-core.c @@ -320,10 +320,17 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip, unsigned int index, const char *label) { - int polarity = GPIO_ACTIVE_HIGH; - enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity); - unsigned int pin = agpio->pin_table[index]; + enum gpiod_flags flags; struct gpio_desc *desc; + unsigned int pin; + int polarity; + + if (index >= agpio->pin_table_length) + return ERR_PTR(-EINVAL); + + pin = agpio->pin_table[index]; + polarity = GPIO_ACTIVE_HIGH; + flags = acpi_gpio_to_gpiod_flags(agpio, polarity); desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags); if (IS_ERR(desc)) @@ -337,7 +344,12 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip, static bool acpi_gpio_irq_is_wake(struct device *parent, const struct acpi_resource_gpio *agpio) { - unsigned int pin = agpio->pin_table[0]; + unsigned int pin; + + if (agpio->pin_table_length == 0) + return false; + + pin = agpio->pin_table[0]; if (agpio->wake_capable != ACPI_WAKE_CAPABLE) return false; @@ -367,6 +379,9 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, if (!acpi_gpio_get_irq_resource(ares, &agpio)) return AE_OK; + if (agpio->pin_table_length == 0) + return AE_OK; + handle = ACPI_HANDLE(chip->parent); pin = agpio->pin_table[0]; -- 2.54.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler 2026-06-02 11:32 [PATCH v5 0/2] gpiolib: acpi: Add bounds-checking and address validation Marco Scardovi 2026-06-02 11:32 ` [PATCH v5 1/2] gpiolib: acpi: Add robust bounds-checking for GPIO pin resources Marco Scardovi @ 2026-06-02 11:32 ` Marco Scardovi 2026-06-02 11:45 ` Mika Westerberg 1 sibling, 1 reply; 7+ messages in thread From: Marco Scardovi @ 2026-06-02 11:32 UTC (permalink / raw) To: andriy.shevchenko, mika.westerberg Cc: brgl, linusw, linux-acpi, linux-gpio, linux-kernel The ACPI address space handler for GPIO OperationRegions receives the pin offset as a 64-bit acpi_physical_address. However, the handler truncates this address to a u16 pin_index before validating it. If an ACPI table attempts to access a pin offset greater than 65535, the truncation wraps the index around. This may result in accesses to unintended GPIO pins. Fix this by adding an explicit check to verify that the 64-bit address is less than agpio->pin_table_length before assigning it to the u16 pin_index, returning AE_BAD_PARAMETER if it is out of bounds. Additionally, make the length calculation overflow-safe and change the types of length and loop counter to unsigned. Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Marco Scardovi <scardracs@disroot.org> --- drivers/gpio/gpiolib-acpi-core.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c index 1cb5f5884ff0..fc157ee9ac61 100644 --- a/drivers/gpio/gpiolib-acpi-core.c +++ b/drivers/gpio/gpiolib-acpi-core.c @@ -1102,10 +1102,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, struct gpio_chip *chip = achip->chip; struct acpi_resource_gpio *agpio; struct acpi_resource *ares; - u16 pin_index = address; + unsigned int length; acpi_status status; - int length; - int i; + unsigned int i; + u16 pin_index; status = acpi_buffer_to_resource(achip->conn_info.connection, achip->conn_info.length, &ares); @@ -1125,7 +1125,16 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, return AE_BAD_PARAMETER; } - length = min(agpio->pin_table_length, pin_index + bits); + if (address >= agpio->pin_table_length) { + ACPI_FREE(ares); + return AE_BAD_PARAMETER; + } + + pin_index = address; + if (bits > agpio->pin_table_length - pin_index) + length = agpio->pin_table_length; + else + length = pin_index + bits; for (i = pin_index; i < length; ++i) { unsigned int pin = agpio->pin_table[i]; struct acpi_gpio_connection *conn; -- 2.54.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler 2026-06-02 11:32 ` [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler Marco Scardovi @ 2026-06-02 11:45 ` Mika Westerberg 2026-06-02 11:59 ` Marco Scardovi 0 siblings, 1 reply; 7+ messages in thread From: Mika Westerberg @ 2026-06-02 11:45 UTC (permalink / raw) To: Marco Scardovi Cc: andriy.shevchenko, brgl, linusw, linux-acpi, linux-gpio, linux-kernel On Tue, Jun 02, 2026 at 01:32:20PM +0200, Marco Scardovi wrote: > The ACPI address space handler for GPIO OperationRegions receives the > pin offset as a 64-bit acpi_physical_address. However, the handler > truncates this address to a u16 pin_index before validating it. > > If an ACPI table attempts to access a pin offset greater than 65535, > the truncation wraps the index around. This may result in accesses to > unintended GPIO pins. How in practice this can be done given that the GPIO resource has only 2 bytes for the index? > Fix this by adding an explicit check to verify that the 64-bit address > is less than agpio->pin_table_length before assigning it to the u16 > pin_index, returning AE_BAD_PARAMETER if it is out of bounds. > Additionally, make the length calculation overflow-safe and change the types > of length and loop counter to unsigned. > > Assisted-by: Antigravity:gemini-3.5-flash > Signed-off-by: Marco Scardovi <scardracs@disroot.org> > --- > drivers/gpio/gpiolib-acpi-core.c | 17 +++++++++++++---- > 1 file changed, 13 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c > index 1cb5f5884ff0..fc157ee9ac61 100644 > --- a/drivers/gpio/gpiolib-acpi-core.c > +++ b/drivers/gpio/gpiolib-acpi-core.c > @@ -1102,10 +1102,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, > struct gpio_chip *chip = achip->chip; > struct acpi_resource_gpio *agpio; > struct acpi_resource *ares; > - u16 pin_index = address; > + unsigned int length; > acpi_status status; > - int length; > - int i; > + unsigned int i; > + u16 pin_index; > > status = acpi_buffer_to_resource(achip->conn_info.connection, > achip->conn_info.length, &ares); > @@ -1125,7 +1125,16 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, > return AE_BAD_PARAMETER; > } > > - length = min(agpio->pin_table_length, pin_index + bits); > + if (address >= agpio->pin_table_length) { > + ACPI_FREE(ares); > + return AE_BAD_PARAMETER; > + } > + > + pin_index = address; > + if (bits > agpio->pin_table_length - pin_index) > + length = agpio->pin_table_length; > + else > + length = pin_index + bits; > for (i = pin_index; i < length; ++i) { > unsigned int pin = agpio->pin_table[i]; > struct acpi_gpio_connection *conn; > -- > 2.54.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler 2026-06-02 11:45 ` Mika Westerberg @ 2026-06-02 11:59 ` Marco Scardovi 2026-06-02 12:15 ` Mika Westerberg 0 siblings, 1 reply; 7+ messages in thread From: Marco Scardovi @ 2026-06-02 11:59 UTC (permalink / raw) To: Mika Westerberg Cc: andriy.shevchenko, brgl, linusw, linux-acpi, linux-gpio, linux-kernel Hi Mika, On Tue, Jun 02, 2026 at 01:45:40PM +0200, Mika Westerberg wrote: > How in practice this can be done given that the GPIO resource has only 2 > bytes for the index? The 2-byte limitation is in the GPIO resource descriptor representation of the pin table, not in the ACPI address space handler interface itself. The acpi_gpio_adr_space_handler() receives the access offset as a 64-bit acpi_physical_address from ACPICA. This value is generated when AML accesses a Field within the GPIO OperationRegion, and it is not constrained by the GPIO resource descriptor's pin_table_length. This is not GPIO-specific in ACPICA terms: all address space handlers receive a raw 64-bit address, and any semantic interpretation (such as treating it as a GPIO pin index) is done by the individual handler. In the GPIO case, the driver maps this address directly to an index into agpio->pin_table[]. Without validating the full 64-bit value against pin_table_length before truncating to u16, an out-of-bounds access can occur due to wraparound. The fix ensures the 64-bit address is validated against the table size before any narrowing conversion, avoiding the wraparound and rejecting invalid AML accesses. Marco ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler 2026-06-02 11:59 ` Marco Scardovi @ 2026-06-02 12:15 ` Mika Westerberg 2026-06-03 8:25 ` Marco Scardovi 0 siblings, 1 reply; 7+ messages in thread From: Mika Westerberg @ 2026-06-02 12:15 UTC (permalink / raw) To: Marco Scardovi Cc: andriy.shevchenko, brgl, linusw, linux-acpi, linux-gpio, linux-kernel Hi, On Tue, Jun 02, 2026 at 01:59:36PM +0200, Marco Scardovi wrote: > Hi Mika, > > On Tue, Jun 02, 2026 at 01:45:40PM +0200, Mika Westerberg wrote: > > How in practice this can be done given that the GPIO resource has only 2 > > bytes for the index? > > The 2-byte limitation is in the GPIO resource descriptor representation of the > pin table, not in the ACPI address space handler interface itself. > > The acpi_gpio_adr_space_handler() receives the access offset as a 64-bit > acpi_physical_address from ACPICA. This value is generated when AML > accesses a Field within the GPIO OperationRegion, and it is not constrained > by the GPIO resource descriptor's pin_table_length. Yes, but you access it from AML like this: Field(\_SB.GPI2.GPO2, ByteAcc, NoLock, Preserve) { Connection (GpioIo(Exclusive, PullUp, , , , "\\_SB.GPI2") {7}), STAT, 1, // e.g. Status signal from the device Connection (GpioIo (Exclusive, PullUp, , , , "\\_SB.GPI2") {9}), RSET, 1 // e.g. Reset signal to the device } In other words it still uses GPIO resource descriptor (so 2 bytes per pin), nothing else is accepted as far as I understand. The example is here: https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#declaring-generalpurposeio-fields ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler 2026-06-02 12:15 ` Mika Westerberg @ 2026-06-03 8:25 ` Marco Scardovi 0 siblings, 0 replies; 7+ messages in thread From: Marco Scardovi @ 2026-06-03 8:25 UTC (permalink / raw) To: mika.westerberg Cc: andriy.shevchenko, brgl, linusw, linux-acpi, linux-gpio, linux-kernel, scardracs Hi Mika, Thanks for the clarification. After looking again at the ACPI specification, I agree that AML accesses GPIO fields through Connection() resources, so the offset used by the handler is derived from the GPIO resource descriptor itself. Therefore, describing this as a truncation issue is not accurate. The actual issue is that the address argument is used as an index into agpio->pin_table without first validating that it is within agpio->pin_table_length. I'll update the description accordingly and focus on the missing bounds check rather than truncation or wrap-around. If You or anyone else haven't any more suggestions/reviews I'll post it later today/tomorrow as a v6. Thanks, Marco ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-03 8:26 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-06-02 11:32 [PATCH v5 0/2] gpiolib: acpi: Add bounds-checking and address validation Marco Scardovi 2026-06-02 11:32 ` [PATCH v5 1/2] gpiolib: acpi: Add robust bounds-checking for GPIO pin resources Marco Scardovi 2026-06-02 11:32 ` [PATCH v5] gpiolib: acpi: prevent address truncation in OperationRegion handler Marco Scardovi 2026-06-02 11:45 ` Mika Westerberg 2026-06-02 11:59 ` Marco Scardovi 2026-06-02 12:15 ` Mika Westerberg 2026-06-03 8:25 ` Marco Scardovi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®