Linux Input/HID development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Sasha Levin" <sashal@kernel.org>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow
Date: Mon, 19 Oct 2026 14:35:59 +0000	[thread overview]
Message-ID: <sashiko-outbox-177440@kernel.org> (raw)
In-Reply-To: <20261019135441.1420968-123-sashal@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] HID: quicki2c: input_buf size mismatch with DMA in quicki2c_alloc_report_buf()
- [Medium] HID: intel-thc-hid: incomplete report_buf sizing in quicki2c_alloc_report_buf()
--

commit 916fd20197b9aebc1d04d169b7d6a4523c3d0a4d
Author: Even Xu <even.xu@intel.com>

HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow

This commit enlarges the qcdev->input_buf and qcdev->report_buf allocations
in quicki2c_alloc_report_buf() by wrapping max_report_len with
HIDI2C_PACKET_LEN() to account for the 2-byte HID-over-I2C packet length
header.

> diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> index c6ba6886072ad..4588c55cf255d 100644
> --- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> @@ -586,7 +586,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
>  	 */
>  	max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), SZ_4K);
>  
> -	qcdev->input_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
> +	qcdev->input_buf = devm_kzalloc(qcdev->dev,
> +					HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);

[Severity: High]
Can qcdev->input_buf still be overflowed or mismatched with the DMA packet
limits when reading reports into it?

In drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c, read_dma_buffer()
bounds-checks the incoming DMA transfer only against
read_config->max_packet_size before copying into read_buff
(qcdev->input_buf):

drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c:read_dma_buffer() {
	prd_tbl = &read_config->prd_tbls[prd_table_index];
	mes_len = calc_message_len(prd_tbl, &nent);
	if (mes_len > read_config->max_packet_size) {
		...
		return -EMSGSIZE;
	}

	sg = read_config->sgls[prd_table_index];
	ret = sg_copy_to_buffer(sg, nent, read_buff, mes_len);
}

Meanwhile, quicki2c_dma_init() and quicki2c_dma_adv_enable() in
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c configure the DMA
and hardware frame limits using the raw max_input_len and report_desc_len
without HIDI2C_PACKET_LEN():

drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_dma_init() {
	swdma_max_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len),
			    le16_to_cpu(qcdev->dev_desc.report_desc_len));

	ret = thc_dma_set_max_packet_sizes(qcdev->thc_hw, 0,
					   le16_to_cpu(qcdev->dev_desc.max_input_len),
					   le16_to_cpu(qcdev->dev_desc.max_output_len),
					   swdma_max_len);
}

drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_dma_adv_enable() {
	if (qcdev->i2c_max_frame_size_enable) {
		if (qcdev->i2c_max_frame_size >=
		    le16_to_cpu(qcdev->dev_desc.max_input_len)) {
			thc_i2c_set_rx_max_size(qcdev->thc_hw,
						le16_to_cpu(qcdev->dev_desc.max_input_len));
}

Because dma_set_max_packet_size() rounds max_packet_size up with
ALIGN(size, SZ_4K), this leaves three mismatches on the
quicki2c_irq_thread_handler() -> handle_input_report() -> thc_rxdma_read()
and quicki2c_hid_raw_request() -> quicki2c_get_report() -> thc_swdma_read()
paths:

1. If report_desc_len is larger than max(max_input_len, SZ_4K) + 2,
THC_SWDMA has max_packet_size = ALIGN(report_desc_len, SZ_4K) while
qcdev->input_buf is only max(max_input_len, SZ_4K) + 2 bytes, so
quicki2c_get_report() calling thc_swdma_read() with prd_tbl_len = NULL can
copy past the end of qcdev->input_buf.

2. If max_input_len > SZ_4K and is not within 2 bytes of a 4K multiple (for
example, 4100), qcdev->input_buf is 4102 bytes while THC_RXDMA2 and
THC_SWDMA have max_packet_size = 8192 bytes, allowing read_dma_buffer() to
overflow qcdev->input_buf if a larger DMA transfer arrives.

3. If max_input_len is 4095 or an exact multiple of SZ_4K (such as 4096),
passing raw max_input_len to thc_dma_set_max_packet_sizes() and
thc_i2c_set_rx_max_size() leaves the DMA buffer and RX max frame size at
4096 or 4095 bytes, whereas a full-size input packet with its 2-byte length
header requires 4098 or 4097 bytes.

Should quicki2c_dma_init(), quicki2c_dma_adv_enable(), and the
qcdev->input_buf allocation all use consistent packet sizes?

>  	if (!qcdev->input_buf)
>  		return -ENOMEM;
>  
> @@ -596,7 +597,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
>  	max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_output_len),
>  			     max_report_len);
>  
> -	qcdev->report_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
> +	qcdev->report_buf = devm_kzalloc(qcdev->dev,
> +					 HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
>  	if (!qcdev->report_buf)
>  		return -ENOMEM;
>  

[Severity: Medium]
Does enlarging qcdev->report_buf by HIDI2C_PACKET_LEN(max_report_len) allow
maximum-length output or feature reports to succeed?

At the end of quicki2c_alloc_report_buf(), qcdev->report_len is still set
to max_report_len:

drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_alloc_report_buf() {
	qcdev->report_buf = devm_kzalloc(qcdev->dev,
					 HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
	if (!qcdev->report_buf)
		return -ENOMEM;

	qcdev->report_len = max_report_len;
}

When write_cmd_to_txdma() or quicki2c_get_report() in
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c formats a
packet into qcdev->report_buf, it passes qcdev->report_len as write_buf_len
to quicki2c_init_write_buf():

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c:write_cmd_to_txdma() {
	ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
				      buf_len, qcdev->report_buf, qcdev->report_len);
}

And quicki2c_init_write_buf() prepends cmd_reg (HIDI2C_REG_LEN = 2 bytes),
cmd (HIDI2C_CMD_LEN = 2 bytes, or HIDI2C_CMD_LEN_OPT = 3 bytes when
report_id >= 15), data_reg (HIDI2C_REG_LEN = 2 bytes), and the packet
length header (HIDI2C_LENGTH_LEN = 2 bytes) before checking against
write_buf_len:

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c:quicki2c_init_write_buf() {
	buf_len = HIDI2C_REG_LEN + cmd_len;

	if (append_data_reg)
		buf_len += HIDI2C_REG_LEN;

	if (data && data_len)
		buf_len += data_len + HIDI2C_LENGTH_LEN;

	if (buf_len > write_buf_len)
		return -EINVAL;
}

Because qcdev->report_len is left at max_report_len, the extra 2 bytes in
qcdev->report_buf cannot be used, and because quicki2c_init_write_buf()
writes 8 to 9 bytes of framing ahead of data_len, HIDI2C_PACKET_LEN() (only
2 extra bytes) is still 6 to 7 bytes short for a payload of max_report_len
bytes, causing quicki2c_init_write_buf() to return -EINVAL.

Should qcdev->report_buf and qcdev->report_len both be sized to include the
full command, register, and packet length headers written by
quicki2c_init_write_buf()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-123-sashal@kernel.org?part=1

  reply	other threads:[~2026-10-19 14:36 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow Sasha Levin
2026-10-19 14:35   ` sashiko-bot [this message]
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] iio: hid-sensor: als: scale each channel individually Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.1] HID: quirks: add ALWAYS_POLL quirk for AULA Mini 60 HE Pro Dongle Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.6] HID: i2c-hid: Add a quirk for a Cirque I2C device Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] HID: amd_sfh: Serialize access to the shared emp2 pointer Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: multitouch: Fix stale MT slots when contact count drops to zero Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: elecom: Add support for ELECOM M-XT4DRBK (018E) Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: i2c-hid: add reset quirk for Lenovo Yoga Slim 7x Gen 11 keyboard Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: intel-ish-hid: ignore post-init ENUM_DEVICES from firmware Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] HID: roccat: fix locking in roccat_connect() and roccat_disconnect() Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow Sasha Levin
2026-10-19 15:04   ` sashiko-bot
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: quirks: Add ALWAYS_POLL quirk for Beitong BTP-KP20D dongle Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: i2c-hid: Add i2c-hid-quirk-bad-input-size quirk for 0911:5288 device Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.6] HID: logitech-hidpp: Add support for G502 X Plus USB mouse Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports Sasha Levin
2026-10-19 15:07   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-177440@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sashal@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox