Re: [PATCH] mfd: qnap-mcu: clear the reply state when a command times out
[email protected] Sun, 02 Aug 2026 13:20:11 +0000
| Newsgroups | dev.linux.lists.mfd |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider: New issues: - [Critical] Lockless clearance of `reply->length` and `reply->data` on the timeout path introduces a TOCTOU race leading to a NULL pointer dereference or unbounded stack overflow. - [Low] The commit message description is not capitalized. Pre-existing issues: - [High] Unhandled error path from `qnap_mcu_write` fails to clear the reply state, leaving a stale pointer to a destroyed stack frame. - [High] Dynamic modification of a non-const global `mfd_cell` array during driver probe violates MFD subsystem rules and introduces a data race. - [High] Lockless design of `qnap_mcu_receive_buf()` causes data races against `qnap_mcu_exec()` initialization, leading to cross-command state corruption on unhandled timeouts. - [High] Passing complex structure pointers directly through the `.data` field in the `of_device_id` match table violates MFD subsystem guidelines. -- --- Patch [1]: [PATCH] mfd: qnap-mcu: clear the reply state when a command times out --- commit 89b6394df945cf63d91370772916c2e3c424866f Author: Ali Ahmet Memis <[email protected]> mfd: qnap-mcu: clear the reply state when a command times out This commit modifies the timeout path in qnap_mcu_exec() to clear the reply length and pointer. The goal is to prevent a late asynchronous reply from being written into a destroyed on-stack buffer. > mfd: qnap-mcu: clear the reply state when a command times out [Severity: Low] This isn't a bug introduced by this patch, but the MFD subsystem guidelines require capitalizing the description after the subsystem prefix. Could we update the subject to "mfd: qnap-mcu: Clear the reply state..."? > diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c > index 8de974ddac3e7..f810cb4ff2ab7 100644 > --- a/drivers/mfd/qnap-mcu.c > +++ b/drivers/mfd/qnap-mcu.c > @@ -239,6 +239,8 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, > > if (!wait_for_completion_timeout(&reply->done, msecs_to_jiffies(QNAP_MCU_TIMEOUT_MS))) { > dev_err(&mcu->serdev->dev, "Command timeout\n"); > + reply->length = 0; > + reply->data = NULL; [Severity: Critical] Does clearing these fields locklessly introduce a race condition with the asynchronous receive callback? If qnap_mcu_receive_buf() is actively executing: qnap_mcu_receive_buf() if (!reply->length) return size; while (src < end) { reply->data[reply->received] = *src++; ... if (reply->received == reply->length) ... If the compiler reloads reply->data after it is set to NULL, couldn't this cause a NULL pointer dereference? Additionally, if it caches reply->data but reloads reply->length as 0, the termination condition reply->received == reply->length becomes impossible to satisfy. Could this cause the loop to blindly copy incoming bytes and create an unbounded stack overflow? > return -ETIMEDOUT; > } [Severity: High] This is a pre-existing issue, but the error path for qnap_mcu_write() in qnap_mcu_exec() appears to leave a stale pointer: qnap_mcu_exec() { ... reply->data = rx; reply->length = length; ... ret = qnap_mcu_write(mcu, cmd_data, cmd_data_size); if (ret < 0) return ret; If qnap_mcu_write() fails, we return without clearing reply->length and reply->data. Could an asynchronous UART receive callback write into the destroyed stack frame here? [Severity: High] This is a pre-existing issue, but does the lockless design of qnap_mcu_receive_buf() allow cross-command state corruption? In qnap_mcu_exec(), we initialize the reply locklessly: qnap_mcu_exec() { ... reply->data = rx; reply->length = length; reply->received = 0; ... If a previous command timed out and a late reply arrives while these fields are being initialized for the next command, could the late reply bytes corrupt the new command's buffer or incorrectly trigger its completion? [Severity: High] This is a pre-existing issue, but does qnap_mcu_probe() dynamically modify a shared global mfd_cell array? Looking at qnap_mcu_cells: static struct mfd_cell qnap_mcu_cells[] = { ... }; qnap_mcu_probe() { ... qnap_mcu_cells[i].platform_data = mcu->variant; qnap_mcu_cells[i].pdata_size = sizeof(*mcu->variant); } MFD subsystem rules require mfd_cell arrays to be static and constant. If two QNAP MCU devices are probed concurrently, could they mutate this shared global array simultaneously and cause a data race? [Severity: High] This is a pre-existing issue, but is it safe to pass complex structure pointers through the match table data field? qnap_mcu_dt_ids[] = { { .compatible = "qnap,ts133-mcu", .data = &qnap_ts133_mcu }, ... }; The MFD subsystem guidelines state that passing complex pointers through match data tables can cause memory safety hazards and initialization races. The guidelines mandate using an enum or integer ID instead. Should this be updated to select the static struct in the probe function? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1