[PATCH v2] Input: tca8418_keypad - fix potential infinite loop and OOB access on invalid keycodes
flat view
STALE82d
From: Liang Zhan <hidden>
Date: 2026-07-25 08:10:01
Also in:
lkml, stable
Subsystem:
input (keyboard, mouse, joystick, touchscreen) drivers, the rest · Maintainers:
Dmitry Torokhov, Linus Torvalds
The current code checks the raw register value against zero to detect an empty FIFO. However, the TCA8418 datasheet defines key code 0 as the empty-FIFO condition. If the hardware returns garbage data, the loop may never terminate and the extracted keycode can cause an out-of-bounds access on keymap[]. Move the empty-FIFO check to operate on the extracted key code so that the loop terminates correctly. Additionally, validate row/column indices against the configured matrix dimensions before indexing into the keymap array, skipping invalid events. Cc: stable@vger.kernel.org Signed-off-by: Zhian Liang <redacted> --- changes in v2: - Moved empty-FIFO check to operate on extracted key code instead of raw register value. - Added row/col validation against configured matrix dimensions. - Dropped explicit 0xFF check as requested. --- drivers/input/keyboard/tca8418_keypad.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index b124e576feca..36d4a7c38bb1 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c@@ -114,6 +114,8 @@ struct tca8418_keypad { struct input_dev *input; unsigned int row_shift; + unsigned int rows; + unsigned int cols; }; /*
@@ -171,19 +173,28 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) break; } - /* Assume that key code 0 signifies empty FIFO */ - if (reg <= 0) - break; state = reg & KEY_EVENT_VALUE; code = reg & KEY_EVENT_CODE; + /* Key code 0 signifies empty FIFO */ + if (!code) + break; + row = code / TCA8418_MAX_COLS; col = code % TCA8418_MAX_COLS; row = (col) ? row : row - 1; col = (col) ? col - 1 : TCA8418_MAX_COLS - 1; + /* Validate against configured matrix size */ + if (row >= keypad_data->rows || col >= keypad_data->cols) { + dev_err(&keypad_data->client->dev, + "invalid key code %d (row %d, col %d)\n", + code, row, col); + continue; + } + code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift); input_event(input, EV_MSC, MSC_SCAN, code); input_report_key(input, keymap[code], state);
@@ -298,6 +309,8 @@ static int tca8418_keypad_probe(struct i2c_client *client) keypad_data->client = client; keypad_data->row_shift = row_shift; + keypad_data->rows = rows; + keypad_data->cols = cols; /* Read key lock register, if this fails assume device not present */ error = tca8418_read_byte(keypad_data, REG_KEY_LCK_EC, ®);
--
2.34.1