* [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed
@ 2026-09-23 2:46 Fan Wu
2026-09-24 7:22 ` Huang Wei
2026-09-28 12:53 ` Heikki Krogerus
0 siblings, 2 replies; 3+ messages in thread
From: Fan Wu @ 2026-09-23 2:46 UTC (permalink / raw)
To: Heikki Krogerus; +Cc: linux-usb, linux-kernel, stable, Fan Wu, Song Li
dp_altmode_remove() cancels dp->work with cancel_work_sync(), but the
typec bus clears alt->ops only after ->remove() has returned, so the
dp_altmode_vdm(), dp_cable_altmode_vdm() and dp_altmode_attention()
callbacks can still call schedule_work(&dp->work) after the cancel. dp
is devm-allocated on the partner altmode device and is freed once the
unbind completes; a re-queued dp_altmode_work() may then run on freed
memory.
Fix this by disabling the work instead of only cancelling it.
disable_work_sync() drains an in-flight dp_altmode_work() and keeps the
work item disabled, so the late schedule_work() calls are rejected. The
work is still drained before the plug reference is dropped.
A later probe initializes a new work item, and the remove path holds no
lock that dp_altmode_work() takes, so waiting cannot deadlock.
This issue was found by an in-house static analysis tool.
Fixes: 0e3bb7d6894d ("usb: typec: Add driver for DisplayPort alternate mode")
Cc: stable@vger.kernel.org # v6.10+
Co-developed-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
---
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index d96ab106a980..f7b3566d4029 100644
@@ -815,7 +815,7 @@
{
struct dp_altmode *dp = typec_altmode_get_drvdata(alt);
- cancel_work_sync(&dp->work);
+ disable_work_sync(&dp->work);
typec_altmode_put_plug(dp->plug_prime);
if (dp->connector_fwnode) {
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed
2026-09-23 2:46 [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed Fan Wu
@ 2026-09-24 7:22 ` Huang Wei
2026-09-28 12:53 ` Heikki Krogerus
1 sibling, 0 replies; 3+ messages in thread
From: Huang Wei @ 2026-09-24 7:22 UTC (permalink / raw)
To: Fan Wu
Cc: Heikki Krogerus, Song Li, linux-usb, linux-kernel, stable, huangwei
Hi Fan,
I checked this over and the race is real - typec_remove() in the typec
bus only clears adev->ops after drv->remove() has returned, and it
even calls typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL) in
between, so dp_altmode_vdm() and friends can definitely re-queue
dp->work after the cancel_work_sync() in dp_altmode_remove(). With dp
being devm-allocated that is a use-after-free waiting to happen.
disable_work_sync() is the right fix here - it drains the work and
rejects the late schedule_work() calls, and since probe always runs
INIT_WORK on a freshly allocated dp there is no risk of the disabled
state leaking into a later bind.
Reviewed-by: Huang Wei <huangwei@kylinos.cn>
Thanks,
Huang Wei
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed
2026-09-23 2:46 [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed Fan Wu
2026-09-24 7:22 ` Huang Wei
@ 2026-09-28 12:53 ` Heikki Krogerus
1 sibling, 0 replies; 3+ messages in thread
From: Heikki Krogerus @ 2026-09-28 12:53 UTC (permalink / raw)
To: Fan Wu; +Cc: linux-usb, linux-kernel, stable, Song Li
On Wed, Sep 23, 2026 at 02:46:37AM +0000, Fan Wu wrote:
> dp_altmode_remove() cancels dp->work with cancel_work_sync(), but the
> typec bus clears alt->ops only after ->remove() has returned, so the
> dp_altmode_vdm(), dp_cable_altmode_vdm() and dp_altmode_attention()
> callbacks can still call schedule_work(&dp->work) after the cancel. dp
> is devm-allocated on the partner altmode device and is freed once the
> unbind completes; a re-queued dp_altmode_work() may then run on freed
> memory.
>
> Fix this by disabling the work instead of only cancelling it.
> disable_work_sync() drains an in-flight dp_altmode_work() and keeps the
> work item disabled, so the late schedule_work() calls are rejected. The
> work is still drained before the plug reference is dropped.
>
> A later probe initializes a new work item, and the remove path holds no
> lock that dp_altmode_work() takes, so waiting cannot deadlock.
>
> This issue was found by an in-house static analysis tool.
>
> Fixes: 0e3bb7d6894d ("usb: typec: Add driver for DisplayPort alternate mode")
> Cc: stable@vger.kernel.org # v6.10+
> Co-developed-by: Song Li <songl@zju.edu.cn>
> Signed-off-by: Song Li <songl@zju.edu.cn>
> Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> index d96ab106a980..f7b3566d4029 100644
> @@ -815,7 +815,7 @@
> {
> struct dp_altmode *dp = typec_altmode_get_drvdata(alt);
>
> - cancel_work_sync(&dp->work);
> + disable_work_sync(&dp->work);
> typec_altmode_put_plug(dp->plug_prime);
>
> if (dp->connector_fwnode) {
--
heikki
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-28 12:53 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-23 2:46 [PATCH] usb: typec: altmodes/displayport: Disable work before dp is freed Fan Wu
2026-09-24 7:22 ` Huang Wei
2026-09-28 12:53 ` Heikki Krogerus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®