Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH v2] HID: ft260: validate report size and payload length in raw_event
From: Sebastian Josue Alba Vives @ 2026-03-24 20:18 UTC (permalink / raw)
  To: michael.zaidman, jikos, bentiss
  Cc: linux-i2c, linux-input, linux-kernel, stable,
	Sebastian Josue Alba Vives
In-Reply-To: <20260324173527.11321-1-sebasjosue84@gmail.com>

ft260_raw_event() casts the raw data buffer to a
ft260_i2c_input_report struct and accesses its fields without
validating the size parameter. Since __hid_input_report() invokes
the driver's raw_event callback before hid_report_raw_event()
performs its own report-size validation, a device sending a
truncated HID report can cause out-of-bounds heap reads.

Additionally, even with a full-sized report, a corrupted
xfer->length field can cause memcpy to read beyond the report
buffer. The existing check only validates against the destination
buffer size, not the source data available in the report.

Add two checks: reject reports shorter than FT260_REPORT_MAX_LENGTH,
and verify that xfer->length does not exceed the actual data
available in the report. Log warnings to aid debugging.

Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
---
 drivers/hid/hid-ft260.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
index 333341e80..68008a423 100644
--- a/drivers/hid/hid-ft260.c
+++ b/drivers/hid/hid-ft260.c
@@ -1068,6 +1068,17 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
 	struct ft260_device *dev = hid_get_drvdata(hdev);
 	struct ft260_i2c_input_report *xfer = (void *)data;
 
+	if (size < FT260_REPORT_MAX_LENGTH) {
+		hid_warn(hdev, "short report: %d\n", size);
+		return 0;
+	}
+
+	if (xfer->length > size - offsetof(struct ft260_i2c_input_report, data)) {
+		hid_warn(hdev, "payload %d exceeds report size %d\n",
+			 xfer->length, size);
+		return 0;
+	}
+
 	if (xfer->report >= FT260_I2C_REPORT_MIN &&
 	    xfer->report <= FT260_I2C_REPORT_MAX) {
 		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] HID: ft260: validate report size in raw_event handler
From: Michael Zaidman @ 2026-03-24 20:00 UTC (permalink / raw)
  To: Sebastian Josue Alba Vives
  Cc: jikos, bentiss, linux-i2c, linux-input, linux-kernel, stable
In-Reply-To: <20260324173527.11321-1-sebasjosue84@gmail.com>

Hi Sebastian,

Thanks for the patch. The report size validation gap in ft260_raw_event()
is a valid concern - the raw_event callback is indeed invoked before
hid_report_raw_event() validates the report size, so a truncated report
from a malicious or buggy device could cause OOB reads.

However, I have a couple of comments on the proposed fix:

Please use the existing FT260_REPORT_MAX_LENGTH macro instead of the
hardcoded 64.

More importantly, the size < 64 check alone is insufficient. It prevents
accessing struct fields in a truncated buffer, but does not guard against
a corrupted xfer->length field in an otherwise full-sized report.

Consider: a device sends a valid 64-byte report (passes the size check),
but with xfer->length set to, say, 100. The data payload starts at offset 2,
so only 62 bytes are available in the buffer. The existing check at line 1077
validates against the destination buffer (dev->read_len - dev->read_idx),
not the source. If read_len is large enough (e.g., 180), the check passes,
and the memcpy reads 100 bytes from a 62-byte region - a 38-byte OOB heap
read from the source side.

A more complete fix would validate xfer->length against the actual report size:

    struct ft260_i2c_input_report *xfer = (void *)data;
    if (size < FT260_REPORT_MAX_LENGTH) {
        hid_warn(hdev, "short report: %d\n", size);
        return 0;
    }
    if (xfer->length > size -
        offsetof(struct ft260_i2c_input_report, data)) {
        hid_warn(hdev, "payload %d exceeds report size %d\n",
             xfer->length, size);
        return 0;
    }
This catches both truncated reports and corrupted length fields.

Would you like to send a v2 addressing the above?

Thanks, Michael

On Tue, Mar 24, 2026 at 7:35 PM Sebastian Josue Alba Vives
<sebasjosue84@gmail.com> wrote:
>
> ft260_raw_event() casts the raw data buffer to a
> ft260_i2c_input_report struct and accesses its fields without
> validating the size parameter. Since __hid_input_report() invokes
> the driver's raw_event callback before hid_report_raw_event()
> performs its own report-size validation, a device sending a
> truncated HID report can cause out-of-bounds heap reads in the
> kernel.
>
> In the I2C response path, xfer->length (data[1]) is used as the
> length for a memcpy into dev->read_buf. While xfer->length is
> checked against dev->read_len, there is no check that size is large
> enough to actually contain xfer->length bytes of data starting at
> offset 2. A malicious USB device could therefore cause an OOB read
> from the kernel heap, with the result accessible from userspace via
> the I2C read interface.
>
> FT260 devices use 64-byte HID reports. Add a check at the top of
> the handler to reject any report shorter than expected, and log a
> warning to aid debugging.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
> ---
>  drivers/hid/hid-ft260.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
> index 333341e80..7ca323992 100644
> --- a/drivers/hid/hid-ft260.c
> +++ b/drivers/hid/hid-ft260.c
> @@ -1068,6 +1068,12 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
>         struct ft260_device *dev = hid_get_drvdata(hdev);
>         struct ft260_i2c_input_report *xfer = (void *)data;
>
> +       /* FT260 always sends 64-byte reports */
> +       if (size < 64) {
> +               hid_warn(hdev, "report too short: %d < 64\n", size);
> +               return 0;
> +       }
> +
>         if (xfer->report >= FT260_I2C_REPORT_MIN &&
>             xfer->report <= FT260_I2C_REPORT_MAX) {
>                 ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
> --
> 2.43.0
>

^ permalink raw reply

* Re: [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b
From: Dmitry Torokhov @ 2026-03-24 19:42 UTC (permalink / raw)
  To: david
  Cc: Kaustabh Chakraborty, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jason A. Donenfeld, Matthias Schiffer,
	Vincent Huang, Casey Connolly, linux-input, devicetree,
	linux-kernel, phone-devel, Krzysztof Kozlowski
In-Reply-To: <20260324-synaptics-rmi4-v8-1-2168d2df68f5@ixit.cz>

On Tue, Mar 24, 2026 at 08:40:34PM +0100, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> Mostly irrelevant for authentic Synaptics touchscreens, but very important
> for applying workarounds to cheap TS knockoffs.
> 
> These knockoffs work well with the downstream driver, and since the user
> has no way to distinguish them, later in this patch set, we introduce
> workarounds to ensure they function as well as possible.
> 
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---
>  Documentation/devicetree/bindings/input/syna,rmi4.yaml | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> index 8685ef4481f4a..fb4804ac3544d 100644
> --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> @@ -18,9 +18,14 @@ description: |
>  
>  properties:
>    compatible:
> -    enum:
> -      - syna,rmi4-i2c
> -      - syna,rmi4-spi
> +    oneOf:
> +      - enum:
> +          - syna,rmi4-i2c
> +          - syna,rmi4-spi
> +      - items:
> +          - enum:
> +              - syna,rmi4-s3706b  # OnePlus 6/6T

I thought that all the workarounds will be keyed off this new
compatible, but I do not see that. What am I missing?

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH v8 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Kaustabh Chakraborty <kauschluss@disroot.org>

Some replacement displays include third-party touch ICs which do not
expose the function number and the interrupt status in its PDT entries.

OnePlus 6 (original touch IC)
  rmi4_i2c 12-0020: read 6 bytes at 0x00e3: 0 (2b 22 0d 06 01 01)

OnePlus 6 (aftermarket touch IC)
  rmi4_i2c 12-0020: read 6 bytes at 0x00e3: 0 (2c 23 0d 06 00 00)

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[codeflow adjustments, checkpatch fixes, wording]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_driver.c | 63 +++++++++++++++++++++++++++++++++++------
 drivers/input/rmi4/rmi_driver.h |  3 ++
 include/linux/rmi.h             |  3 ++
 3 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index fc84799c36e04..bb1db5bbb3abb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -462,9 +462,10 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
 	return 0;
 }
 
-static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
-			      struct pdt_entry *entry, u16 pdt_address)
+static int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
+			      struct pdt_scan_state *state, u16 pdt_address)
 {
+	const struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
 	u8 buf[RMI_PDT_ENTRY_SIZE];
 	int error;
 
@@ -475,6 +476,21 @@ static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
 		return error;
 	}
 
+	if (pdata->pdt_fallback_size > state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1) {
+		/* Use the description bytes from the driver */
+		buf[5] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS];
+		buf[4] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1];
+
+		error = rmi_read_block(rmi_dev, pdt_address, buf,
+				RMI_PDT_ENTRY_SIZE - 2);
+		if (error) {
+			dev_err(&rmi_dev->dev,
+					"Read PDT entry at %#06x failed, code: %d.\n",
+					pdt_address, error);
+			return error;
+		}
+	}
+
 	entry->page_start = pdt_address & RMI4_PAGE_MASK;
 	entry->query_base_addr = buf[0];
 	entry->command_base_addr = buf[1];
@@ -522,6 +538,7 @@ static bool rmi_pdt_entry_is_valid(struct rmi_device *rmi_dev,
 	}
 
 	state->pdts[fn] = true;
+	state->pdt_count++;
 	return true;
 }
 
@@ -546,7 +563,7 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
 	int retval;
 
 	for (addr = pdt_start; addr >= pdt_end; addr -= RMI_PDT_ENTRY_SIZE) {
-		error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, addr);
+		error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, state, addr);
 		if (error)
 			return error;
 
@@ -1023,9 +1040,13 @@ static int rmi_driver_remove(struct device *dev)
 }
 
 #ifdef CONFIG_OF
-static int rmi_driver_of_probe(struct device *dev,
-				struct rmi_device_platform_data *pdata)
+static const u8 rmi_s3706_fallback_pdt[] = {34, 41, 01, 01, 12, 01};
+
+static int rmi_driver_of_probe(struct rmi_device *rmi_dev,
+			       struct rmi_device_platform_data *pdata)
 {
+	struct device *dev = rmi_dev->xport->dev;
+	u8 buf[RMI_PDT_ENTRY_SIZE];
 	int retval;
 
 	retval = rmi_of_property_read_u32(dev, &pdata->reset_delay_ms,
@@ -1033,11 +1054,37 @@ static int rmi_driver_of_probe(struct device *dev,
 	if (retval)
 		return retval;
 
+	/*
+	 * In some aftermerket touch ICs, the first PDT entry is empty and
+	 * the function number register is 0. If so, the driver
+	 * may have provide backup PDT entries.
+	 */
+
+	retval = rmi_read_block(rmi_dev, PDT_START_SCAN_LOCATION,
+			buf, RMI_PDT_ENTRY_SIZE);
+	if (retval) {
+		dev_err(dev, "Read PDT entry at %#06x failed, code: %d.\n",
+			PDT_START_SCAN_LOCATION, retval);
+		return retval;
+	}
+
+	if (!RMI4_END_OF_PDT(buf[5]))
+		return 0;
+
+	/* List of known PDT entries per compatible. */
+	if (of_device_is_compatible(dev->of_node, "syna,rmi4-s3706b")) {
+		pdata->pdt_fallback_desc = rmi_s3706_fallback_pdt;
+		pdata->pdt_fallback_size = ARRAY_SIZE(rmi_s3706_fallback_pdt);
+	} else {
+		dev_err(dev, "First PDT entry is empty and no backup values provided.\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 #else
-static inline int rmi_driver_of_probe(struct device *dev,
-					struct rmi_device_platform_data *pdata)
+static inline int rmi_driver_of_probe(struct rmi_device *rmi_dev,
+				      struct rmi_device_platform_data *pdata)
 {
 	return -ENODEV;
 }
@@ -1158,7 +1205,7 @@ static int rmi_driver_probe(struct device *dev)
 	pdata = rmi_get_platform_data(rmi_dev);
 
 	if (rmi_dev->xport->dev->of_node) {
-		retval = rmi_driver_of_probe(rmi_dev->xport->dev, pdata);
+		retval = rmi_driver_of_probe(rmi_dev, pdata);
 		if (retval)
 			return retval;
 	}
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 2c47373c3d177..a6a29fde49f35 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -31,6 +31,8 @@
 #define RMI_PDT_FUNCTION_VERSION_MASK   0x60
 #define RMI_PDT_INT_SOURCE_COUNT_MASK   0x07
 
+#define RMI_OF_PDT_DESC_CELLS 2
+
 #define PDT_START_SCAN_LOCATION 0x00e9
 #define PDT_END_SCAN_LOCATION	0x0005
 #define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
@@ -50,6 +52,7 @@ struct pdt_entry {
 
 struct pdt_scan_state {
 	u8 empty_pages;
+	u8 pdt_count;
 	bool pdts[RMI_PDT_MAX + 1];
 };
 
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index ab7eea01ab427..4ba2cefac8558 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -214,6 +214,9 @@ struct rmi_device_platform_data {
 	int reset_delay_ms;
 	int irq;
 
+	unsigned int pdt_fallback_size;
+	const u8 *pdt_fallback_desc;
+
 	struct rmi_device_platform_data_spi spi_data;
 
 	/* function handler pdata */

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 6/7] Input: synaptics-rmi4 - read product ID on aftermarket touch ICs
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Kaustabh Chakraborty <kauschluss@disroot.org>

Some replacement displays include third-party touch ICs which do not
report the product ID correctly unless we read directly from the
product ID register. Add a check and a fallback read to handle this.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_f01.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 47be64284b25e..2278e9b6a9207 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -250,6 +250,20 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
 		}
 	}
 
+	/*
+	 * Some aftermarket ICs put garbage into the product id field unless
+	 * we read directly from the product id register.
+	 */
+	if (props->product_id[0] < 0x20) {
+		ret = rmi_read_block(rmi_dev, query_base_addr + 11,
+				       props->product_id, RMI_PRODUCT_ID_LENGTH);
+		if (ret) {
+			dev_err(&rmi_dev->dev,
+				"Failed to read product id: %d\n", ret);
+			return ret;
+		}
+	}
+
 	return 0;
 }
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 5/7] Input: synaptics-rmi4 - don't do unaligned reads in IRQ context
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Kaustabh Chakraborty <kauschluss@disroot.org>

Some replacement displays include third-party touch ICs which incur a
significant penalty (1-2 seconds) when doing certain unaligned reads.
This is enough to break functionality when it happens in the hot path,
so adjust the interrupt handler to not read from an unaligned address.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_driver.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index dea04cf076eb4..fc84799c36e04 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -137,9 +137,14 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
 		return 0;
 
 	if (!data->attn_data.data) {
+		/*
+		 * Read the device status register as well and ignore it.
+		 * Some aftermarket ICs have issues with interrupt requests
+		 * otherwise.
+		 */
 		error = rmi_read_block(rmi_dev,
-				data->f01_container->fd.data_base_addr + 1,
-				data->irq_status, data->num_of_irq_regs);
+				data->f01_container->fd.data_base_addr,
+				(u8 *)data->irq_status - 1, data->num_of_irq_regs + 1);
 		if (error < 0) {
 			dev_err(dev, "Failed to read irqs, code=%d\n", error);
 			return error;
@@ -1078,16 +1083,17 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
 	data->num_of_irq_regs = (data->irq_count + 7) / 8;
 
 	size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
-	data->irq_memory = devm_kcalloc(dev, size, 4, GFP_KERNEL);
+	data->irq_memory = devm_kzalloc(dev, size * 4 + 1, GFP_KERNEL);
 	if (!data->irq_memory) {
 		dev_err(dev, "Failed to allocate memory for irq masks.\n");
 		return -ENOMEM;
 	}
 
-	data->irq_status	= data->irq_memory + size * 0;
-	data->fn_irq_bits	= data->irq_memory + size * 1;
-	data->current_irq_mask	= data->irq_memory + size * 2;
-	data->new_irq_mask	= data->irq_memory + size * 3;
+	/* The first byte is reserved for the device status register */
+	data->irq_status	= data->irq_memory + size * 0 + 1;
+	data->fn_irq_bits	= data->irq_memory + size * 1 + 1;
+	data->current_irq_mask	= data->irq_memory + size * 2 + 1;
+	data->new_irq_mask	= data->irq_memory + size * 3 + 1;
 
 	return retval;
 }

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 4/7] Input: synaptics-rmi4 - f55: handle zero electrode count
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Kaustabh Chakraborty <kauschluss@disroot.org>

Some third party ICs claim to support f55 but report an electrode count
of 0. Catch this and bail out early so that we don't confuse the i2c bus
with 0 sized reads.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[simplify code, adjust wording]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_f55.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/input/rmi4/rmi_f55.c b/drivers/input/rmi4/rmi_f55.c
index 488adaca4dd00..776c915b82e72 100644
--- a/drivers/input/rmi4/rmi_f55.c
+++ b/drivers/input/rmi4/rmi_f55.c
@@ -52,6 +52,11 @@ static int rmi_f55_detect(struct rmi_function *fn)
 
 	f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
 	f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
+	if (!f55->num_rx_electrodes || !f55->num_tx_electrodes) {
+		dev_err(&fn->dev, "%s: F55 query returned no electrodes, giving up\n",
+			__func__);
+		return -EINVAL;
+	}
 
 	f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
 	f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 3/7] Input: synaptics-rmi4 - f12: use hardcoded values for aftermarket touch ICs
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Kaustabh Chakraborty <kauschluss@disroot.org>

Some replacement displays include third-party touch ICs which are
devoid of register descriptors. Create a fake data register descriptor
for such ICs and provide hardcoded default values.

It isn't possible to reliably determine if the touch IC is original or
not, so these fallback values are offered as an alternative to the error
path when register descriptors aren't available.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[changes for readability / codeflow, checkpatch fixes]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_f12.c | 117 +++++++++++++++++++++++++++++++++----------
 1 file changed, 91 insertions(+), 26 deletions(-)

diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8246fe77114bb..1a103cc5f2235 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -218,6 +218,41 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
 		rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
 }
 
+static void rmi_f12_set_hardcoded_desc(struct rmi_function *fn, struct f12_data *f12)
+{
+	struct rmi_2d_sensor *sensor = &f12->sensor;
+	struct rmi_register_desc_item *reg_desc;
+
+	/* We have no f12->data_reg_desc, so the pkt_size is 0, override it with
+	 * a somewhat sensible default (this corresponds to 10 fingers).
+	 */
+	sensor->pkt_size = 88;
+
+	/*
+	 * There are no register descriptors to get these values from.
+	 * We set them to high values to either be overwritten by the clip
+	 * properties from devicetree, or to just not get in the way.
+	 */
+	sensor->max_x = 65535;
+	sensor->max_y = 65535;
+
+	/*
+	 * Create the Data1 register descriptor so that touch events
+	 * can work properly.
+	 */
+	reg_desc = devm_kcalloc(&fn->dev, 1,
+			sizeof(struct rmi_register_desc_item), GFP_KERNEL);
+	reg_desc->reg = 1;
+	reg_desc->reg_size = 80;
+	reg_desc->num_subpackets = 10;
+
+	f12->data1 = reg_desc;
+	f12->data1_offset = 0;
+	sensor->nbr_fingers = reg_desc->num_subpackets;
+	sensor->report_abs = 1;
+	sensor->attn_size += reg_desc->reg_size;
+}
+
 static irqreturn_t rmi_f12_attention(int irq, void *ctx)
 {
 	int retval;
@@ -338,6 +373,40 @@ static int rmi_f12_config(struct rmi_function *fn)
 	return 0;
 }
 
