Skip to content

Commit 7453eb8

Browse files
andy-shevgregkh
authored andcommitted
gpiolib: acpi: Fix potential out-of-boundary left shift
commit e64d1cb upstream. GPIO Address Space handler gets a pointer to the in or out value. This value is supposed to be at least 64-bit, but it's not limited to be exactly 64-bit. When ACPI tables are being parsed, for the bigger Connection():s ACPICA creates a Buffer instead of regular Integer object. The Buffer exists as long as Namespace holds the certain Connection(). Hence we can access the necessary bits without worrying. On the other hand, the left shift, used in the code, is limited by 31 (on 32-bit platforms) and otherwise considered to be Undefined Behaviour. Also the code uses only the first 64-bit word for the value, and anything bigger than 63 will be also subject to UB. Fix all this by modifying the code to correctly set or clear the respective bit in the bitmap constructed of 64-bit words. Fixes: 59084c5 ("gpiolib: acpi: use BIT_ULL() for u64 mask in address space handler") Fixes: 2c4d00c ("gpiolib: acpi: Use BIT() macro to increase readability") Cc: stable@vger.kernel.org Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20260128095918.4157491-1-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3dac9f4 commit 7453eb8

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

drivers/gpio/gpiolib-acpi-core.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
10941094
unsigned int pin = agpio->pin_table[i];
10951095
struct acpi_gpio_connection *conn;
10961096
struct gpio_desc *desc;
1097+
u16 word, shift;
10971098
bool found;
10981099

10991100
mutex_lock(&achip->conn_lock);
@@ -1148,10 +1149,22 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
11481149

11491150
mutex_unlock(&achip->conn_lock);
11501151

1151-
if (function == ACPI_WRITE)
1152-
gpiod_set_raw_value_cansleep(desc, !!(*value & BIT_ULL(i)));
1153-
else
1154-
*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
1152+
/*
1153+
* For the cases when OperationRegion() consists of more than
1154+
* 64 bits calculate the word and bit shift to use that one to
1155+
* access the value.
1156+
*/
1157+
word = i / 64;
1158+
shift = i % 64;
1159+
1160+
if (function == ACPI_WRITE) {
1161+
gpiod_set_raw_value_cansleep(desc, value[word] & BIT_ULL(shift));
1162+
} else {
1163+
if (gpiod_get_raw_value_cansleep(desc))
1164+
value[word] |= BIT_ULL(shift);
1165+
else
1166+
value[word] &= ~BIT_ULL(shift);
1167+
}
11551168
}
11561169

11571170
out:

0 commit comments

Comments
 (0)