From: Tristan Madani <tristmd@gmail.com>
To: Even Xu <even.xu@intel.com>, Xinpeng Sun <xinpeng.sun@intel.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>,
Mark Pearson <mpearson-lenovo@squebb.ca>,
linux-input@vger.kernel.org, stable@vger.kernel.org,
Tristan Madani <tristan@talencesecurity.com>
Subject: [PATCH v3 1/2] HID: intel-thc-hid: quickspi: validate ACPI buffer length before memcpy
Date: Thu, 29 Oct 2026 14:10:35 +0000 [thread overview]
Message-ID: <20261029141037.2655603-2-tristmd@gmail.com> (raw)
In-Reply-To: <20261029141037.2655603-1-tristmd@gmail.com>
From: Tristan Madani <tristan@talencesecurity.com>
thc_acpi_get_property() copies firmware-returned ACPI buffers into
caller-provided structures without verifying the buffer length.
Malformed or short ACPI tables could cause an out-of-bounds read from
the firmware buffer, and oversized responses could overflow the
destination struct.
Add a buf_size parameter and reject responses larger than the
destination buffer. Accept shorter responses to handle firmware that
returns buffers without struct tail padding (e.g. 1 byte for a 4-byte
SPI opcode field). Zero-initialize caller stack structures so fields
beyond the firmware response length are deterministic.
Fixes: 7cb06f08ef13 ("HID: intel-thc-hid: intel-quickspi: Add THC QuickSPI ACPI interfaces")
Cc: stable@vger.kernel.org
Reviewed-by: Even Xu <even.xu@intel.com>
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
.../intel-quickspi/pci-quickspi.c | 37 ++++++++++++-------
1 file changed, 23 insertions(+), 14 deletions(-)
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 ad676fde211b6..deca020a46497 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
@@ -75,13 +75,15 @@ static const struct acpi_gpio_mapping quickspi_gpios[] = {
* @func: ACPI method's function number
* @type: ACPI parameter's data type
* @prop_buf: point to return buffer
+ * @buf_size: size of @prop_buf in bytes (0 to skip length check)
*
* This is a helper function for device to query its ACPI parameters.
*
* 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 +96,15 @@ 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) {
+ ACPI_FREE(obj);
+ return -ENOSPC;
+ }
memcpy(prop_buf, obj->buffer.pointer, obj->buffer.length);
+ }
ACPI_FREE(obj);
@@ -129,7 +136,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_HDR_ADDR,
ACPI_TYPE_INTEGER,
- &qsdev->input_report_hdr_addr);
+ &qsdev->input_report_hdr_addr, 0);
if (ret)
return ret;
@@ -137,7 +144,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_BDY_ADDR,
ACPI_TYPE_INTEGER,
- &qsdev->input_report_bdy_addr);
+ &qsdev->input_report_bdy_addr, 0);
if (ret)
return ret;
@@ -145,7 +152,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_OUTPUT_REP_ADDR,
ACPI_TYPE_INTEGER,
- &qsdev->output_report_addr);
+ &qsdev->output_report_addr, 0);
if (ret)
return ret;
@@ -153,7 +160,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 +169,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;
@@ -169,7 +178,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_IO_MODE,
ACPI_TYPE_INTEGER,
- &qsdev->spi_read_io_mode);
+ &qsdev->spi_read_io_mode, 0);
if (ret)
return ret;
@@ -184,7 +193,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_CONNECTION_SPEED,
ACPI_TYPE_INTEGER,
- &qsdev->spi_freq_val);
+ &qsdev->spi_freq_val, 0);
if (ret)
return ret;
@@ -192,7 +201,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_LIMIT_PACKET_SIZE,
ACPI_TYPE_INTEGER,
- &qsdev->limit_packet_size);
+ &qsdev->limit_packet_size, 0);
if (ret)
return ret;
@@ -205,7 +214,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_PERFORMANCE_LIMIT,
ACPI_TYPE_INTEGER,
- &qsdev->performance_limit);
+ &qsdev->performance_limit, 0);
if (ret)
return ret;
@@ -215,7 +224,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_ACTIVE_LTR,
ACPI_TYPE_INTEGER,
- &qsdev->active_ltr_val);
+ &qsdev->active_ltr_val, 0);
if (ret)
return ret;
@@ -223,7 +232,7 @@ static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
ACPI_QUICKSPI_REVISION_NUM,
ACPI_QUICKSPI_FUNC_NUM_LP_LTR,
ACPI_TYPE_INTEGER,
- &qsdev->low_power_ltr_val);
+ &qsdev->low_power_ltr_val, 0);
if (ret)
return ret;
--
2.47.3
next prev parent reply other threads:[~2026-10-29 14:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 14:10 [PATCH v3 0/2] HID: intel-thc-hid: validate ACPI buffer lengths Tristan Madani
2026-10-29 14:10 ` Tristan Madani [this message]
2026-10-29 14:10 ` [PATCH v3 2/2] HID: intel-thc-hid: quicki2c: validate ACPI buffer length before memcpy 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=20261029141037.2655603-2-tristmd@gmail.com \
--to=tristmd@gmail.com \
--cc=bentiss@kernel.org \
--cc=even.xu@intel.com \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=mpearson-lenovo@squebb.ca \
--cc=srinivas.pandruvada@linux.intel.com \
--cc=stable@vger.kernel.org \
--cc=tristan@talencesecurity.com \
--cc=xinpeng.sun@intel.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