+static int rmi_f12_sensor_init(struct rmi_function *fn, struct f12_data *f12)
+{
+	struct rmi_2d_sensor *sensor = &f12->sensor;
+
+	sensor->fn = fn;
+	f12->data_addr = fn->fd.data_base_addr;
+
+	/* On quirky devices that don't have a data_reg_desc we hardcode the packet
+	 * in rmi_f12_set_hardcoded_desc(). Make sure not to set it to 0 here.
+	 */
+	if (!sensor->pkt_size)
+		sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+
+	sensor->axis_align =
+		f12->sensor_pdata.axis_align;
+
+	sensor->x_mm = f12->sensor_pdata.x_mm;
+	sensor->y_mm = f12->sensor_pdata.y_mm;
+	sensor->dribble = f12->sensor_pdata.dribble;
+
+	if (sensor->sensor_type == rmi_sensor_default)
+		sensor->sensor_type =
+			f12->sensor_pdata.sensor_type;
+
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+		sensor->pkt_size);
+
+	sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+	if (!sensor->data_pkt)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int rmi_f12_probe(struct rmi_function *fn)
 {
 	struct f12_data *f12;
@@ -351,6 +420,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
 	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
 	u16 data_offset = 0;
 	int mask_size;
+	bool hardcoded_desc_quirk = false;
 
 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
 
@@ -365,9 +435,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
 	++query_addr;
 
 	if (!(buf & BIT(0))) {
-		dev_err(&fn->dev,
-			"Behavior of F12 without register descriptors is undefined.\n");
-		return -ENODEV;
+		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+			"No register descriptors defined for F12, using fallback\n");
+		hardcoded_desc_quirk = true;
 	}
 
 	f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
@@ -375,6 +445,8 @@ static int rmi_f12_probe(struct rmi_function *fn)
 	if (!f12)
 		return -ENOMEM;
 
+	dev_set_drvdata(&fn->dev, f12);
+
 	f12->abs_mask = (unsigned long *)((char *)f12
 			+ sizeof(struct f12_data));
 	f12->rel_mask = (unsigned long *)((char *)f12
@@ -393,6 +465,18 @@ static int rmi_f12_probe(struct rmi_function *fn)
 		f12->sensor_pdata = pdata->sensor_pdata;
 	}
 
+	sensor = &f12->sensor;
+
+	if (hardcoded_desc_quirk) {
+		rmi_f12_set_hardcoded_desc(fn, f12);
+
+		ret = rmi_f12_sensor_init(fn, f12);
+		if (ret)
+			return ret;
+
+		goto skip_register_desc;
+	}
+
 	ret = rmi_read_register_desc(rmi_dev, query_addr,
 					&f12->query_reg_desc);
 	if (ret) {
@@ -423,29 +507,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
 	}
 	query_addr += 3;
 
-	sensor = &f12->sensor;
-	sensor->fn = fn;
-	f12->data_addr = fn->fd.data_base_addr;
-	sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
-
-	sensor->axis_align =
-		f12->sensor_pdata.axis_align;
-
-	sensor->x_mm = f12->sensor_pdata.x_mm;
-	sensor->y_mm = f12->sensor_pdata.y_mm;
-	sensor->dribble = f12->sensor_pdata.dribble;
-
-	if (sensor->sensor_type == rmi_sensor_default)
-		sensor->sensor_type =
-			f12->sensor_pdata.sensor_type;
-
-	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
-		sensor->pkt_size);
-	sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
-	if (!sensor->data_pkt)
-		return -ENOMEM;
-
-	dev_set_drvdata(&fn->dev, f12);
+	ret = rmi_f12_sensor_init(fn, f12);
+	if (ret)
+		return ret;
 
 	ret = rmi_f12_read_sensor_tuning(f12);
 	if (ret)
@@ -543,6 +607,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
 		data_offset += item->reg_size;
 	}
 
+skip_register_desc:
 	/* allocate the in-kernel tracking buffers */
 	sensor->tracking_pos = devm_kcalloc(&fn->dev,
 			sensor->nbr_fingers, sizeof(struct input_mt_pos),

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel, Krzysztof Kozlowski
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: David Heidelberg <david@ixit.cz>

Mostly irrelevant for authentic Synaptics touchscreens, but very important
for applying workarounds to cheap TS knockoffs.

These knockoffs work well with the downstream driver, and since the user
has no way to distinguish them, later in this patch set, we introduce
workarounds to ensure they function as well as possible.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 Documentation/devicetree/bindings/input/syna,rmi4.yaml | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index 8685ef4481f4a..fb4804ac3544d 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -18,9 +18,14 @@ description: |
 
 properties:
   compatible:
-    enum:
-      - syna,rmi4-i2c
-      - syna,rmi4-spi
+    oneOf:
+      - enum:
+          - syna,rmi4-i2c
+          - syna,rmi4-spi
+      - items:
+          - enum:
+              - syna,rmi4-s3706b  # OnePlus 6/6T
+          - const: syna,rmi4-i2c
 
   reg:
     maxItems: 1

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 2/7] Input: synaptics-rmi4 - handle duplicate/unknown PDT entries
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel
In-Reply-To: <20260324-synaptics-rmi4-v8-0-2168d2df68f5@ixit.cz>

From: Casey Connolly <casey.connolly@linaro.org>

Some third party rmi4-compatible ICs don't expose their PDT entries
very well. Add a few checks to skip duplicate entries as well as entries
for unsupported functions.

This is required to support some phones with third party displays.

Validated on a stock OnePlus 6T (original parts):
manufacturer: Synaptics, product: S3706B, fw id: 2852315

Co-developed-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/input/rmi4/rmi_driver.c | 41 +++++++++++++++++++++++++++++++++++------
 drivers/input/rmi4/rmi_driver.h |  7 +++++++
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index ccd9338a44dbe..dea04cf076eb4 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -494,12 +494,38 @@ static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
 	fd->function_version = pdt->function_version;
 }
 
+static bool rmi_pdt_entry_is_valid(struct rmi_device *rmi_dev,
+				   struct pdt_scan_state *state, u8 fn)
+{
+	switch (fn) {
+	case 0x01:
+	case 0x03:
+	case 0x11:
+	case 0x12:
+	case 0x30:
+	case 0x34:
+	case 0x3a:
+	case 0x54:
+	case 0x55:
+		if (state->pdts[fn] == true)
+			return false;
+		break;
+	default:
+		rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+			"PDT has unknown function number %#02x\n", fn);
+		return false;
+	}
+
+	state->pdts[fn] = true;
+	return true;
+}
+
 #define RMI_SCAN_CONTINUE	0
 #define RMI_SCAN_DONE		1
 
 static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
 			     int page,
-			     int *empty_pages,
+			     struct pdt_scan_state *state,
 			     void *ctx,
 			     int (*callback)(struct rmi_device *rmi_dev,
 					     void *ctx,
@@ -522,6 +548,9 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
 		if (RMI4_END_OF_PDT(pdt_entry.function_number))
 			break;
 
+		if (!rmi_pdt_entry_is_valid(rmi_dev, state, pdt_entry.function_number))
+			continue;
+
 		retval = callback(rmi_dev, ctx, &pdt_entry);
 		if (retval != RMI_SCAN_CONTINUE)
 			return retval;
@@ -532,11 +561,11 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
 	 * or more is found, stop scanning.
 	 */
 	if (addr == pdt_start)
-		++*empty_pages;
+		++state->empty_pages;
 	else
-		*empty_pages = 0;
+		state->empty_pages = 0;
 
-	return (data->bootloader_mode || *empty_pages >= 2) ?
+	return (data->bootloader_mode || state->empty_pages >= 2) ?
 					RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
 }
 
