[PATCH v2 1/3] Input: raydium_i2c_ts - validate report parameters

From: Pooyan Azad

Date: Mon Sep 28 2026 - 12:29:14 EST


The controller supplies packet and per-contact sizes used to allocate and
parse touch reports. The driver trusts these values without validation.

A packet size smaller than the two-byte checksum makes report_size wrap,
allowing the IRQ handler to read beyond the report buffer. A zero or
undersized contact size can cause a divide by zero or make the contact
parser read beyond a record.

Validate both sizes before publishing them, and reject reports that
describe more contacts than the input device has slots. Return main
firmware query errors from initialization as well; otherwise rejecting
invalid parameters would not stop probe or firmware update.

Fixes: 48a2b783483b ("Input: add Raydium I2C touchscreen driver")
Link: https://lore.kernel.org/r/20260728135127.48971-1-meatuni001@xxxxxxxxx/
Link: https://lore.kernel.org/r/20260927114425.442803-1-pooyan.azadparvar@xxxxxxxxx/
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Muhammad Bilal <meatuni001@xxxxxxxxx>
Signed-off-by: Pooyan Azad <pooyan.azadparvar@xxxxxxxxx>
---
drivers/input/touchscreen/raydium_i2c_ts.c | 23 ++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 0256055abcef..03ea0ae62999 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -64,6 +64,7 @@
#define RM_CONTACT_PRESSURE_POS 5
#define RM_CONTACT_WIDTH_X_POS 6
#define RM_CONTACT_WIDTH_Y_POS 7
+#define RM_MIN_CONTACT_SIZE (RM_CONTACT_WIDTH_Y_POS + 1)

/* Bootloader relative info */
#define RM_BL_WRT_CMD_SIZE 3 /* bl flash wrt cmd size */
@@ -332,6 +333,7 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
struct i2c_client *client = ts->client;
struct raydium_data_info data_info;
__le32 query_bank_addr;
+ u8 report_size;

int error, retry_cnt;

@@ -341,6 +343,23 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
if (error)
continue;

+ if (data_info.pkg_size < RM_PACKET_CRC_SIZE) {
+ dev_err(&client->dev,
+ "invalid report sizes: packet=%u contact=%u\n",
+ data_info.pkg_size, data_info.tp_info_size);
+ return -EINVAL;
+ }
+
+ report_size = data_info.pkg_size - RM_PACKET_CRC_SIZE;
+ if (data_info.tp_info_size < RM_MIN_CONTACT_SIZE ||
+ data_info.tp_info_size > report_size ||
+ report_size / data_info.tp_info_size > RM_MAX_TOUCH_NUM) {
+ dev_err(&client->dev,
+ "invalid report sizes: packet=%u contact=%u\n",
+ data_info.pkg_size, data_info.tp_info_size);
+ return -EINVAL;
+ }
+
/*
* Warn user if we already allocated memory for reports and
* then the size changed (due to firmware update?) and keep
@@ -352,7 +371,7 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
ts->pkg_size, data_info.pkg_size);
} else {
ts->pkg_size = data_info.pkg_size;
- ts->report_size = ts->pkg_size - RM_PACKET_CRC_SIZE;
+ ts->report_size = report_size;
}

ts->contact_size = data_info.tp_info_size;
@@ -428,7 +447,7 @@ static int raydium_i2c_initialize(struct raydium_data *ts)
if (ts->boot_mode == RAYDIUM_TS_BLDR)
raydium_i2c_query_ts_bootloader_info(ts);
else
- raydium_i2c_query_ts_info(ts);
+ error = raydium_i2c_query_ts_info(ts);

return error;
}
--
2.43.0