[PATCH] HID: intel-thc-hid: intel-quicki2c: size the input buffer for the DMA

HyeongJun An <[email protected]>
Newsgroups org.kernel.vger.linux-input,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
quicki2c_alloc_report_buf() sizes input_buf as max(max_input_len, SZ_4K),
but two channels deliver into it and dma_set_max_packet_size() rounds both
up: RxDMA2 to ALIGN(max_input_len, SZ_4K) and SWDMA to
ALIGN(max(max_input_len, report_desc_len), SZ_4K).  read_dma_buffer()
bounds the copy against those, not against the allocation.

quicki2c_get_report() reads into input_buf with prd_tbl_len NULL, so
nothing programs a length, and a device declaring report_desc_len 5000
with max_input_len 64 overruns the 4K buffer by 4096 bytes.  The RxDMA2
leg additionally needs the I2C max input size clamp to be off.

Size input_buf from the SWDMA packet size and keep the 4K floor.

Fixes: 66b59bfce6d9 ("HID: intel-thc-hid: intel-quicki2c: Complete THC QuickI2C driver")
Cc: [email protected]
Assisted-by: Claude:claude-opus-5
Signed-off-by: HyeongJun An <[email protected]>
---
Not reproduced on hardware.  Triggering it needs a controller that sends
more than the lengths it declared, which is the case the existing comment
was already written for.

max_report_len is reused for the report_buf allocation below, so that
buffer and qcdev->report_len grow with input_buf whenever the SWDMA
ceiling is the larger term.  Both stay bounded by that ceiling.

 drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

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 0d2ad7bc3648..f6f9f95296d3 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
@@ -602,9 +602,12 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
 
 	/*
 	 * Some HIDI2C devices don't declare input/output max length correctly,
-	 * give default 4K buffer to avoid DMA buffer overrun.
+	 * give default 4K buffer to avoid DMA buffer overrun.  Both RxDMA2 and
+	 * SWDMA land here, so cover the larger SWDMA packet size.
 	 */
-	max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), SZ_4K);
+	max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len),
+			     le16_to_cpu(qcdev->dev_desc.report_desc_len));
+	max_report_len = max_t(size_t, ALIGN(max_report_len, SZ_4K), SZ_4K);
 
 	qcdev->input_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
 	if (!qcdev->input_buf)
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.