Re: [PATCH v2] mfd: qnap-mcu: keep the reply buffer alive past a command timeout
[email protected] Sun, 02 Aug 2026 14:05:25 +0000
| Newsgroups | dev.linux.lists.mfd |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: New issues: - [Low] The commit message description is not capitalized, violating MFD subsystem formatting rules. Pre-existing issues: - [Critical] A data race between `qnap_mcu_exec()` and `qnap_mcu_receive_buf()` on `reply->length` and `reply->received` bypasses the loop exit condition, leading to a severe heap buffer overflow. - [High] Late UART replies from timed-out or failed commands can be written into the active buffer of the next command, causing data cross-talk and spurious early completion. - [High] A data race can cause `qnap_mcu_verify_checksum()` to be called with `reply->received == 0`, leading to an integer underflow and a deterministic kernel panic. -- --- Patch [1]: [PATCH v2] mfd: qnap-mcu: keep the reply buffer alive past a command timeout --- commit 876c0f2fd3f8e4b677ad50b82d00f3dcfe4a3283 Author: Ali Ahmet Memis <[email protected]> mfd: qnap-mcu: keep the reply buffer alive past a command timeout This patch moves the receive buffer from the stack in qnap_mcu_exec() to the qnap_mcu structure. This prevents stack corruption when late replies arrive after a command has timed out. Link: https://lore.kernel.org/all/[email protected]/ > mfd: qnap-mcu: keep the reply buffer alive past a command timeout [Severity: Low] Is there a capitalization typo in the subject line? Should "keep" be "Keep"? > diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c > index 8de974ddac3e7..93a3dd93404dd 100644 > --- a/drivers/mfd/qnap-mcu.c > +++ b/drivers/mfd/qnap-mcu.c [ ... ] > @@ -214,19 +216,18 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, > const u8 *cmd_data, size_t cmd_data_size, > u8 *reply_data, size_t reply_data_size) > { > - unsigned char rx[QNAP_MCU_RX_BUFFER_SIZE]; > size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE; > struct qnap_mcu_reply *reply = &mcu->reply; > int ret = 0; > > - if (length > sizeof(rx)) { > + if (length > sizeof(mcu->rx)) { > dev_err(&mcu->serdev->dev, "expected data too big for receive buffer"); > return -EINVAL; > } > > guard(mutex)(&mcu->bus_lock); > > - reply->data = rx; > + reply->data = mcu->rx; > reply->length = length; > reply->received = 0; [Severity: Critical] This is a pre-existing issue, but can this reset race with an active receive loop and cause a heap buffer overflow? If the receive thread is running in qnap_mcu_receive_buf() and we reset reply->received to 0 here without synchronization, the exact equality check in the receive thread could be bypassed: drivers/mfd/qnap-mcu.c:qnap_mcu_receive_buf() reply->received++; if (reply->received == reply->length) { ... If the equality check is bypassed, the receive loop could write unbounded bytes into reply->data (which now points to mcu->rx on the heap), causing a heap buffer overflow. > reinit_completion(&reply->done); [Severity: High] This isn't a bug introduced by this patch, but can resetting the completion here allow late replies to corrupt the new command? If a previous command times out, its receive thread is still active. If we just reset the completion and start a new command, could a concurrently arriving late response from the previous command be written into mcu->rx by qnap_mcu_receive_buf()? Since the old response is well-formed, it could pass the simple XOR checksum, triggering a spurious complete() and causing the new command to instantly return with stale data. > > ret = qnap_mcu_write(mcu, cmd_data, cmd_data_size); > if (ret < 0) > return ret; > > serdev_device_wait_until_sent(mcu->serdev, msecs_to_jiffies(QNAP_MCU_TIMEOUT_MS)); > > if (!wait_for_completion_timeout(&reply->done, msecs_to_jiffies(QNAP_MCU_TIMEOUT_MS))) { > dev_err(&mcu->serdev->dev, "Command timeout\n"); > return -ETIMEDOUT; > } > > - if (!qnap_mcu_verify_checksum(rx, reply->received)) { > + if (!qnap_mcu_verify_checksum(mcu->rx, reply->received)) { [Severity: High] This is a pre-existing issue, but could this cause an integer underflow and a kernel panic if reply->received is 0? If qnap_mcu_receive_buf() evaluates reply->received == reply->length and zeroes reply->length, but is preempted before calling complete(), the original command can time out. A new command could then call qnap_mcu_exec(), setting reply->received to 0. If the preempted receive thread then resumes and calls complete(), the new command will wake up and call qnap_mcu_verify_checksum() with reply->received == 0: drivers/mfd/qnap-mcu.c:qnap_mcu_verify_checksum() u8 crc = qnap_mcu_csum(buf, size - QNAP_MCU_CHECKSUM_SIZE); If size is 0, this underflows to the maximum size value, and qnap_mcu_csum() will loop reading sequentially out of bounds until it hits an unmapped page. > dev_err(&mcu->serdev->dev, "Invalid Checksum received from controller\n"); > return -EPROTO; > } -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1