mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Input: raydium_i2c_ts - validate report parameters
@ 2026-09-27 11:44 Pooyan Azad
  2026-09-27 17:30 ` Muhammad Bilal
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Pooyan Azad @ 2026-09-27 11:44 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Uwe Kleine-König, Muhammad Bilal, Herlangga Maulani,
	linux-input, linux-kernel

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.

Allocate the report buffer once valid main firmware information is
available, and resize it if a firmware update changes the packet size.
This also handles devices that probe in bootloader mode, where the packet
size is not known yet.

Finally, return main firmware query failures from initialization so probe
and firmware update do not continue with invalid report parameters. Keep
bootloader HWID query failures non-fatal so the recovery interface remains
available.

Fixes: 48a2b783483b ("Input: add Raydium I2C touchscreen driver")
Link: https://lore.kernel.org/all/20260728135127.48971-1-meatuni001@gmail.com/
Cc: stable@vger.kernel.org
Signed-off-by: Pooyan Azad <pooyan.azadparvar@gmail.com>
---
This partially overlaps Muhammad Bilal's earlier patch linked above. That
patch propagates both main and bootloader query errors. This version keeps
bootloader HWID errors non-fatal so recovery remains available, and moves
report-buffer allocation into the main query path so size changes can be
handled safely.

Compile-tested with:

  make O=/tmp/raydium-build W=1 -j$(nproc) \
    drivers/input/touchscreen/raydium_i2c_ts.o

 drivers/input/touchscreen/raydium_i2c_ts.c | 64 +++++++++++++---------
 1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 0256055abcef..1d7f53d0b9fe 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 */
@@ -331,7 +332,10 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
 {
 	struct i2c_client *client = ts->client;
 	struct raydium_data_info data_info;
+	struct raydium_info info;
 	__le32 query_bank_addr;
+	u8 *report_data;
+	u8 report_size;
 
 	int error, retry_cnt;
 
@@ -341,26 +345,22 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
 		if (error)
 			continue;
 
-		/*
-		 * Warn user if we already allocated memory for reports and
-		 * then the size changed (due to firmware update?) and keep
-		 * old size instead.
-		 */
-		if (ts->report_data && ts->pkg_size != data_info.pkg_size) {
-			dev_warn(&client->dev,
-				 "report size changes, was: %d, new: %d\n",
-				 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;
+		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;
 		}
 
-		ts->contact_size = data_info.tp_info_size;
-		ts->data_bank_addr = le32_to_cpu(data_info.data_bank_addr);
-
-		dev_dbg(&client->dev,
-			"data_bank_addr: %#08x, report_size: %d, contact_size: %d\n",
-			ts->data_bank_addr, ts->report_size, ts->contact_size);
+		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;
+		}
 
 		error = raydium_i2c_read(client, RM_CMD_QUERY_BANK,
 					 &query_bank_addr,
@@ -369,10 +369,29 @@ static int raydium_i2c_query_ts_info(struct raydium_data *ts)
 			continue;
 
 		error = raydium_i2c_read(client, le32_to_cpu(query_bank_addr),
-					 &ts->info, sizeof(ts->info));
+					 &info, sizeof(info));
 		if (error)
 			continue;
 
+		if (!ts->report_data || ts->pkg_size != data_info.pkg_size) {
+			report_data = devm_krealloc(&client->dev, ts->report_data,
+						    data_info.pkg_size, GFP_KERNEL);
+			if (!report_data)
+				return -ENOMEM;
+
+			ts->report_data = report_data;
+		}
+
+		ts->pkg_size = data_info.pkg_size;
+		ts->report_size = report_size;
+		ts->contact_size = data_info.tp_info_size;
+		ts->data_bank_addr = le32_to_cpu(data_info.data_bank_addr);
+		ts->info = info;
+
+		dev_dbg(&client->dev,
+			"data_bank_addr: %#08x, report_size: %d, contact_size: %d\n",
+			ts->data_bank_addr, ts->report_size, ts->contact_size);
+
 		return 0;
 	}
 
@@ -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;
 }
@@ -1116,11 +1135,6 @@ static int raydium_i2c_probe(struct i2c_client *client)
 		return error;
 	}
 
-	ts->report_data = devm_kmalloc(&client->dev,
-				       ts->pkg_size, GFP_KERNEL);
-	if (!ts->report_data)
-		return -ENOMEM;
-
 	ts->input = devm_input_allocate_device(&client->dev);
 	if (!ts->input) {
 		dev_err(&client->dev, "Failed to allocate input device\n");
-- 
2.43.0

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-09-28 16:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-27 11:44 [PATCH] Input: raydium_i2c_ts - validate report parameters Pooyan Azad
2026-09-27 17:30 ` Muhammad Bilal
2026-09-27 17:58   ` Pooyan Azadparvar
2026-09-28  2:38 ` Dmitry Torokhov
2026-09-28  6:04   ` Pooyan Azadparvar
2026-09-28 16:26 ` [PATCH v2 0/3] Input: raydium_i2c_ts report handling fixes Pooyan Azad
2026-09-28 16:26   ` [PATCH v2 1/3] Input: raydium_i2c_ts - validate report parameters Pooyan Azad
2026-09-28 16:26   ` [PATCH v2 2/3] Input: raydium_i2c_ts - resize report buffer after firmware update Pooyan Azad
2026-09-28 16:26   ` [PATCH v2 3/3] Input: raydium_i2c_ts - defer report buffer allocation Pooyan Azad

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®