[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