[PATCH] Input: raydium_i2c_ts - propagate device info query errors from raydium_i2c_initialize()

Muhammad Bilal <[email protected]>
Newsgroups org.kernel.vger.linux-input,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
raydium_i2c_initialize() calls raydium_i2c_query_ts_info() (or
raydium_i2c_query_ts_bootloader_info() in bootloader mode) but never
checks or returns its result. raydium_i2c_probe() treats a zero
return from raydium_i2c_initialize() as full success, then
unconditionally allocates ts->report_data with size ts->pkg_size and
registers the IRQ handler.

If raydium_i2c_query_ts_info() fails on every one of its own retries
(e.g. because the device is still completing power-up when probe
runs), ts->pkg_size and ts->report_size are left at their
devm_kzalloc()'d default of 0, and ts->report_data is never
meaningfully allocated: devm_kmalloc(dev, 0, GFP_KERNEL) returns
ZERO_SIZE_PTR, a non-NULL sentinel (include/linux/slab.h) that must
never be dereferenced, which passes the existing
'if (!ts->report_data)' check. RAYDIUM_TS_MAIN is also 0, the same
value ts->boot_mode has from devm_kzalloc() before
raydium_i2c_check_fw_status() ever confirms a mode, so a
spurious/garbage first read that raydium_i2c_check_fw_status()
does not recognize as either ack byte leaves boot_mode looking like
an already-confirmed RAYDIUM_TS_MAIN without it ever being set.

With both conditions met, probe() completes 'successfully' with a
live IRQ, ts->boot_mode == RAYDIUM_TS_MAIN, and ts->report_data
pointing at a zero-size allocation. The next touch fires
raydium_i2c_irq(), which passes the boot_mode check and dereferences
ts->report_data at offset ts->report_size, both derived from that
never-actually-confirmed state, producing a NULL/invalid pointer
dereference in interrupt context:

  BUG: kernel NULL pointer dereference
  RIP: raydium_i2c_irq+0x5b/0x1d0 [raydium_i2c_ts]

On kernels with CONFIG_PANIC_ON_OOPS=y (e.g. linux-hardened) this is
a full system panic on the first touch; on a default kernel it only
kills the IRQ thread, but the touchscreen stops working and a
subsequent reboot can hang cleaning up the recursive fault.

Have raydium_i2c_initialize() return the result of the info query in
both the bootloader and main-firmware branches, so a failure there
aborts raydium_i2c_probe() before report_data or the IRQ are ever
set up, instead of leaving them in this half-initialized state.

Reported-by: Herlangga Maulani <[email protected]>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221777
Fixes: 48a2b783483b ("Input: add Raydium I2C touchscreen driver")
Cc: [email protected]
Signed-off-by: Muhammad Bilal <[email protected]>
---
 drivers/input/touchscreen/raydium_i2c_ts.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 0256055abcef..a0b23772f4c0 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -426,9 +426,9 @@ static int raydium_i2c_initialize(struct raydium_data *ts)
 		ts->boot_mode = RAYDIUM_TS_BLDR;
 
 	if (ts->boot_mode == RAYDIUM_TS_BLDR)
-		raydium_i2c_query_ts_bootloader_info(ts);
+		error = raydium_i2c_query_ts_bootloader_info(ts);
 	else
-		raydium_i2c_query_ts_info(ts);
+		error = raydium_i2c_query_ts_info(ts);
 
 	return error;
 }
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.