[PATCH v6 2/2] gpiolib: acpi: Prevent out-of-bounds pin access in OperationRegion handler

From: Marco Scardovi

Date: Wed Jun 10 2026 - 11:58:29 EST


The ACPI GPIO OperationRegion handler receives pin offsets as a
64-bit address. Previously, this value could be assigned to a pin index
without validation, potentially causing out-of-bounds access if
the ACPI table provides an invalid offset.

This patch explicitly checks that the 64-bit address is less than
agpio->pin_table_length before using it, returning AE_BAD_PARAMETER
if the check fails. Additionally, it makes the length calculation
overflow-safe and ensures proper unsigned types for loop counters.

This corrects the commit message from v5 to accurately reflect the
underlying issue, removing references to truncation or wrap-around,
which do not occur in ACPICA.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs@xxxxxxxxxxx>
---
drivers/gpio/gpiolib-acpi-core.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c
index b09f89832890..220f0ac4204e 100644
--- a/drivers/gpio/gpiolib-acpi-core.c
+++ b/drivers/gpio/gpiolib-acpi-core.c
@@ -1098,10 +1098,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);
@@ -1121,7 +1121,14 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
return AE_BAD_PARAMETER;
}

- length = min(agpio->pin_table_length, pin_index + bits);
+ /* address represents GPIO pin index in connection table */
+ if (address >= agpio->pin_table_length) {
+ ACPI_FREE(ares);
+ return AE_BAD_PARAMETER;
+ }
+
+ pin_index = address;
+ length = min_t(unsigned int, agpio->pin_table_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