From: sashiko-bot@kernel.org
To: "Tristan Madani" <tristmd@gmail.com>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH] HID: intel-thc-hid: validate ACPI buffer length before use
Date: Sat, 24 Oct 2026 21:35:18 +0000 [thread overview]
Message-ID: <sashiko-outbox-183886@kernel.org> (raw)
In-Reply-To: <20261024205850.4051206-1-tristmd@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] HID: intel-thc-hid: ISUB size check in quicki2c_acpi_get_dsd_property() fails
- [High] HID: intel-thc-hid: opcode size check in thc_acpi_get_property() fails probe
--
commit 7818ecd95e7c011bb989cd8c07a2ef782c095de2
Author: Tristan Madani <tristan@talencesecurity.com>
HID: intel-thc-hid: validate ACPI buffer length before use
This commit adds a buf_size parameter to the QuickI2C and QuickSPI ACPI
property helpers to enforce exact buffer length matching for buffer properties
and adds object type validation to the QuickI2C DSD helper.
> 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 7a913f717efaa..6f70b64f20105 100644
> --- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
[ ... ]
> @@ -97,7 +105,8 @@ static int quicki2c_acpi_get_dsm_property(struct acpi_device *adev, const guid_t
> * Return: 0 if success or ENODEV on failed.
> */
> static int quicki2c_acpi_get_dsd_property(struct acpi_device *adev, acpi_string dsd_method_name,
> - acpi_object_type type, void *prop_buf)
> + acpi_object_type type, void *prop_buf,
> + size_t buf_size)
> {
> acpi_handle handle = acpi_device_handle(adev);
> struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> @@ -113,7 +122,18 @@ static int quicki2c_acpi_get_dsd_property(struct acpi_device *adev, acpi_string
>
> ret_obj = buffer.pointer;
>
> + if (ret_obj->type != type) {
> + kfree(buffer.pointer);
> + return -EINVAL;
> + }
> + if (buf_size > 0 && ret_obj->buffer.length != buf_size) {
> + int err = ret_obj->buffer.length > buf_size ? -ENOSPC : -EINVAL;
> +
> + kfree(buffer.pointer);
> + return err;
> + }
> memcpy(prop_buf, ret_obj->buffer.pointer, ret_obj->buffer.length);
> + kfree(buffer.pointer);
>
> return 0;
> }
[ ... ]
> @@ -180,7 +201,8 @@ static int quicki2c_get_acpi_resources(struct quicki2c_device *qcdev)
> qcdev->i2c_config.target_addr = i2c_param.device_address;
>
> ret = quicki2c_acpi_get_dsd_property(adev, QUICKI2C_ACPI_METHOD_NAME_ISUB,
> - ACPI_TYPE_BUFFER, &i2c_config);
> + ACPI_TYPE_BUFFER, &i2c_config,
> + sizeof(i2c_config));
> if (ret)
> return ret;
[Severity: High]
Will requiring ret_obj->buffer.length to equal sizeof(i2c_config) in
quicki2c_get_acpi_resources() -> quicki2c_acpi_get_dsd_property() cause
QuickI2C probing to fail with -EINVAL?
In drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h,
struct quicki2c_subip_acpi_config is defined without __packed:
struct quicki2c_subip_acpi_config {
u64 SMHX;
...
u64 FSEN;
u64 FSVL;
u64 INDE;
u64 INDV;
u8 reserved;
};
With 22 u64 fields (176 bytes) followed by u8 reserved (1 byte), the compiler
adds 7 bytes of tail alignment padding on 64-bit architectures, making
sizeof(i2c_config) equal to 184 bytes.
Firmware ACPI buffers returned by the ISUB method do not include compiler tail
padding. Tables with the 4 advanced-feature u64 fields (FSEN, FSVL, INDE,
INDV, added in commit 0b1fca9dce44 ("HID: intel-thc-hid: intel-quicki2c:
Change ISUB table length")) are at most 177 bytes (0xB1), while Lunar Lake and
older BIOSes (as noted in commit 1db9df89a213 ("HID: intel-thc-hid:
intel-quicki2c: Update ACPI ISUB method support")) return 145 bytes (0x91).
Because ret_obj->buffer.length != buf_size rejects anything other than 184
bytes, won't every valid ISUB table be rejected? Also, if shorter 145-byte
ISUB buffers are accepted when qcdev->ddata is non-NULL, should i2c_config be
zero-initialized in quicki2c_get_acpi_resources() so that FSEN, FSVL, INDE,
and INDV are not read uninitialized from the stack?
> 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 53023e30cf8d4..29689f41f6bf0 100644
> --- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> +++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> @@ -81,7 +81,8 @@ static const struct acpi_gpio_mapping quickspi_gpios[] = {
> * Return: 0 if successful or ENODEV on failed.
> */
> static int thc_acpi_get_property(struct acpi_device *adev, const guid_t *guid,
> - u64 rev, u64 func, acpi_object_type type, void *prop_buf)
> + u64 rev, u64 func, acpi_object_type type,
> + void *prop_buf, size_t buf_size)
> {
> acpi_handle handle = acpi_device_handle(adev);
> union acpi_object *obj;
> @@ -94,10 +95,20 @@ static int thc_acpi_get_property(struct acpi_device *adev, const guid_t *guid,
> return -ENODEV;
> }
>
> - if (type == ACPI_TYPE_INTEGER)
> + if (type == ACPI_TYPE_INTEGER) {
> *(u32 *)prop_buf = (u32)obj->integer.value;
> - else if (type == ACPI_TYPE_BUFFER)
> + } else if (type == ACPI_TYPE_BUFFER) {
> + if (buf_size > 0 && obj->buffer.length != buf_size) {
> + int err = obj->buffer.length > buf_size ? -ENOSPC : -EINVAL;
> +
> + acpi_handle_err(handle,
> + "_DSM buffer size mismatch: %llu vs %zu\n",
> + (unsigned long long)obj->buffer.length, buf_size);
> + ACPI_FREE(obj);
> + return err;
> + }
> memcpy(prop_buf, obj->buffer.pointer, obj->buffer.length);
> + }
>
> ACPI_FREE(obj);
>
> @@ -153,7 +164,8 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
> ACPI_QUICKSPI_REVISION_NUM,
> ACPI_QUICKSPI_FUNC_NUM_READ_OPCODE,
> ACPI_TYPE_BUFFER,
> - &qsdev->spi_read_opcode);
> + &qsdev->spi_read_opcode,
> + sizeof(qsdev->spi_read_opcode));
> if (ret)
> return ret;
>
> @@ -161,7 +173,8 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
> ACPI_QUICKSPI_REVISION_NUM,
> ACPI_QUICKSPI_FUNC_NUM_WRITE_OPCODE,
> ACPI_TYPE_BUFFER,
> - &qsdev->spi_write_opcode);
> + &qsdev->spi_write_opcode,
> + sizeof(qsdev->spi_write_opcode));
> if (ret)
> return ret;
[Severity: High]
Could passing sizeof(qsdev->spi_read_opcode) and
sizeof(qsdev->spi_write_opcode) to thc_acpi_get_property() break probing when
firmware returns 1-byte SPI opcode buffers?
In drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h, spi_read_opcode
and spi_write_opcode in struct quickspi_device are u32 (4 bytes):
u32 spi_read_opcode;
u32 spi_write_opcode;
However, per the HIDSPI _DSM specification (functions 4 and 5) and the
register configuration in drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c
in thc_spi_read_config() and thc_spi_write_config():
if (io_mode == THC_QUAD_IO)
opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO, opcode);
else if (io_mode == THC_DUAL_IO)
opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO, opcode);
else
opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO, opcode);
each SPI opcode is a single byte returned as a 1-byte ACPI buffer
(obj->buffer.length == 1) that was previously copied into the low byte of the
zero-allocated u32 field. With obj->buffer.length != buf_size checking against
4, won't thc_acpi_get_property() reject 1-byte opcode buffers with -EINVAL?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261024205850.4051206-1-tristmd@gmail.com?part=1
next prev parent reply other threads:[~2026-10-24 21:35 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 20:58 [PATCH] HID: intel-thc-hid: validate ACPI buffer length before use Tristan Madani
2026-10-24 21:35 ` sashiko-bot [this message]
2026-10-25 10:49 ` kernel test robot
2026-10-25 15:47 ` [PATCH v2] HID: intel-thc-hid: validate ACPI buffer length before memcpy Tristan Madani
2026-10-25 15:57 ` sashiko-bot
2026-10-26 2:02 ` Xu, Even
2026-10-25 21:40 ` [PATCH v3] " Tristan Madani
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-183886@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tristmd@gmail.com \
/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