mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/4] HID: cougar: fix out-of-bounds read in cougar_raw_event
@ 2026-07-14 13:16 Jiale Yao
  2026-07-14 13:16 ` [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event Jiale Yao
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jiale Yao @ 2026-07-14 13:16 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel; +Cc: Jiale Yao

cougar_raw_event() accesses data[COUGAR_FIELD_CODE] and
data[COUGAR_FIELD_ACTION] (offsets 1 and 2) before validating
the report size.  A malformed HID report shorter than 3 bytes
would read past the allocated buffer.

Add a size < 3 check before accessing those fields.

Assisted-by: Claude:deepseek-v4-pro
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/hid/hid-cougar.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c
index ad027c45f162..9927f45a795b 100644
--- a/drivers/hid/hid-cougar.c
+++ b/drivers/hid/hid-cougar.c
@@ -270,6 +270,12 @@ static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report,
 	if (!shared->enabled || !shared->input)
 		return -EPERM;
 
+	if (size < 3) {
+		hid_err(hdev, "Received HID report of bad size (%d)",
+			size);
+		return -EPERM;
+	}
+
 	code = data[COUGAR_FIELD_CODE];
 	action = data[COUGAR_FIELD_ACTION];
 	for (i = 0; cougar_mapping[i][0]; i++) {
-- 
2.34.1


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

* [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event
  2026-07-14 13:16 [PATCH 1/4] HID: cougar: fix out-of-bounds read in cougar_raw_event Jiale Yao
@ 2026-07-14 13:16 ` Jiale Yao
  2026-07-17 22:55   ` Stuart Hayhurst
  2026-07-14 13:16 ` [PATCH 3/4] HID: mcp2221: fix out-of-bounds read in mcp2221_raw_event Jiale Yao
  2026-07-14 13:16 ` [PATCH 4/4] HID: cp2112: fix out-of-bounds read in cp2112_raw_event Jiale Yao
  2 siblings, 1 reply; 5+ messages in thread
From: Jiale Yao @ 2026-07-14 13:16 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel; +Cc: Jiale Yao

Both the STATUS_REPORT and FIRMWARE_REPORT paths access data[4].
Add a size < 5 guard before the report dispatch.

Assisted-by: Claude:deepseek-v4-pro
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/hid/hid-corsair-void.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/hid/hid-corsair-void.c b/drivers/hid/hid-corsair-void.c
index 5e9a5b8f7f16..7c5435de6aae 100644
--- a/drivers/hid/hid-corsair-void.c
+++ b/drivers/hid/hid-corsair-void.c
@@ -740,6 +740,8 @@ static int corsair_void_raw_event(struct hid_device *hid_dev,
 	struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);
 	bool was_connected = drvdata->connected;
 
+	if (size < 5)
+		return 0;
 	/* Description of packets are documented at the top of this file */
 	if (hid_report->id == CORSAIR_VOID_STATUS_REPORT_ID) {
 		drvdata->mic_up = FIELD_GET(CORSAIR_VOID_MIC_MASK, data[2]);
-- 
2.34.1


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

* [PATCH 3/4] HID: mcp2221: fix out-of-bounds read in mcp2221_raw_event
  2026-07-14 13:16 [PATCH 1/4] HID: cougar: fix out-of-bounds read in cougar_raw_event Jiale Yao
  2026-07-14 13:16 ` [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event Jiale Yao
@ 2026-07-14 13:16 ` Jiale Yao
  2026-07-14 13:16 ` [PATCH 4/4] HID: cp2112: fix out-of-bounds read in cp2112_raw_event Jiale Yao
  2 siblings, 0 replies; 5+ messages in thread
From: Jiale Yao @ 2026-07-14 13:16 UTC (permalink / raw)
  To: Rishi Gupta, Jiri Kosina, Benjamin Tissoires, linux-i2c,
	linux-input, linux-kernel
  Cc: Jiale Yao

The handler dispatches on data[0] without checking size >= 1.
Add a top-level guard and per-case minimum-size checks:
data[2] for the I2C_WR_DATA group, data[20] and
data[50+sizeof(adc_values)] for I2C_PARAM_OR_STATUS,
sizeof(struct mcp_get/set_gpio) for GPIO paths,
and 4+data[3] for the I2C_GET_DATA partial-read memcpy.

Assisted-by: Claude:deepseek-v4-pro
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/hid/hid-mcp2221.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index e4ddd8e9293b..0423b5affe8f 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -861,12 +861,17 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 	u8 *buf;
 	struct mcp2221 *mcp = hid_get_drvdata(hdev);
 
+	if (size < 1)
+		return 1;
+
 	switch (data[0]) {
 
 	case MCP2221_I2C_WR_DATA:
 	case MCP2221_I2C_WR_NO_STOP:
 	case MCP2221_I2C_RD_DATA:
 	case MCP2221_I2C_RD_RPT_START:
+		if (size < 3)
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			mcp->status = 0;
@@ -878,6 +883,12 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_I2C_PARAM_OR_STATUS:
+		if (size < 21)
+			return 1;
+#if IS_REACHABLE(CONFIG_IIO)
+		if (size < 50 + sizeof(mcp->adc_values))
+			return 1;
+#endif
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			if ((mcp->txbuf[3] == MCP2221_I2C_SET_SPEED) &&
@@ -901,6 +912,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_I2C_GET_DATA:
+		if (size < 4)
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			if (data[2] == MCP2221_I2C_ADDR_NACK) {
@@ -918,7 +931,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 			}
 			if (data[2] == MCP2221_I2C_READ_COMPL ||
 			    data[2] == MCP2221_I2C_READ_PARTIAL) {
-				if (!mcp->rxbuf || mcp->rxbuf_idx < 0 || data[3] > 60) {
+				if (!mcp->rxbuf || mcp->rxbuf_idx < 0 ||
+				    data[3] > 60 || size < 4 + data[3]) {
 					mcp->status = -EINVAL;
 					break;
 				}
@@ -941,6 +955,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_GPIO_GET:
+		if (size < sizeof(struct mcp_get_gpio))
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
@@ -958,6 +974,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_GPIO_SET:
+		if (size < sizeof(struct mcp_set_gpio))
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
@@ -974,6 +992,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_SET_SRAM_SETTINGS:
+		if (size < 2)
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			mcp->status = 0;
@@ -985,6 +1005,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_GET_SRAM_SETTINGS:
+		if (size < 26)
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			memcpy(&mcp->mode, &data[22], 4);
@@ -1000,6 +1022,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 		break;
 
 	case MCP2221_READ_FLASH_DATA:
+		if (size < 8)
+			return 1;
 		switch (data[1]) {
 		case MCP2221_SUCCESS:
 			mcp->status = 0;
-- 
2.34.1


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

* [PATCH 4/4] HID: cp2112: fix out-of-bounds read in cp2112_raw_event
  2026-07-14 13:16 [PATCH 1/4] HID: cougar: fix out-of-bounds read in cougar_raw_event Jiale Yao
  2026-07-14 13:16 ` [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event Jiale Yao
  2026-07-14 13:16 ` [PATCH 3/4] HID: mcp2221: fix out-of-bounds read in mcp2221_raw_event Jiale Yao
@ 2026-07-14 13:16 ` Jiale Yao
  2 siblings, 0 replies; 5+ messages in thread
From: Jiale Yao @ 2026-07-14 13:16 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel; +Cc: Jiale Yao

The TRANSFER_STATUS_RESPONSE path dereferences xfer->length at
offset 6, requiring sizeof(*xfer) bytes.  The DATA_READ_RESPONSE
path uses the device-supplied read_length to drive memcpy()
without clamping it to the remaining report size.  Add both
checks, and clamp read_length to size - 3.

Assisted-by: Claude:deepseek-v4-pro
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/hid/hid-cp2112.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 04379db93571..99e31724a421 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -1430,6 +1430,11 @@ static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
 
 	switch (data[0]) {
 	case CP2112_TRANSFER_STATUS_RESPONSE:
+		if (size < sizeof(*xfer)) {
+			hid_err(hdev, "short transfer status report(%d < %zu)\n", size,
+				sizeof(*xfer));
+			return 0;
+		}
 		hid_dbg(hdev, "xfer status: %02x %02x %04x %04x\n",
 			xfer->status0, xfer->status1,
 			be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length));
@@ -1463,12 +1468,18 @@ static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
 		atomic_set(&dev->xfer_avail, 1);
 		break;
 	case CP2112_DATA_READ_RESPONSE:
+		if (size < 4) {
+			hid_err(hdev, "short data read response(%d < 4)\n", size);
+			return 0;
+		}
 		hid_dbg(hdev, "read response: %02x %02x\n", data[1], data[2]);
 
 		dev->read_length = data[2];
 		if (dev->read_length > sizeof(dev->read_data))
 			dev->read_length = sizeof(dev->read_data);
 
+		if (dev->read_length > size - 3)
+			dev->read_length = size - 3;
 		memcpy(dev->read_data, &data[3], dev->read_length);
 		atomic_set(&dev->read_avail, 1);
 		break;
-- 
2.34.1


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

* Re: [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event
  2026-07-14 13:16 ` [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event Jiale Yao
@ 2026-07-17 22:55   ` Stuart Hayhurst
  0 siblings, 0 replies; 5+ messages in thread
From: Stuart Hayhurst @ 2026-07-17 22:55 UTC (permalink / raw)
  To: Jiale Yao, Jiri Kosina, Benjamin Tissoires, linux-input,
	linux-kernel, stuart.a.hayhurst

Hi,

Looking through this, I had a couple thoughts:

  - It should send a warning for unexpected sizes, since most likely 
it's a format we haven't seen yet

  - 5 is a bit of a magic number, especially as some packets of other 
sizes pass through, but we don't do anything with them (yet?)

  - AFAIK returning 0 indicates everything was OK, when actually we 
bailed out. By convention, shouldn't this return 1 on failure?


The patch I submitted a few weeks ago handled these: 
https://lore.kernel.org/all/20260630010656.626157-3-stuart.a.hayhurst@gmail.com/


Stuart


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

end of thread, other threads:[~2026-07-17 22:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-14 13:16 [PATCH 1/4] HID: cougar: fix out-of-bounds read in cougar_raw_event Jiale Yao
2026-07-14 13:16 ` [PATCH 2/4] HID: corsair-void: fix out-of-bounds read in corsair_void_raw_event Jiale Yao
2026-07-17 22:55   ` Stuart Hayhurst
2026-07-14 13:16 ` [PATCH 3/4] HID: mcp2221: fix out-of-bounds read in mcp2221_raw_event Jiale Yao
2026-07-14 13:16 ` [PATCH 4/4] HID: cp2112: fix out-of-bounds read in cp2112_raw_event Jiale Yao

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