@@ -545,11 +574,11 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
 		 void *ctx, const struct pdt_entry *entry))
 {
 	int page;
-	int empty_pages = 0;
+	struct pdt_scan_state state = {0, 0, {0}};
 	int retval = RMI_SCAN_DONE;
 
 	for (page = 0; page <= RMI4_MAX_PAGE; page++) {
-		retval = rmi_scan_pdt_page(rmi_dev, page, &empty_pages,
+		retval = rmi_scan_pdt_page(rmi_dev, page, &state,
 					   ctx, callback);
 		if (retval != RMI_SCAN_CONTINUE)
 			break;
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index e84495caab151..2c47373c3d177 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -46,6 +46,13 @@ struct pdt_entry {
 	u8 function_number;
 };
 
+#define RMI_PDT_MAX 0x55
+
+struct pdt_scan_state {
+	u8 empty_pages;
+	bool pdts[RMI_PDT_MAX + 1];
+};
+
 #define RMI_REG_DESC_PRESENSE_BITS	(32 * BITS_PER_BYTE)
 #define RMI_REG_DESC_SUBPACKET_BITS	(37 * BITS_PER_BYTE)
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
	Matthias Schiffer, Vincent Huang, Casey Connolly
  Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
	phone-devel, Krzysztof Kozlowski

With the growing popularity of running upstream Linux on mobile devices,
we're beginning to run into more and more edgecases. The OnePlus 6 is a
fairly well supported 2018 era smartphone, selling over a million units
in it's first 22 days. With this level of popularity, it's almost
inevitable that we get third party replacement displays, and as a
result, replacement touchscreen controllers.

The OnePlus 6 shipped with an extremely usecase specific touchscreen
driver, it implemented only the bare minimum parts of the highly generic
rmi4 protocol, instead hardcoding most of the register addresses.
  
As a result, the third party touchscreen controllers that are often
found in replacement screens, implement only the registers that the 
downstream driver reads from. They additionally have other restrictions
such as heavy penalties on unaligned reads.
 
This series attempts to implement the necessary workaround to support  
some of these chips with the rmi4 driver. Although it's worth noting
that at the time of writing there are other unofficial controllers in
the wild that don't work even with these patches.
 
We have been shipping these patches in postmarketOS for the last several
years, and they are known to not cause any regressions on the OnePlus
6/6T (with the official Synaptics controller), however I don't own any
other rmi4 hardware to further validate this.

The series is also available (until merged) at
  https://codeberg.org/sdm845/linux/commits/b4/synaptics-rmi4

---
Changes in v8:
- The pdt_scan_state->pdts array should actually be of size
  (RMI_PDT_MAX+1). (Casey)
- Move the pdt_count introduction to the relevant patch. (Casey)
- Link to v7: https://lore.kernel.org/r/20260320-synaptics-rmi4-v7-0-379360de18d0@ixit.cz

Changes in v7:
- Rebased on top of next-20260320, no other changes.
- Link to v6: https://lore.kernel.org/r/20251113-synaptics-rmi4-v6-0-d9836afab801@ixit.cz

Changes in v6:
- Rebased on top of next-20251113.
- No other change since the Rob Herring comment.
- Link to v5: https://lore.kernel.org/r/20250410-synaptics-rmi4-v5-0-b41bb90f78b9@ixit.cz

Changes in v5:
- Removed -i2c suffix from rmi4-s3706b-i2c (Krzysztof).
- Link to v4: https://lore.kernel.org/r/20250402-synaptics-rmi4-v4-0-1bb95959e564@ixit.cz

Changes in v4:
- Replaced patch "dt-bindings: input: syna,rmi4: document syna,pdt-fallback-desc"
  with patch documenting specific touchscreen model used in OnePlus 6 and 6T.
- Fixed zero electrode return code (Dmitry).
- Switched the duplicate detection algo to bitmap (Dmitry).
- Optimized rmi_device_platform_data struct to avoid unnecessary
  padding.
- Changed fallback_size from int to unsigned int.
- Changed SoB from nickname and old address (methanal <baclofen@tuta.io>) to
  Kaustabh Chakraborty <kauschluss@disroot.org>.
  Verified ownership through the sdm845 chatroom on Matrix.
- Link to v3: https://lore.kernel.org/r/20250308-synaptics-rmi4-v3-0-215d3e7289a2@ixit.cz

Changes in v3:
- reworded dt-bindings property description
- fixed the rmi_driver_of_probe definition for non device-tree builds.
- fixed some indentation issues reported by checkpatch
- change rmi_pdt_entry_is_valid() variable to unsigned 
- Link to v2: https://lore.kernel.org/all/20230929-caleb-rmi4-quirks-v2-0-b227ac498d88@linaro.org

Changes in v2:
- Improve dt-bindings patch (thanks Rob)
- Add missing cast in patch 5 to fix the pointer arithmetic
- Link to v1: https://lore.kernel.org/r/20230929-caleb-rmi4-quirks-v1-0-cc3c703f022d@linaro.org

---
Casey Connolly (1):
      Input: synaptics-rmi4 - handle duplicate/unknown PDT entries

David Heidelberg (1):
      dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b

Kaustabh Chakraborty (5):
      Input: synaptics-rmi4 - f12: use hardcoded values for aftermarket touch ICs
      Input: synaptics-rmi4 - f55: handle zero electrode count
      Input: synaptics-rmi4 - don't do unaligned reads in IRQ context
      Input: synaptics-rmi4 - read product ID on aftermarket touch ICs
      Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes

 .../devicetree/bindings/input/syna,rmi4.yaml       |  11 +-
 drivers/input/rmi4/rmi_driver.c                    | 124 +++++++++++++++++----
 drivers/input/rmi4/rmi_driver.h                    |  10 ++
 drivers/input/rmi4/rmi_f01.c                       |  14 +++
 drivers/input/rmi4/rmi_f12.c                       | 117 ++++++++++++++-----
 drivers/input/rmi4/rmi_f55.c                       |   5 +
 include/linux/rmi.h                                |   3 +
 7 files changed, 234 insertions(+), 50 deletions(-)
---
base-commit: 85964cdcad0fac9a0eb7b87a0f9d88cc074b854c
change-id: 20250308-synaptics-rmi4-c832b2f73ceb

Best regards,
-- 
David Heidelberg <david@ixit.cz>



^ permalink raw reply

* [PATCH] HID: hid-lenovo-go: fix LEDS dependencies
From: Arnd Bergmann @ 2026-03-24 19:20 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Derek J. Clark, Mark Pearson,
	Mario Limonciello, Ethan Tidmore
  Cc: Arnd Bergmann, Aditya Garg, Jonathan Denose, Geert Uytterhoeven,
	linux-input, linux-kernel

From: Arnd Bergmann <arnd@arndb.de>

The newly added hid-lenovo-go and hid-lenovo-go-s drivers attempt to
'select LEDS_CLASS', which has a dependency on NEW_LEDS, causing a build
failure when NEW_LEDS itself it disabled:

WARNING: unmet direct dependencies detected for LEDS_CLASS
  Depends on [n]: NEW_LEDS [=n]
  Selected by [m]:
  - HID_LENOVO_GO [=m] && HID_SUPPORT [=y] && HID [=m] && USB_HID [=m]
  - HID_LENOVO_GO_S [=m] && HID_SUPPORT [=y] && HID [=m] && USB_HID [=m]

WARNING: unmet direct dependencies detected for LEDS_CLASS_MULTICOLOR
  Depends on [n]: NEW_LEDS [=n] && LEDS_CLASS [=m]
  Selected by [m]:
  - HID_LENOVO_GO [=m] && HID_SUPPORT [=y] && HID [=m] && USB_HID [=m]
  - HID_LENOVO_GO_S [=m] && HID_SUPPORT [=y] && HID [=m] && USB_HID [=m]
ERROR: modpost: "led_set_brightness_nopm" [drivers/leds/led-class.ko] undefined!
ERROR: modpost: "led_set_brightness" [drivers/leds/led-class.ko] undefined!
ERROR: modpost: "led_get_color_name" [drivers/leds/led-class-multicolor.ko] undefined!
ERROR: modpost: "led_set_brightness" [drivers/leds/led-class-multicolor.ko] undefined!

Device drivers generally should not select other subsystems like this, as
that tends to cause dependency problems including loops in the dependency
graph.

Change these two and the older hid-lenovo driver to behave the same way as all
other HID drivers and use 'depends on LEDS_CLASS' or 'depends on LEDS_CLASS_MULTICOLOR'
instead, which itself has NEW_LEDS and LEDS_CLASS as dependencies.

Fixes: a23f3497bf20 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver")
Fixes: d69ccfcbc955 ("HID: hid-lenovo-go: Add Lenovo Legion Go Series HID Driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/hid/Kconfig | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 10c12d8e6557..f658ed0168ea 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -610,8 +610,7 @@ config HID_LED
 
 config HID_LENOVO
 	tristate "Lenovo / Thinkpad devices"
-	select NEW_LEDS
-	select LEDS_CLASS
+	depends on LEDS_CLASS
 	help
 	Support for IBM/Lenovo devices that are not fully compliant with HID standard.
 
@@ -626,8 +625,7 @@ config HID_LENOVO
 config HID_LENOVO_GO
 	tristate "HID Driver for Lenovo Legion Go Series Controllers"
 	depends on USB_HID
-	select LEDS_CLASS
-	select LEDS_CLASS_MULTICOLOR
+	depends on LEDS_CLASS_MULTICOLOR
 	help
 	Support for Lenovo Legion Go devices with detachable controllers.
 
@@ -638,8 +636,7 @@ config HID_LENOVO_GO
 config HID_LENOVO_GO_S
 	tristate "HID Driver for Lenovo Legion Go S Controller"
 	depends on USB_HID
-	select LEDS_CLASS
-	select LEDS_CLASS_MULTICOLOR
+	depends on LEDS_CLASS_MULTICOLOR
 	help
 	Support for Lenovo Legion Go S Handheld Console Controller.
 
-- 
2.39.5


^ permalink raw reply related

* [PATCH] HID: ft260: validate report size in raw_event handler
From: Sebastian Josue Alba Vives @ 2026-03-24 17:35 UTC (permalink / raw)
  To: michael.zaidman, jikos, bentiss
  Cc: linux-i2c, linux-input, linux-kernel, stable,
	Sebastian Josue Alba Vives

ft260_raw_event() casts the raw data buffer to a
ft260_i2c_input_report struct and accesses its fields without
validating the size parameter. Since __hid_input_report() invokes
the driver's raw_event callback before hid_report_raw_event()
performs its own report-size validation, a device sending a
truncated HID report can cause out-of-bounds heap reads in the
kernel.

In the I2C response path, xfer->length (data[1]) is used as the
length for a memcpy into dev->read_buf. While xfer->length is
checked against dev->read_len, there is no check that size is large
enough to actually contain xfer->length bytes of data starting at
offset 2. A malicious USB device could therefore cause an OOB read
from the kernel heap, with the result accessible from userspace via
the I2C read interface.

FT260 devices use 64-byte HID reports. Add a check at the top of
the handler to reject any report shorter than expected, and log a
warning to aid debugging.

Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
---
 drivers/hid/hid-ft260.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
index 333341e80..7ca323992 100644
--- a/drivers/hid/hid-ft260.c
+++ b/drivers/hid/hid-ft260.c
@@ -1068,6 +1068,12 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
 	struct ft260_device *dev = hid_get_drvdata(hdev);
 	struct ft260_i2c_input_report *xfer = (void *)data;
 
+	/* FT260 always sends 64-byte reports */
+	if (size < 64) {
+		hid_warn(hdev, "report too short: %d < 64\n", size);
+		return 0;
+	}
+
 	if (xfer->report >= FT260_I2C_REPORT_MIN &&
 	    xfer->report <= FT260_I2C_REPORT_MAX) {
 		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2] HID: mcp2221: validate report size in raw_event handler
From: Sebastian Josue Alba Vives @ 2026-03-24 17:06 UTC (permalink / raw)
  To: gupt21, jikos, bentiss
  Cc: linux-i2c, linux-input, linux-kernel, stable,
	Sebastian Josue Alba Vives
In-Reply-To: <20260324062403.341855-1-sebasjosue84@gmail.com>

mcp2221_raw_event() accesses the data buffer at offsets up to 55
without validating the size parameter. Since __hid_input_report()
invokes the driver's raw_event callback before
hid_report_raw_event() performs its own report-size validation, a
device sending a truncated HID report can cause out-of-bounds heap
reads in the kernel.

The most critical access is the memcpy from data[50] into
mcp->adc_values (6 bytes) when CONFIG_IIO is reachable. Other
unchecked accesses include data[20] and a memcpy at data[22].
Additionally, a memcpy with device-controlled length (data[3],
up to 60 bytes) from data[4] does not verify that size is large
enough to cover the copy.

MCP2221 devices use 64-byte HID reports. Add a check at the top of
the handler to reject any report shorter than expected, and log a
warning to aid debugging.

Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Josue Alba Vives <sebasjosue84@gmail.com>
---
 drivers/hid/hid-mcp2221.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index ef3b5c77c..770c305d8 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -850,6 +850,11 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 {
 	u8 *buf;
 	struct mcp2221 *mcp = hid_get_drvdata(hdev);
+	/* MCP2221 always sends 64-byte reports */
+	if (size < 64) {
+		hid_warn(hdev, "report too short: %d < 64\n", size);
+		return 0;
+	}
 
 	switch (data[0]) {
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 2/2] HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write
From: Lee Jones @ 2026-03-24 14:36 UTC (permalink / raw)
  To: lee, Filipe Laíns, Jiri Kosina, Benjamin Tissoires,
	linux-input, linux-kernel
In-Reply-To: <20260324143651.342273-1-lee@kernel.org>

logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT
reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long.  It uses that
assumption to load the associated field's 'value' array with 14 Bytes of
data.  However, if a malicious user only sends say 1 Byte of data,
'report_count' will be 1 and only 1 Byte of memory will be allocated to
the 'value' Byte array.  When we come to populate 'value[1-13]' we will
experience an OOB write.

Signed-off-by: Lee Jones <lee@kernel.org>
---
v1 => v2: Move handling to .probe()

 drivers/hid/hid-logitech-dj.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 32139b2561c0..a8082199d13d 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1859,6 +1859,7 @@ static int logi_dj_probe(struct hid_device *hdev,
 			 const struct hid_device_id *id)
 {
 	struct hid_report_enum *input_report_enum;
+	struct hid_report_enum *output_report_enum;
 	struct hid_report *rep;
 	struct dj_receiver_dev *djrcv_dev;
 	struct usb_interface *intf;
@@ -1903,6 +1904,15 @@ static int logi_dj_probe(struct hid_device *hdev,
 		}
 	}
 
+	output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+	rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+
+	if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) {
+		hid_err(hdev, "Expected size of DJ short report is %d, but got %d",
+			DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count);
+		return -EINVAL;
+	}
+
 	input_report_enum = &hdev->report_enum[HID_INPUT_REPORT];
 
 	/* no input reports, bail out */
-- 
2.53.0.983.g0bb29b3bc5-goog


^ permalink raw reply related

* [PATCH v2 1/2] HID: logitech-dj: Standardise hid_report_enum variable nomenclature
From: Lee Jones @ 2026-03-24 14:36 UTC (permalink / raw)
  To: lee, Filipe Laíns, Jiri Kosina, Benjamin Tissoires,
	linux-input, linux-kernel

Since we will need to differentiate between the two report_enum types
soon, let's unify the naming conventions now to save confusion and/or
unnecessary/unrelated changes in upcoming commits.

{input,output}_report_enum is used in other places to let's conform.

Signed-off-by: Lee Jones <lee@kernel.org>
---
v1 => v2: New patch

 drivers/hid/hid-logitech-dj.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 44b716697510..32139b2561c0 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1858,7 +1858,7 @@ static int logi_dj_raw_event(struct hid_device *hdev,
 static int logi_dj_probe(struct hid_device *hdev,
 			 const struct hid_device_id *id)
 {
-	struct hid_report_enum *rep_enum;
+	struct hid_report_enum *input_report_enum;
 	struct hid_report *rep;
 	struct dj_receiver_dev *djrcv_dev;
 	struct usb_interface *intf;
@@ -1903,10 +1903,10 @@ static int logi_dj_probe(struct hid_device *hdev,
 		}
 	}
 
-	rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+	input_report_enum = &hdev->report_enum[HID_INPUT_REPORT];
 
 	/* no input reports, bail out */
-	if (list_empty(&rep_enum->report_list))
+	if (list_empty(&input_report_enum->report_list))
 		return -ENODEV;
 
 	/*
@@ -1914,7 +1914,7 @@ static int logi_dj_probe(struct hid_device *hdev,
 	 * Note: we should theoretically check for HID++ and DJ
 	 * collections, but this will do.
 	 */
-	list_for_each_entry(rep, &rep_enum->report_list, list) {
+	list_for_each_entry(rep, &input_report_enum->report_list, list) {
 		if (rep->application == 0xff000001)
 			has_hidpp = true;
 	}
@@ -1927,7 +1927,7 @@ static int logi_dj_probe(struct hid_device *hdev,
 		return -ENODEV;
 
 	/* get the current application attached to the node */
-	rep = list_first_entry(&rep_enum->report_list, struct hid_report, list);
+	rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list);
 	djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data,
 					rep->application, has_hidpp);
 	if (!djrcv_dev) {
@@ -1935,7 +1935,7 @@ static int logi_dj_probe(struct hid_device *hdev,
 		return -ENOMEM;
 	}
 
-	if (!rep_enum->numbered)
+	if (!input_report_enum->numbered)
 		djrcv_dev->unnumbered_application = rep->application;
 
 	/* Starts the usb device and connects to upper interfaces hiddev and
-- 
2.53.0.983.g0bb29b3bc5-goog


^ permalink raw reply related

* Re: [PATCH v2 00/19] tracepoint: Avoid double static_branch evaluation at guarded call sites
From: Steven Rostedt @ 2026-03-24 14:28 UTC (permalink / raw)
  To: Vineeth Pillai (Google)
  Cc: Peter Zijlstra, Dmitry Ilvokhin, Masami Hiramatsu,
	Mathieu Desnoyers, Ingo Molnar, Jens Axboe, io-uring,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Alexei Starovoitov, Daniel Borkmann, Marcelo Ricardo Leitner,
	Xin Long, Jon Maloy, Aaron Conole, Eelco Chaudron, Ilya Maximets,
	netdev, bpf, linux-sctp, tipc-discussion, dev, Jiri Pirko,
	Oded Gabbay, Koby Elbaz, dri-devel, Rafael J. Wysocki,
	Viresh Kumar, Gautham R. Shenoy, Huang Rui, Mario Limonciello,
	Len Brown, Srinivas Pandruvada, linux-pm, MyungJoo Ham,
	Kyungmin Park, Chanwoo Choi, Christian König, Sumit Semwal,
	linaro-mm-sig, Eddie James, Andrew Jeffery, Joel Stanley,
	linux-fsi, David Airlie, Simona Vetter, Alex Deucher,
	Danilo Krummrich, Matthew Brost, Philipp Stanner, Harry Wentland,
	Leo Li, amd-gfx, Jiri Kosina, Benjamin Tissoires, linux-input,
	Wolfram Sang, linux-i2c, Mark Brown, Michael Hennerich,
	Nuno Sá, linux-spi, James E.J. Bottomley, Martin K. Petersen,
	linux-scsi, Chris Mason, David Sterba, linux-btrfs,
	Thomas Gleixner, Andrew Morton, SeongJae Park, linux-mm,
	Borislav Petkov, Dave Hansen, x86, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20260323160052.17528-1-vineeth@bitbyteword.org>

On Mon, 23 Mar 2026 12:00:19 -0400
"Vineeth Pillai (Google)" <vineeth@bitbyteword.org> wrote:

> When a caller already guards a tracepoint with an explicit enabled check:
> 
>   if (trace_foo_enabled() && cond)
>       trace_foo(args);

Thanks Vineeth!

I'm going to start pulling in this series. I'll take the first patch, and
then any patch that has an Acked-by or Reviewed-by from the maintainer.

For patches without acks, I'll leave alone and then after the first patch
gets merged into mainline, the maintainers could pull in their own patches
at their own convenience. Unless of course they speak up now if they want
me to take them ;-)

-- Steve

^ permalink raw reply

* [PATCH] hid: usbhid: fix deadlock in hid_post_reset()
From: Oliver Neukum @ 2026-03-24 14:24 UTC (permalink / raw)
  To: bentiss, jikos, linux-input, linux-usb; +Cc: Oliver Neukum

You can build a USB device that includes a HID component
and a storage or UAS component. The components can be reset
only together. That means that hid_pre_reset() and hid_post_reset()
are in the block IO error handling. Hence no memory allocation
used in them may do block IO because the IO can deadlock
on the mutex held while resetting a device and calling the
interface drivers.
Use GFP_NOIO for all allocations in them.

Fixes: dc3c78e434690 ("HID: usbhid: Check HID report descriptor contents after device reset")
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/hid/usbhid/hid-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index ddd5d77fb5a5..fd3e1aedc5cb 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1552,7 +1552,7 @@ static int hid_post_reset(struct usb_interface *intf)
 	 * configuration descriptors passed, we already know that
 	 * the size of the HID report descriptor has not changed.
 	 */
-	rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL);
+	rdesc = kmalloc(hid->dev_rsize, GFP_NOIO);
 	if (!rdesc)
 		return -ENOMEM;
 
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH 2/3] Input: adafruit-seesaw - add interrupt support
From: Charles Dias @ 2026-03-24 13:59 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Anshul Dalal, Shuah Khan, Brigham Campbell, linux-input,
	linux-kernel, Charles Dias
In-Reply-To: <acDLSiujizhuYfOt@google.com>

On Mon, Mar 23, 2026 at 2:12 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> Hi Charles,
>
> On Sat, Mar 21, 2026 at 05:24:45PM -0300, charles.embedded@gmail.com wrote:
> > @@ -289,6 +341,19 @@ static int seesaw_probe(struct i2c_client *client)
> >       input_set_max_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MAX);
> >       input_set_min_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MIN);
> >
> > +     if (client->irq) {
> > +             err = seesaw_register_write_u32(client, SEESAW_GPIO_INTENSET, SEESAW_BUTTON_MASK);
> > +             if (err)
> > +                     return dev_err_probe(&client->dev, err,
> > +                                             "failed to enable hardware interrupts\n");
>
> Maybe this should be in seesaw_open()?
>
> Thanks.
>
> --
> Dmitry

Hi Dmitry. Thank you for your review!

Since this is a one-time setup, I believe it should remain as is
within the seesaw_probe() function, similar to other pin
configurations.

Please let me know if I'm missing any point here.

Best regards,
Charles Dias

^ permalink raw reply

* Re: [PATCH v2] Input: penmount: bound packet buffer indices in IRQ path
From: Andy Shevchenko @ 2026-03-24 13:47 UTC (permalink / raw)
  To: Pengpeng Hou; +Cc: dmitry.torokhov, kees, linux-input, linux-kernel
In-Reply-To: <20260324131442.27632-1-pengpeng@iscas.ac.cn>

On Tue, Mar 24, 2026 at 09:14:42PM +0800, Pengpeng Hou wrote:
> pm_interrupt() stores each incoming byte into pm->data[] before the
> packet parser gets a chance to reset pm->idx. If the incoming serial
> stream never matches one of the expected packet headers, pm->idx can
> advance past the fixed receive buffer and the next IRQ will write beyond
> PM_MAX_LENGTH.
> 
> Reset stale indices before storing the next byte. Once pm->idx has
> already moved past the valid packet buffer state, the current partial
> packet can no longer be trusted, so the smallest local recovery is to
> drop that stale state and resynchronize from the current byte instead of
> carrying the invalid index into the next interrupt.
> 
> Found by static code analysis.

Missed blank line here. No need to resend until maintainers ask explicitly for
that.

...

The explanation sounds sane, but I'm not familiar enough with how this device
works. In case others consider this good, feel free to add

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: Question regarding error handling in usbhid
From: Alan Stern @ 2026-03-24 13:40 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: USB list, linux-input@vger.kernel.org
In-Reply-To: <8d665258-6dd6-404a-85e0-a2f3420cd992@suse.com>

On Tue, Mar 24, 2026 at 10:57:16AM +0100, Oliver Neukum wrote:
> Hi,
> 
> hid_io_error(), in case it decides that a reset is necessary,
> schedules reset_work(). reset_work() in turn calls usb_queue_reset_device().
> Why? Is there a reason usb_queue_reset_device() is not used directly
> in hid_io_error()?

This is partly explained in the changelog for commit 8f507ef522d5 ("HID: 
usbhid: improve handling of Clear-Halt and reset"):

    The way resets are carried out is also changed.  Now the driver will
    call usb_queue_reset_device() instead of calling usb_reset_device()
    directly.  This avoids a deadlock that would arise when a device is
    unplugged: The hid_reset() routine runs as a workqueue item, a reset
    attempt after the device has been unplugged will fail, failure will
    cause usbhid to be unbound, and the disconnect routine will try to do
    cancel_work_sync().  The usb_queue_reset_device() implementation is
    carefully written to handle scenarios like this one properly.

The other part of the explanation is that the reset code was added to 
hid_io_error() before usb_queue_reset_device() existed (2006 vs 2008).

Alan Stern

^ permalink raw reply

* [PATCH v2] Input: penmount: bound packet buffer indices in IRQ path
From: Pengpeng Hou @ 2026-03-24 13:14 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: andriy.shevchenko, kees, linux-input, linux-kernel, pengpeng
In-Reply-To: <20260323121715.74954-1-pengpeng@iscas.ac.cn>

pm_interrupt() stores each incoming byte into pm->data[] before the
packet parser gets a chance to reset pm->idx. If the incoming serial
stream never matches one of the expected packet headers, pm->idx can
advance past the fixed receive buffer and the next IRQ will write beyond
PM_MAX_LENGTH.

Reset stale indices before storing the next byte. Once pm->idx has
already moved past the valid packet buffer state, the current partial
packet can no longer be trusted, so the smallest local recovery is to
drop that stale state and resynchronize from the current byte instead of
carrying the invalid index into the next interrupt.

Found by static code analysis.
Fixes: 98b013eb7a94 ("Input: penmount - rework handling of different protocols")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v2:
- note that the issue was found by static code analysis
- explain why resetting the stale index is the preferred resynchronization path
- add a Fixes tag

 drivers/input/touchscreen/penmount.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 4b57b6664e37..ba09096c6573 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -163,6 +163,9 @@ static irqreturn_t pm_interrupt(struct serio *serio,
 {
 	struct pm *pm = serio_get_drvdata(serio);
 
+	if (pm->idx >= pm->packetsize || pm->idx >= PM_MAX_LENGTH)
+		pm->idx = 0;
+
 	pm->data[pm->idx] = data;
 
 	pm->parse_packet(pm);
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* Re: [PATCH] Input: penmount: bound packet buffer indices in IRQ path
From: Andy Shevchenko @ 2026-03-24 12:11 UTC (permalink / raw)
  To: Pengpeng Hou; +Cc: andy, hansg, mchehab, gregkh, linux-kernel, linux-input
In-Reply-To: <20260324022950.456-1-pengpeng@iscas.ac.cn>

On Tue, Mar 24, 2026 at 10:29:50AM +0800, Pengpeng Hou wrote:
> 
> This was found during static code analysis of the packet receive path.
> 
> About the fix: my reasoning was that once pm->idx has already moved past
> the valid packet buffer state, the current partial packet is no longer
> usable, so the safest local recovery is to drop that stale state and
> resynchronize from the current byte. That is why I reset the index before
> storing the next byte.
> 
> I did not choose to ignore the IRQ entirely because the interrupt has
> already delivered a byte, and simply returning without resetting the stale
> state would leave the parser in the same invalid condition for the next
> interrupt. Resetting the index seemed like the smallest change that both
> prevents the out-of-bounds write and lets the parser recover cleanly.

Good, (summary of) this should be in the commit message in the first place.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* [PATCH AUTOSEL 6.19-5.10] HID: multitouch: Check to ensure report responses match the request
From: Sasha Levin @ 2026-03-24 11:19 UTC (permalink / raw)
  To: patches, stable
  Cc: Lee Jones, Benjamin Tissoires, Sasha Levin, jikos, linux-input,
	linux-kernel
In-Reply-To: <20260324111931.3257972-1-sashal@kernel.org>

From: Lee Jones <lee@kernel.org>

[ Upstream commit e716edafedad4952fe3a4a273d2e039a84e8681a ]

It is possible for a malicious (or clumsy) device to respond to a
specific report's feature request using a completely different report
ID.  This can cause confusion in the HID core resulting in nasty
side-effects such as OOB writes.

Add a check to ensure that the report ID in the response, matches the
one that was requested.  If it doesn't, omit reporting the raw event and
return early.

Signed-off-by: Lee Jones <lee@kernel.org>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

As Tissoires noted, `hid-vivaldi-common.c` has the same vulnerable
pattern. `wacom_sys.c` also has it. This confirms the bug is systemic.

Record: Same vulnerable pattern exists in hid-vivaldi-common.c and
wacom_sys.c. This is a known systemic issue.

## PHASE 6: CROSS-REFERENCING AND STABLE TREE ANALYSIS

### Step 6.1: DOES THE BUGGY CODE EXIST IN STABLE TREES?

The buggy code was introduced in commit `6d4f5440a3a2bb` from
2015-10-07, which is approximately kernel v4.4. This means the
vulnerable code exists in **ALL active stable trees** (5.4.y, 5.10.y,
5.15.y, 6.1.y, 6.6.y, 6.12.y, etc.).

Record: Buggy code exists in all active stable trees. Very wide
exposure.

### Step 6.2: CHECK FOR BACKPORT COMPLICATIONS

The fix is 7 lines added to a single function. The function has been
stable since 2015 with only minor modifications (2018 `ret` variable and
`hid_report_len` changes). The patch should apply cleanly to all stable
trees or with trivial context adjustments.

Record: Expected backport difficulty: clean apply or trivial conflicts.

### Step 6.3: CHECK IF RELATED FIXES ARE ALREADY IN STABLE
No related fixes for this specific issue found in any stable tree.

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

### Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
- **Subsystem**: HID (Human Interface Devices) — drivers/hid/
- **Criticality**: IMPORTANT — HID affects all USB input devices (mice,
  keyboards, touchscreens, touchpads). Multitouch is used by virtually
  all modern laptops and tablets.
- **Security aspect**: USB devices are a common physical attack vector.
  A malicious USB device can be plugged into any machine.

Record: [HID/multitouch] [IMPORTANT - affects all multitouch devices,
USB attack vector]

### Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Active subsystem with regular commits. The HID maintainer (Benjamin
Tissoires) actively reviews and merges patches.

Record: Active subsystem, responsive maintainer.

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: DETERMINE WHO IS AFFECTED
Any system using HID multitouch devices (virtually all laptops, tablets,
kiosks, and touchscreen-equipped systems). The vulnerability is
triggerable via a malicious USB device.

Record: Affected user population: universal (any system with USB ports
and HID multitouch support).

### Step 8.2: DETERMINE THE TRIGGER CONDITIONS
- **Trigger**: A USB device sends a HID feature report response with a
  report ID different from the one requested
- **Attack scenario**: Malicious USB device (BadUSB-style attack) — plug
  in a crafted USB device
- **Also possible**: Buggy/clumsy device firmware (accidental trigger)
- **Privilege**: Physical access to USB port required (no unprivileged
  userspace trigger)
- **Reproducibility**: Deterministic — controlled by the device firmware

Record: Physical access via USB required. Deterministic trigger from
device side. No unprivileged software trigger.

### Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
- **Failure mode**: Out-of-bounds memory write in kernel space
- **Consequences**: Memory corruption, potential kernel crash, potential
  privilege escalation
- **Severity**: **CRITICAL** — OOB write is one of the most serious
  vulnerability classes

Record: [OOB write / memory corruption] [Severity: CRITICAL]

### Step 8.4: CALCULATE RISK-BENEFIT RATIO
- **BENEFIT**: Very high — prevents OOB kernel memory corruption from
  malicious USB devices
- **RISK**: Very low — 7 lines, simple ID comparison check, only affects
  feature report processing in multitouch driver
- **Ratio**: Excellent — high benefit, minimal risk

Record: [Benefit: VERY HIGH] [Risk: VERY LOW] [Ratio: strongly favors
backporting]

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: COMPILE THE EVIDENCE

**FOR backporting:**
- Fixes OOB write (CRITICAL severity security vulnerability)
- Exploitable via malicious USB device (physical attack vector)
- Fix is 7 lines, obviously correct (simple ID comparison)
- Accepted by HID maintainer Benjamin Tissoires
- Buggy code exists in ALL stable trees (since 2015, kernel v4.4)
- No dependencies on other patches (standalone fix)
- Clean backport expected
- Verified the OOB mechanism in `hid_report_raw_event()` — the `memset`
  at line 2062 can write beyond buffer bounds

**AGAINST backporting:**
- Part of a 2-patch series, but patch 1/2 is independent (different
  file, different issue)
- No explicit Cc: stable from author or reviewer (expected, that's why
  we're reviewing)
- Requires physical USB access (not remotely exploitable)

**UNRESOLVED:**
- None significant — the bug mechanism is clearly verified

### Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. **Obviously correct and tested?** YES — simple comparison of
   report->id vs buf[0], reviewed and accepted by HID maintainer
2. **Fixes a real bug that affects users?** YES — OOB write from
   malicious/buggy USB devices
3. **Important issue?** YES — memory corruption / security vulnerability
   (CRITICAL)
4. **Small and contained?** YES — 7 lines in one function in one file
5. **No new features or APIs?** YES — purely validation logic
6. **Can apply to stable trees?** YES — code has been stable since 2015

### Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Not an exception category — this is a standard security bug fix, which
is the primary use case for stable.

### Step 9.4: MAKE YOUR DECISION
This is a clear YES. It's a small, obviously correct security fix that
prevents OOB writes from malicious USB devices. The fix has been
reviewed and accepted by the HID maintainer. It affects all stable trees
and has minimal regression risk.

## Verification

- [Phase 1] Parsed tags: Signed-off-by Lee Jones (author), Signed-off-by
  Benjamin Tissoires (HID maintainer). No Fixes/Reported-by/Cc:stable
  tags.
- [Phase 2] Diff analysis: 7 lines added to `mt_get_feature()` in hid-
  multitouch.c, adds report ID validation check before calling
  `hid_report_raw_event()`
- [Phase 3] git blame: Buggy code introduced in commit `6d4f5440a3a2bb`
  (2015-10-07, ~v4.4), present in ALL active stable trees
- [Phase 3] git log: No previous related fixes for this issue found
- [Phase 4] lore.kernel.org: Found patch submission at
  `20260227163031.1166560-2-lee@kernel.org`. Patch 2/2 of series; patch
  1/2 is independent (different file). Benjamin Tissoires reviewed and
  accepted. He noted same bug exists in hid-vivaldi-common.c.
- [Phase 4] RFC v3: Tissoires NACK'd core-level fix, preferred per-
  driver fixes like this one — confirming this is the maintainer's
  preferred approach.
- [Phase 5] Callers: `mt_get_feature()` called from
  `mt_feature_mapping()` at 3 sites during device enumeration — standard
  path for multitouch devices
- [Phase 5] Verified OOB mechanism: `hid_report_raw_event()` at hid-
  core.c:2040 uses `data[0]` (buf[0]) to look up report; at line 2062,
  `memset(cdata + csize, 0, rsize - csize)` writes beyond buffer if
  looked-up report is larger than the buffer allocated for the requested
  report
- [Phase 5] Same vulnerable pattern confirmed in hid-vivaldi-common.c:87
  and wacom_sys.c:397
- [Phase 6] Code exists in all active stable trees (v4.4+), fix should
  apply cleanly
- [Phase 7] HID subsystem: IMPORTANT criticality, affects all multitouch
  USB devices
- [Phase 8] Failure mode: OOB kernel memory write, severity CRITICAL.
  Trigger: malicious USB device (physical access required).

**YES**

 drivers/hid/hid-multitouch.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index b8a748bbf0fd8..e82a3c4e5b44e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -526,12 +526,19 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
 		dev_warn(&hdev->dev, "failed to fetch feature %d\n",
 			 report->id);
 	} else {
+		/* The report ID in the request and the response should match */
+		if (report->id != buf[0]) {
+			hid_err(hdev, "Returned feature report did not match the request\n");
+			goto free;
+		}
+
 		ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
 					   size, 0);
 		if (ret)
 			dev_warn(&hdev->dev, "failed to report feature\n");
 	}
 
+free:
 	kfree(buf);
 }
 
-- 
2.51.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.19-6.18] HID: core: Mitigate potential OOB by removing bogus memset()
From: Sasha Levin @ 2026-03-24 11:19 UTC (permalink / raw)
  To: patches, stable
  Cc: Lee Jones, Benjamin Tissoires, Sasha Levin, jikos, linux-input,
	linux-kernel
In-Reply-To: <20260324111931.3257972-1-sashal@kernel.org>

From: Lee Jones <lee@kernel.org>

[ Upstream commit 0a3fe972a7cb1404f693d6f1711f32bc1d244b1c ]

The memset() in hid_report_raw_event() has the good intention of
clearing out bogus data by zeroing the area from the end of the incoming
data string to the assumed end of the buffer.  However, as we have
previously seen, doing so can easily result in OOB reads and writes in
the subsequent thread of execution.

The current suggestion from one of the HID maintainers is to remove the
memset() and simply return if the incoming event buffer size is not
large enough to fill the associated report.

Suggested-by Benjamin Tissoires <bentiss@kernel.org>

Signed-off-by: Lee Jones <lee@kernel.org>
[bentiss: changed the return value]
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed to complete the analysis. Let me
compile the full assessment.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: Subject Line**
- Subsystem: `HID: core:`
- Action verb: "Mitigate" (fix-oriented)
- Summary: Removes a memset() that causes OOB reads/writes when incoming
  HID event data is shorter than expected report size.
- Record: [HID core] [Mitigate/fix] [Remove memset that causes OOB
  memory corruption]

**Step 1.2: Tags**
- `Suggested-by: Benjamin Tissoires <bentiss@kernel.org>` — HID co-
  maintainer suggested the approach
- `Signed-off-by: Lee Jones <lee@kernel.org>` — author
- `[bentiss: changed the return value]` — maintainer modified the return
  value
- `Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>` — applied by
  HID maintainer
- No Fixes: tag (expected for candidates)
- No Cc: stable (expected)
- No Reported-by tag
- Record: Suggested and accepted by the HID co-maintainer. Strong
  endorsement.

**Step 1.3: Commit Body**
- Bug: The `memset()` in `hid_report_raw_event()` zeros from `cdata +
  csize` to `cdata + rsize` when `csize < rsize`. However, the actual
  buffer may not be `rsize` bytes — it could be smaller, causing OOB
  writes.
- "as we have previously seen" — acknowledges a history of OOB issues
  from this code.
- The fix: reject short reports entirely with -EINVAL instead of zero-
  padding.
- Record: OOB writes from memset writing past actual buffer boundary.
  Longstanding known issue class.

**Step 1.4: Hidden Bug Fix Detection**
- Not hidden — explicitly describes an OOB vulnerability fix. The word
  "mitigate" and "OOB" make it clear.

## PHASE 2: DIFF ANALYSIS

**Step 2.1: Inventory**
- Files: `drivers/hid/hid-core.c` (+4/-3 lines)
- Function: `hid_report_raw_event()`
- Scope: Single-file, single-function surgical fix
- Record: [1 file, net +1 line] [hid_report_raw_event()] [Single-file
  surgical fix]

**Step 2.2: Code Flow Change**
- BEFORE: When `csize < rsize`, the code logs a debug message and calls
  `memset(cdata + csize, 0, rsize - csize)` to zero-pad the buffer, then
  continues processing.
- AFTER: When `csize < rsize`, the code logs a rate-limited warning and
  returns `-EINVAL` via `goto out`, rejecting the short report entirely.
- Record: [Short report path: zero-pad and continue → reject and return
  -EINVAL]

**Step 2.3: Bug Mechanism**
- Category: **Buffer overflow / OOB write** (memory safety)
- Mechanism: `memset(cdata + csize, 0, rsize - csize)` writes zeros from
  the end of the actual received data to position `rsize`. But the
  underlying buffer (allocated by the transport layer) may only be
  `csize` bytes, meaning the memset writes past the buffer boundary.
- Additionally, subsequent code (like `hid_process_report`) reads up to
  `rsize` bytes from the buffer, causing OOB reads.
- Record: [OOB write from memset] [Buffer may be smaller than rsize,
  memset writes past end]

**Step 2.4: Fix Quality**
- Obviously correct: rejecting a too-short report is safer than
  attempting to zero-pad a buffer of unknown size.
- Minimal: 4 lines changed, net +1 line.
- Regression risk: Some devices that send short reports and relied on
  zero-padding will now have those reports rejected. Tissoires
  acknowledged this ("let's go with it and say sorry if we break some
  devices later on"), meaning the maintainer accepted this tradeoff.
- Record: [High quality, minimal fix] [Low regression risk, maintainer-
  accepted tradeoff]

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: Blame**
- The buggy memset line traces to `85cdaf524b7dda` ("HID: make a bus
  from hid code") from 2008-05-16.
- This code has been present since Linux 2.6.26 — it exists in ALL
  active stable trees.
- Record: [Buggy code from 2008, present in all stable trees]

**Step 3.2: Fixes Tag**
- No Fixes: tag present. However, the memset dates to 85cdaf524b7dda
  (2008).

**Step 3.3: File History — Related Changes**
- 966922f26c7fb (2011): Fixed crash from rsize being too large
  (536870912) causing memset crash
- 5ebdffd250988 (2020): Fixed off-by-one in rsize calculation causing
  OOB memset
- b1a37ed00d790 (2023): Added `max_buffer_size` attribute to cap rsize
- ec61b41918587 (2022): Fixed shift-out-of-bounds in the processing
  after the memset
- Record: **Long history of OOB/crash bugs from this exact memset**.
  This is the definitive fix.

**Step 3.4: Author**
- Lee Jones is a prolific kernel contributor and has previously worked
  on HID buffer size hardening (b1a37ed00d790).
- Fix was suggested by and applied by Benjamin Tissoires, HID co-
  maintainer.
- Record: [Experienced author, maintainer-endorsed fix]

**Step 3.5: Dependencies**
- The fix uses `hid_warn_ratelimited`, introduced in commit
  1d64624243af8, which only entered v6.18.
- For stable trees < 6.18, this would need trivial adaptation (use
  `hid_warn` or `dev_warn_ratelimited` instead).
- The companion patch `e716edafedad4` (hid-multitouch report ID check)
  is independent — it adds a defense at the caller level, not a
  prerequisite.
- Record: [Minor dependency on hid_warn_ratelimited macro for older
  trees, trivially resolvable]

## PHASE 4: MAILING LIST RESEARCH

From the lore.kernel.org investigation:
- **v1 (2026-02-27)**: Initial version simply removed the memset
  entirely.
- **Tissoires review (2026-03-02)**: Pushed back — removing memset alone
  isn't enough because `hid_process_report()` would still read OOB.
  Suggested rejecting short reports entirely.
- **v3 (2026-03-09)**: Revised per Tissoires's feedback — now returns
  early with warning.
- **Tissoires final review (2026-03-16)**: Endorsed, changed return to
  -EINVAL, noted "works in 99% of cases" since transport layers allocate
  big enough buffers.
- Applied 2026-03-16, merged to Linus 2026-03-17.
- No explicit stable nomination, but no objections to backporting
  either.
- Record: [Thorough review by HID maintainer, iterated to correct
  approach, accepted]

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: Functions Modified**
- `hid_report_raw_event()` — the core HID report processing function.

**Step 5.2: Callers**
- `__hid_input_report()` in hid-core.c (line 2144) — **THE main HID
  input path** for all HID devices
- `wacom_sys.c` — 3 call sites (Wacom tablet driver)
- `hid-gfrm.c` — Google Fiber Remote
- `hid-logitech-hidpp.c` — Logitech HID++
- `hid-primax.c` — Primax keyboards
- `hid-multitouch.c` — multitouch devices
- `hid-vivaldi-common.c` — Vivaldi keyboard
- Record: [Called from core HID input path and multiple drivers — very
  high impact surface]

**Step 5.3-5.4: Call Chain**
- USB HID: `hid_irq_in()` → `hid_input_report()` →
  `__hid_input_report()` → `hid_report_raw_event()`
- This is reachable from any USB HID device event — keyboards, mice,
  touchscreens, gamepads, etc.
- Also reachable from I2C-HID, BT-HID, and other transports.
- Record: [Reachable from any HID device input — universal impact]

## PHASE 6: STABLE TREE ANALYSIS

**Step 6.1: Buggy Code in Stable?**
- The memset dates to 2008. Present in every stable tree.
- Record: [ALL active stable trees contain the buggy code]

**Step 6.2: Backport Complications**
- `hid_warn_ratelimited` only in v6.18+. For older stable trees, trivial
  substitution needed (e.g., `hid_warn`).
- The rest of the code context (csize, rsize, max_buffer_size, goto out)
  is identical in recent stable trees (verified: max_buffer_size was
  added in b1a37ed00d790 from 2023, present in 6.6+).
- Record: [Minor adaptation needed for < 6.18, clean apply otherwise]

**Step 6.3: Related Fixes in Stable**
- Previous mitigations (max_buffer_size capping, off-by-one fix) are in
  stable but didn't eliminate the fundamental OOB risk.
- Record: [No equivalent fix already in stable — this is the definitive
  solution]

## PHASE 7: SUBSYSTEM CONTEXT

**Step 7.1: Subsystem Criticality**
- HID core — every keyboard, mouse, touchscreen, gamepad, etc. goes
  through this code.
- Criticality: **IMPORTANT** (affects virtually all desktop/laptop
  systems and many embedded devices)

**Step 7.2: Subsystem Activity**
- Very active — multiple fixes per release cycle.

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: Affected Users**
- Every system with HID devices (USB, Bluetooth, I2C) — essentially
  universal for desktops/laptops.

**Step 8.2: Trigger Conditions**
- A HID device sends a report shorter than the expected report size.
- Can be triggered by: malicious USB devices, faulty/buggy HID devices,
  or specific device configurations.
- Potentially exploitable via USB (e.g., BadUSB attacks).
- Record: [Trigger: short HID report] [Moderate likelihood for
  accidental, high for deliberate]

**Step 8.3: Failure Mode**
- **OOB write**: memset writes past buffer boundary → memory corruption,
  potential code execution
- **OOB read**: subsequent `hid_process_report()` reads past buffer →
  info leak or crash
- Severity: **CRITICAL** (OOB writes = security vulnerability, potential
  crash/corruption)

**Step 8.4: Risk-Benefit**
- Benefit: **VERY HIGH** — prevents OOB writes in a core, universally-
  used kernel path. Addresses a class of bugs that has caused multiple
  CVEs/crashes historically.
- Risk: **VERY LOW** — 4-line change, simple logic (reject vs. pad),
  maintainer acknowledged 99% of cases won't be affected, accepted the
  tradeoff.
- Ratio: Strongly favors backporting.

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: Evidence Summary**

FOR backporting:
- Fixes OOB writes and reads (security-critical memory safety bug)
- In HID core — affects all HID users (universal impact)
- Very small change: 4 lines, single function, single file
- Bug exists since 2008 — present in ALL stable trees
- Long history of crashes/CVEs from this exact memset (966922f, 5ebdffd,
  ec61b41)
- Reviewed and applied by HID co-maintainer (Tissoires)
- Suggested by the maintainer himself
- Fix is the definitive solution after years of band-aid fixes

AGAINST backporting:
- Uses `hid_warn_ratelimited` not available before v6.18 (trivially
  adaptable)
- Tissoires noted potential for breaking devices relying on zero-padding
  (accepted risk)
- No explicit stable nomination (expected for candidates)

**Step 9.2: Stable Rules Checklist**
1. Obviously correct and tested? **YES** — reviewed by maintainer,
   iterated through 3 versions
2. Fixes a real bug? **YES** — OOB write/read in HID core
3. Important issue? **YES** — security vulnerability (OOB write),
   potential crash/corruption
4. Small and contained? **YES** — 4 lines, single function
5. No new features or APIs? **YES** — behavior change only (reject
   instead of pad)
6. Can apply to stable? **YES** — with trivial adaptation for
   hid_warn_ratelimited

**Step 9.3: Exception Categories**
- Not an exception category — this is a standard critical bug fix.

**Step 9.4: Decision**
This is a clear YES. A 4-line fix to a critical OOB write vulnerability
in the core HID input path, present since 2008, with a long history of
related crashes, endorsed by the HID co-maintainer.

## Verification

- [Phase 1] Parsed tags: Suggested-by Tissoires, SOB by Lee Jones and
  Tissoires (maintainer applied)
- [Phase 2] Diff analysis: +4/-3 lines in hid_report_raw_event(),
  replaces memset+dbg_hid with warn+return -EINVAL
- [Phase 3] git blame: buggy memset from commit 85cdaf524b7dda (2008,
  v2.6.26), present in all stable trees
- [Phase 3] git log: found 3 prior fixes to same memset area (966922f,
  5ebdffd, b1a37ed) — confirms recurring issue
- [Phase 3] Author: Lee Jones authored the max_buffer_size hardening
  (b1a37ed), experienced with this code
- [Phase 4] lore.kernel.org: v1 reviewed by Tissoires who requested
  stronger approach; v3 accepted with -EINVAL return; maintainer noted
  "works in 99% of cases"
- [Phase 5] Callers: hid_report_raw_event() called from
  __hid_input_report() (core path) and 6+ drivers
- [Phase 6] hid_warn_ratelimited introduced in v6.18 (1d64624243af8) —
  verified not in v6.12/6.14/6.15/6.16/6.17; needs trivial adaptation
  for older trees
- [Phase 6] Companion patch e716edafedad4 is independent (hid-
  multitouch.c report ID check), not a prerequisite
- [Phase 8] Failure mode: OOB writes via memset → memory corruption,
  severity CRITICAL
- UNVERIFIED: Exact behavior with specific HID devices that send
  intentionally short reports (Tissoires accepted the risk)

**YES**

 drivers/hid/hid-core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index a5b3a8ca2fcbc..f5587b786f875 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2057,9 +2057,10 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
 		rsize = max_buffer_size;
 
 	if (csize < rsize) {
-		dbg_hid("report %d is too short, (%d < %d)\n", report->id,
-				csize, rsize);
-		memset(cdata + csize, 0, rsize - csize);
+		hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n",
+				     report->id, rsize, csize);
+		ret = -EINVAL;
+		goto out;
 	}
 
 	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
-- 
2.51.0


^ permalink raw reply related


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