Linux Input/HID development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "HyeongJun An" <sammiee5311@gmail.com>
Cc: dmitry.torokhov@gmail.com, linux-input@vger.kernel.org
Subject: Re: [PATCH v2] HID: intel-thc-hid: intel-quickspi: validate report size before copy
Date: Fri, 17 Jul 2026 09:37:35 +0000	[thread overview]
Message-ID: <20260717093735.EA6751F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260717091622.1744196-1-sammiee5311@gmail.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Unbounded memcpy in `quickspi_get_report()` causes a heap buffer overflow if the device responds with a report larger than the caller-allocated buffer.
- [High] The receive buffer `qsdev->input_buf` can be overflowed during an RXDMA interrupt because the message size is bounds-checked against a 4K-aligned limit instead of the actual buffer capacity.
- [High] Unbounded memcpy in `quickspi_handle_input_data()` causes a heap buffer overflow of `qsdev->report_buf` on the receive path.
- [High] Concurrent ioctl requests lead to data corruption in the shared DMA buffer `qsdev->report_buf`.
--

--- Patch [1]: [PATCH v2] HID: intel-thc-hid: intel-quickspi: validate report size before copy ---
commit 13f5051992cd9276077cab1966153d3866079f49
Author: HyeongJun An <sammiee5311@gmail.com>

    HID: intel-thc-hid: intel-quickspi: validate report size before copy
    
    write_cmd_to_txdma() builds an output report in qsdev->report_buf, a heap
    buffer allocated in quickspi_alloc_report_buf() to the device-descriptor
    derived max_report_len (a few hundred bytes for a touch controller).  It
    copies the caller-supplied report into that buffer:
    
[ ... ]

> diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> index 4ae2e1718b30c..da5ecfcd0fbf8 100644
> --- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> +++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> @@ -555,7 +555,14 @@ static int quickspi_alloc_report_buf(struct quickspi_device *qsdev)
>  	max_report_len = max(le16_to_cpu(qsdev->dev_desc.max_output_len),
>  			     le16_to_cpu(qsdev->dev_desc.max_input_len));
>  
> -	qsdev->report_buf = devm_kzalloc(qsdev->dev, max_report_len, GFP_KERNEL);
> +	/*
> +	 * write_cmd_to_txdma() writes the output report header ahead of the
> +	 * content in this buffer, so it has to hold both.
> +	 */
> +	qsdev->report_buf_size = HIDSPI_OUTPUT_REPORT_SIZE(max_report_len);
> +
> +	qsdev->report_buf = devm_kzalloc(qsdev->dev, qsdev->report_buf_size,
> +					 GFP_KERNEL);

[Severity: High]
This is a pre-existing issue, but does the allocation for qsdev->input_buf
earlier in quickspi_alloc_report_buf() need to be 4K-aligned to prevent a heap
overflow during an RX DMA interrupt?

In thc_rxdma_read(), read_dma_buffer() bounds-checks the message length
against read_config->max_packet_size, which is 4K-aligned via
thc_dma_set_max_packet_sizes().

If a hardware device sends a DMA packet larger than max_input_len but
smaller than or equal to ALIGN(max_input_len, SZ_4K), it would pass the
bounds check in read_dma_buffer():

intel-thc/intel-thc-dma.c:read_dma_buffer() {
    ...
    if (mes_len > read_config->max_packet_size) {
    ...
}

and copy up to 4096 bytes into qsdev->input_buf, which was allocated strictly
to the unaligned max_input_len.

>  	if (!qsdev->report_buf)
>  		return -ENOMEM;
>  

[ ... ]

> diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c
> index cb19057f1191b..db6054843e777 100644
> --- a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c
> +++ b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c
> @@ -30,6 +30,9 @@ static int write_cmd_to_txdma(struct quickspi_device *qsdev,
>  
>  	write_buf = (struct output_report *)qsdev->report_buf;
>  
> +	if (HIDSPI_OUTPUT_REPORT_SIZE(report_buf_len) > qsdev->report_buf_size)
> +		return -EINVAL;
> +
>  	write_buf->output_hdr.report_type = report_type;
>  	write_buf->output_hdr.content_len = cpu_to_le16(report_buf_len);
>  	write_buf->output_hdr.content_id = report_id;
>  
>  	if (report_buf && report_buf_len > 0)
>  		memcpy(write_buf->content, report_buf, report_buf_len);

[Severity: High]
This is a pre-existing issue, but can concurrent ioctl requests cause data
corruption in the shared DMA buffer qsdev->report_buf?

Multiple userspace processes can concurrently call HIDIOCSFEATURE or
HIDIOCGFEATURE. The HID core routines hold a read-lock, allowing parallel
execution in the driver callbacks.

Does write_cmd_to_txdma() modify qsdev->report_buf and trigger DMA writes
without mutual exclusion against concurrent TX or RX requests like
quickspi_handle_input_data()?

quickspi-protocol.c:quickspi_handle_input_data() {
    ...
    memcpy(qsdev->report_buf, input_report, qsdev->report_len);
    ...
}


[Severity: High]
This is a pre-existing issue, but can the receive path also overflow
qsdev->report_buf?

While this patch secures the output path, quickspi_handle_input_data()
parses input_len from the payload and executes an unbounded memcpy:

quickspi-protocol.c:quickspi_handle_input_data() {
    ...
    memcpy(qsdev->report_buf, input_report, qsdev->report_len);
    ...
}

If a compromised device sends a GET_FEATURE_RESPONSE with a length exceeding
qsdev->report_buf_size, will this cause a heap buffer overflow?


[Severity: Critical]
This isn't a bug introduced by this patch, but is there an unbounded memcpy
in quickspi_get_report() that could cause a heap buffer overflow?

When a userspace process calls ioctl(HIDIOCGFEATURE) with a length parameter
smaller than the actual hardware report size, quickspi_hid_raw_request()
discards the bounds-checking len parameter:

quickspi-hid.c:quickspi_hid_raw_request() {
    ...
    ret = quickspi_get_report(qsdev, rtype, reportnum, buf);
    ...
}

Then quickspi_get_report() copies qsdev->report_len bytes into the
caller's buffer without validating against the buffer's true capacity:

quickspi-protocol.c:quickspi_get_report() {
    ...
    memcpy(buf, qsdev->report_buf, qsdev->report_len);
    ...
}

Could this lead to memory corruption if the device responds with a report
larger than the caller-allocated buffer?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260717091622.1744196-1-sammiee5311@gmail.com?part=1

      reply	other threads:[~2026-07-17  9:37 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-28 13:37 [PATCH] HID: intel-thc-hid: intel-quickspi: validate report size before copy HyeongJun An
2026-06-28 13:51 ` sashiko-bot
2026-07-17  9:16 ` [PATCH v2] " HyeongJun An
2026-07-17  9:37   ` sashiko-bot [this message]

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=20260717093735.EA6751F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sammiee5311@gmail.com \
    --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