[PATCH v9 02/12] mfd: nct6694: Check the length of received USB packets

From: a0282524688

Date: Tue Oct 13 2026 - 02:34:07 EST


From: Ming Yu <a0282524688@xxxxxxxxx>

The response status and the interrupt status are parsed without
checking how many bytes were actually received. A short or zero-length
packet leaves stale data in the buffer, which is then taken as a valid
status and may repeatedly dispatch the same interrupts.

Reject short response packets and ignore short interrupt packets.

Fixes: 51dad33ede63 ("mfd: Add core driver for Nuvoton NCT6694")
Signed-off-by: Ming Yu <a0282524688@xxxxxxxxx>
---
Changes in v9:
- None.

Changes in v8:
- New patch. Check the length of the response and interrupt packets
before parsing them.

drivers/mfd/nct6694.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/drivers/mfd/nct6694.c b/drivers/mfd/nct6694.c
index b9526b22754c..de0027c98726 100644
--- a/drivers/mfd/nct6694.c
+++ b/drivers/mfd/nct6694.c
@@ -117,6 +117,12 @@ int nct6694_read_msg(struct nct6694 *nct6694, const struct nct6694_cmd_header *c
if (ret)
return ret;

+ if (rx_len != sizeof(msg->response_header)) {
+ dev_err(nct6694->dev, "Expected response length %zu, but got %d\n",
+ sizeof(msg->response_header), rx_len);
+ return -EIO;
+ }
+
/* Receive data packet from USB device */
ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), buf,
le16_to_cpu(cmd_hd->len), &rx_len, NCT6694_URB_TIMEOUT);
@@ -173,6 +179,12 @@ int nct6694_write_msg(struct nct6694 *nct6694, const struct nct6694_cmd_header *
if (ret)
return ret;

+ if (rx_len != sizeof(msg->response_header)) {
+ dev_err(nct6694->dev, "Expected response length %zu, but got %d\n",
+ sizeof(msg->response_header), rx_len);
+ return -EIO;
+ }
+
/* Receive data packet from USB device */
ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), buf,
le16_to_cpu(cmd_hd->len), &rx_len, NCT6694_URB_TIMEOUT);
@@ -207,6 +219,9 @@ static void usb_int_callback(struct urb *urb)
goto resubmit;
}

+ if (urb->actual_length < sizeof(*status_le))
+ goto resubmit;
+
int_status = le32_to_cpu(*status_le);

while (int_status) {
--
2.34.1