From: sashiko-bot@kernel.org
To: "Michael Scott" <mike.scott@oss.qualcomm.com>
Cc: neil.armstrong@linaro.org, olteanv@gmail.com,
conor+dt@kernel.org, vkoul@kernel.org, robh@kernel.org,
linux-phy@lists.infradead.org, devicetree@vger.kernel.org
Subject: Re: [PATCH 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
Date: Thu, 21 May 2026 01:32:18 +0000 [thread overview]
Message-ID: <20260521013219.BC4F31F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260521003615.1260844-2-mike.scott@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] Bailing out early in `qmp_combo_usb_exit()` completely bypasses the release of shared common resources, causing a permanent reference leak when a Type-C switch to `DP_ONLY` occurs.
- [High] A lockless Time-of-Check to Time-of-Use (TOCTOU) race condition on `qmp->usb_init_count` in `qmp_combo_usb_exit()` leads to integer underflow and state corruption.
Pre-existing issues:
- [High] The patch attempts to fix an MMIO crash by introducing a Use-After-Free read on the `qmp` driver data structure.
--
commit 35c4e56f462fac540e8354624e2048c6bd3ecd9e
Author: Michael Scott <mike.scott@oss.qualcomm.com>
phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
This commit adds checks to qmp_combo_usb_power_off() and qmp_combo_usb_exit()
to guard against being called by an external consumer after the device's
backing resources have been released. It uses the usb_init_count variable
to determine if the PHY is powered on, skipping the operations to prevent
an oops.
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 93f1aa10d4008..4057583c0cfeb 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3922,6 +3922,17 @@ static int qmp_combo_usb_power_off(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
>
> + /*
> + * Reachable as ->exit from external consumers (notably dwc3) after
> + * this device's backing resources have already been released along
> + * a teardown chain. Refuse to touch registers in that case.
> + */
> + if (!qmp->usb_init_count) {
[Severity: High]
This isn't a bug introduced by this patch, but does this check introduce
a use-after-free read on the qmp driver data structure?
The commit message notes that this path runs after the device's backing
resources are released. Since qmp is allocated using devm_kzalloc(), it is
also freed during devres teardown.
When dwc3 calls phy_exit() later, phy_get_drvdata() returns a freed pointer.
Dereferencing qmp->usb_init_count accesses this freed memory. If the memory
was reallocated and non-zero, or if KASAN is enabled, wouldn't this still
trigger a use-after-free and crash instead of masking the teardown order bug?
> + dev_dbg(qmp->dev, "%s: PHY not powered on, skipping\n",
> + __func__);
> + return 0;
> + }
> +
> clk_disable_unprepare(qmp->pipe_clk);
[ ... ]
> @@ -3966,6 +3977,17 @@ static int qmp_combo_usb_exit(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> int ret;
>
> + /*
> + * See qmp_combo_usb_power_off(): an external consumer may call
> + * phy_exit() after the QMP device's resources have been torn
> + * down. usb_init_count tracks usb_init/usb_exit balance.
> + */
> + if (!qmp->usb_init_count) {
[Severity: High]
Does bailing out early here bypass the release of shared common resources,
causing a reference leak when a Type-C switch to DP_ONLY occurs?
When the Type-C mux switches to QMPPHY_MODE_DP_ONLY,
qmp_combo_typec_mux_set() decrements usb_init_count to 0 but leaves
init_count unchanged. If the consumer unbinds and calls phy_exit() in
this state, this early return bypasses the qmp_combo_com_exit(qmp, false)
call.
Doesn't this mean qmp->init_count is never decremented, permanently
leaking shared resources like clocks and regulators?
[Severity: High]
Is there a lockless Time-of-Check to Time-of-Use race condition here?
This check is performed before acquiring qmp->phy_mutex. If another path
like qmp_combo_typec_mux_set() holds the mutex and decrements
usb_init_count to 0:
CPU1
qmp_combo_usb_exit()
if (!qmp->usb_init_count) // observes > 0
mutex_lock(&qmp->phy_mutex); // blocks
CPU2
qmp_combo_typec_mux_set()
mutex_lock(&qmp->phy_mutex);
qmp->usb_init_count--; // becomes 0
mutex_unlock(&qmp->phy_mutex);
When CPU1 acquires the lock, it proceeds to decrement qmp->usb_init_count
without re-verifying the state. Doesn't decrementing 0 cause an integer
underflow to UINT_MAX, breaking the PHY's power management balance?
> + dev_dbg(qmp->dev, "%s: PHY not initialised, skipping\n",
> + __func__);
> + return 0;
> + }
> +
> mutex_lock(&qmp->phy_mutex);
> ret = qmp_combo_usb_power_off(phy);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260521003615.1260844-1-mike.scott@oss.qualcomm.com?part=1
next prev parent reply other threads:[~2026-05-21 1:32 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 0:36 [PATCH 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
2026-05-21 0:36 ` [PATCH 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
2026-05-21 1:32 ` sashiko-bot [this message]
2026-05-21 0:36 ` [PATCH 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
2026-05-21 2:20 ` sashiko-bot
2026-05-21 0:36 ` [PATCH 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on Michael Scott
2026-05-21 0:36 ` [PATCH 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260521013219.BC4F31F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=mike.scott@oss.qualcomm.com \
--cc=neil.armstrong@linaro.org \
--cc=olteanv@gmail.com \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox