* [PATCH 0/2] (no cover subject)
@ 2026-06-14 5:36 Bryam Vargas via B4 Relay
2026-06-14 5:36 ` [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count Bryam Vargas via B4 Relay
2026-06-14 5:36 ` [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count Bryam Vargas via B4 Relay
0 siblings, 2 replies; 5+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-14 5:36 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, Hans de Goede, Vincent Huang, linux-input,
Andrew Duggan
From be2c4843f6145374f28edd25cef43c9373542874 Mon Sep 17 00:00:00 2001
Message-ID: <cover.1781415009.git.hexlabsecurity@proton.me>
From: Bryam Vargas <hexlabsecurity@proton.me>
Date: Sun, 14 Jun 2026 00:30:09 -0500
Subject: [PATCH 0/2] Input: synaptics-rmi4 - fix out-of-bounds keymap access on large GPIO counts
The RMI4 F3A and F30 function handlers size their GPIO/LED key map to
min(device_gpio_count, TRACKSTICK_RANGE_END) == at most 6 entries, but
then consume that map with the full, unclamped device-reported count in
two places: the attention-interrupt report loop, and input->keycodemax
(while input->keycode points at the small allocation).
A device that reports a GPIO/LED count greater than 6 therefore yields a
key map of at most 12 bytes that is indexed up to count-1:
- rmi_f3a_attention() / rmi_f30_attention() read gpio[led]_key_map[i]
out of bounds on every attention interrupt (device-triggered), and
- the input core's default keymap ioctls bound the index only against
keycodemax, so EVIOCGKEYCODE reads adjacent slab memory back to user
space and EVIOCSKEYCODE writes a caller-controlled u16 past the
allocation -- a controlled out-of-bounds heap write reachable by any
process that can open the evdev node.
Both handlers have the same shape; F3A was copied from F30. Patch 1 fixes
F3A, patch 2 fixes F30. The one-line fix in each sizes the key map to the
full device count; the mapping loop is unchanged (it still populates only
the first min(count, 6) entries, the rest stay KEY_RESERVED and are
skipped on report), and keycodemax now matches the allocation, closing
the interrupt and both ioctl paths.
Reproduced with KASAN on a faithful in-kernel model of each handler
(kmalloc-16 bucket, 12-byte request, reported count = 127):
# without the patch -- attention read path
BUG: KASAN: slab-out-of-bounds in rmi_f3a_attention
Read of size 2 ... 0 bytes to the right of allocated 12-byte region
... cache kmalloc-16
# without the patch -- EVIOCSKEYCODE write path
BUG: KASAN: slab-out-of-bounds ...
Write of size 2 ... 0 bytes to the right of allocated 12-byte region
# with the patch (key map sized to the full count): clean
# benign device (reported count <= 6): clean
The full read and write splats and a 32/64-bit ASan model of the same
geometry are available on request.
Bryam Vargas (2):
Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
drivers/input/rmi4/rmi_f30.c | 2 +-
drivers/input/rmi4/rmi_f3a.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
---
Bryam Vargas (2):
Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
drivers/input/rmi4/rmi_f30.c | 2 +-
drivers/input/rmi4/rmi_f3a.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
---
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
change-id: 20260614-b4-disp-818d6bda-8df90972ace6
Best regards,
--
Bryam Vargas <hexlabsecurity@proton.me>
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
2026-06-14 5:36 [PATCH 0/2] (no cover subject) Bryam Vargas via B4 Relay
@ 2026-06-14 5:36 ` Bryam Vargas via B4 Relay
2026-06-14 5:51 ` sashiko-bot
2026-06-14 5:36 ` [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count Bryam Vargas via B4 Relay
1 sibling, 1 reply; 5+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-14 5:36 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, Hans de Goede, Vincent Huang, linux-input,
Andrew Duggan
From: Bryam Vargas <hexlabsecurity@proton.me>
rmi_f3a_initialize() takes the GPIO count from the device query register
(f3a->gpio_count = buf & RMI_F3A_GPIO_COUNT, range 0..127).
rmi_f3a_map_gpios() then allocates gpio_key_map with
min(gpio_count, TRACKSTICK_RANGE_END) == at most 6 entries, but
rmi_f3a_attention() iterates the full gpio_count and dereferences
gpio_key_map[i], and input->keycodemax is set to the full gpio_count
while input->keycode points at the 6-entry allocation.
A device that reports gpio_count > 6 therefore causes an out-of-bounds
read of gpio_key_map[] on every attention interrupt, and out-of-bounds
accesses through the input core's default keymap ioctls: EVIOCGKEYCODE
reads past the buffer (leaking adjacent slab memory to user space) and
EVIOCSKEYCODE writes a caller-controlled value past it, for any process
able to open the evdev node, since input_default_getkeycode() and
input_default_setkeycode() only bound the index against keycodemax.
Size the keymap for the full gpio_count. The mapping loop is unchanged:
it still assigns only the first min(gpio_count, TRACKSTICK_RANGE_END)
entries; the remaining slots stay KEY_RESERVED (devm_kcalloc zero-fills)
and are skipped when reporting.
Fixes: 9e4c596bfd00 ("Input: synaptics-rmi4 - add support for F3A")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
drivers/input/rmi4/rmi_f3a.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_f3a.c b/drivers/input/rmi4/rmi_f3a.c
index 0e8baed84dbb..a0777644eef0 100644
--- a/drivers/input/rmi4/rmi_f3a.c
+++ b/drivers/input/rmi4/rmi_f3a.c
@@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a,
int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END);
f3a->gpio_key_map = devm_kcalloc(&fn->dev,
- button_count,
+ f3a->gpio_count,
sizeof(f3a->gpio_key_map[0]),
GFP_KERNEL);
if (!f3a->gpio_key_map) {
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
2026-06-14 5:36 ` [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count Bryam Vargas via B4 Relay
@ 2026-06-14 5:51 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-14 5:51 UTC (permalink / raw)
To: Bryam Vargas via B4 Relay; +Cc: dmitry.torokhov, linux-input
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [High] Out-of-bounds shift and logic error in `rmi_f3a_report_button` when `button >= 8`.
- [High] Unbinding the `rmi4_f3a` driver leaves a dangling `input->keycode` pointer, leading to a Use-After-Free.
- [High] Failing to insert into the attention FIFO leaks the dynamically allocated duplicate buffer.
- [Medium] Multiple RMI4 functions concurrently overwrite the shared `input->keycode` map, making all but the last probed map inaccessible to userspace.
--
commit 1556a27ea7ad4e1c54736060ac2c334003a11681
Author: Bryam Vargas <hexlabsecurity@proton.me>
Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count
This commit addresses an out-of-bounds access in the F3A keymap. It sizes the
gpio_key_map buffer to the full gpio_count rather than capping it at 6,
preventing reads or writes past the allocated array during attention
interrupts or keymap ioctls.
> diff --git a/drivers/input/rmi4/rmi_f3a.c b/drivers/input/rmi4/rmi_f3a.c
> index 0e8baed84dbb5..a0777644eef07 100644
> --- a/drivers/input/rmi4/rmi_f3a.c
> +++ b/drivers/input/rmi4/rmi_f3a.c
> @@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a,
> int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END);
>
> f3a->gpio_key_map = devm_kcalloc(&fn->dev,
> - button_count,
> + f3a->gpio_count,
> sizeof(f3a->gpio_key_map[0]),
> GFP_KERNEL);
[Severity: High]
This isn't a bug introduced by this patch, but I have a question about the
lifecycle of the keymap allocated here.
Since input->keycode is set to f3a->gpio_key_map later in this function, if
the rmi4_f3a function driver is unbound via sysfs, devres will free this
memory. Because rmi_f3a_handler lacks a .remove callback and does not set
.suppress_bind_attrs = true, does this leave input->keycode pointing to freed
memory? Could subsequent EVIOCGKEYCODE or EVIOCSKEYCODE ioctls on the shared
input_dev dereference this freed pointer?
[Severity: Medium]
This is a pre-existing issue, but I also noticed how this keymap interacts
with the shared input device.
Both F3A and F30 assign their own private arrays to the shared input->keycode:
drivers/input/rmi4/rmi_f3a.c:rmi_f3a_map_gpios() {
...
input->keycode = f3a->gpio_key_map;
...
}
drivers/input/rmi4/rmi_f30.c:rmi_f30_map_gpios() {
...
input->keycode = f30->gpioled_key_map;
...
}
Since multiple RMI4 functions concurrently overwrite the shared
input->keycode, does this make all but the last probed map inaccessible to
userspace? Would earlier functions then report events using their
unmodifiable, private arrays?
> if (!f3a->gpio_key_map) {
[ ... ]
[Severity: High]
This is a pre-existing issue, but looking at rmi_f3a_report_button() in
drivers/input/rmi4/rmi_f3a.c:
drivers/input/rmi4/rmi_f3a.c:rmi_f3a_report_button() {
...
bool key_down = !(f3a->data_regs[0] & BIT(button));
...
}
Since f3a->data_regs is a u8 array, could this incorrectly report the key as
constantly pressed if button >= 8? If button >= 32, could this result in an
out-of-bounds shift? Since userspace can map a high button index via
EVIOCSKEYCODE and trigger an interrupt, could this be triggered intentionally?
[Severity: High]
This is a pre-existing issue, but looking at rmi_set_attn_data() in
drivers/input/rmi4/rmi_driver.c:
drivers/input/rmi4/rmi_driver.c:rmi_set_attn_data() {
...
fifo_data = kmemdup(data, size, GFP_ATOMIC);
...
attn_data.data = fifo_data;
...
kfifo_put(&drvdata->attn_fifo, attn_data);
...
}
If kfifo_put() fails because the FIFO is full, does this silently leak the
dynamically allocated fifo_data buffer? Could a flood of interrupts lead to
memory exhaustion?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260614-b4-disp-818d6bda-v1-0-cf39a3615085@proton.me?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
2026-06-14 5:36 [PATCH 0/2] (no cover subject) Bryam Vargas via B4 Relay
2026-06-14 5:36 ` [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count Bryam Vargas via B4 Relay
@ 2026-06-14 5:36 ` Bryam Vargas via B4 Relay
2026-06-14 5:50 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-14 5:36 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, Hans de Goede, Vincent Huang, linux-input,
Andrew Duggan
From: Bryam Vargas <hexlabsecurity@proton.me>
rmi_f30_map_gpios() allocates gpioled_key_map with
min(gpioled_count, TRACKSTICK_RANGE_END) == at most 6 entries, but
rmi_f30_attention() iterates the full f30->gpioled_count (device query
register, range 0..31) and dereferences gpioled_key_map[i], and
input->keycodemax is set to the full gpioled_count while input->keycode
points at the 6-entry allocation.
A device that reports gpioled_count > 6 with GPIO support enabled
therefore causes an out-of-bounds read on the attention interrupt and
out-of-bounds read/write through the EVIOCGKEYCODE/EVIOCSKEYCODE ioctls,
which bound the index only against keycodemax. This is the same defect
as the F3A handler, which was copied from F30.
Size the keymap for the full gpioled_count; the mapping loop still
assigns only the first min(gpioled_count, TRACKSTICK_RANGE_END) entries.
Fixes: 3e64fcbdbd10 ("Input: synaptics-rmi4 - limit the range of what GPIOs are buttons")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
drivers/input/rmi4/rmi_f30.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index 35045f161dc2..b2155c8e20e7 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
f30->gpioled_key_map = devm_kcalloc(&fn->dev,
- button_count,
+ f30->gpioled_count,
sizeof(f30->gpioled_key_map[0]),
GFP_KERNEL);
if (!f30->gpioled_key_map) {
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
2026-06-14 5:36 ` [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count Bryam Vargas via B4 Relay
@ 2026-06-14 5:50 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-14 5:50 UTC (permalink / raw)
To: Bryam Vargas via B4 Relay; +Cc: linux-input, dmitry.torokhov
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Unbinding the `rmi4_f30` driver leaves a dangling pointer in the shared input device's `keycode` field, leading to a Use-After-Free.
--
commit 251790cc33b0da19e8d0320efecb822396ad7b5f
Author: Bryam Vargas <hexlabsecurity@proton.me>
Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count
This commit fixes an out-of-bounds read and write issue in the F30
keymap handler. It allocates the keymap based on the full reported
GPIO/LED count rather than capping the allocation at 6 entries.
> diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
> --- a/drivers/input/rmi4/rmi_f30.c
> +++ b/drivers/input/rmi4/rmi_f30.c
> @@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
> int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
>
> f30->gpioled_key_map = devm_kcalloc(&fn->dev,
> - button_count,
> + f30->gpioled_count,
> sizeof(f30->gpioled_key_map[0]),
> GFP_KERNEL);
[Severity: High]
This is a pre-existing issue, but since we are modifying this allocation,
can this lead to a use-after-free when the driver is unbound?
The memory for f30->gpioled_key_map is managed by the function subdevice
using fn->dev. Later in rmi_f30_map_gpios(), this pointer is assigned to the
shared input device's keycode field:
input->keycode = f30->gpioled_key_map;
Since the shared input device is attached to the parent RMI device, it can
outlive the function subdevice. If userspace unbinds the rmi4_f30 driver
via sysfs (because the driver lacks a remove callback and does not set
suppress_bind_attrs), devres will free f30->gpioled_key_map while
the input device remains registered.
Would a subsequent ioctl like EVIOCGKEYCODE or EVIOCSKEYCODE access this
freed input->keycode memory?
Does this also cause a race condition during device unplug, since the
function devices are unbound before the input device is unregistered?
> if (!f30->gpioled_key_map) {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260614-b4-disp-818d6bda-v1-0-cf39a3615085@proton.me?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-14 5:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-14 5:36 [PATCH 0/2] (no cover subject) Bryam Vargas via B4 Relay
2026-06-14 5:36 ` [PATCH 1/2] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count Bryam Vargas via B4 Relay
2026-06-14 5:51 ` sashiko-bot
2026-06-14 5:36 ` [PATCH 2/2] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count Bryam Vargas via B4 Relay
2026-06-14 5:50 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox