From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Fan Wu <fanwu01@zju.edu.cn>
Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] usb: typec: ucsi: acpi: Fix use-after-free of ucsi on remove
Date: Tue, 21 Jul 2026 11:27:48 +0300 [thread overview]
Message-ID: <al8thH8aWmMOUuAZ@kuha> (raw)
In-Reply-To: <20260718021142.3146566-1-fanwu01@zju.edu.cn>
On Sat, Jul 18, 2026 at 02:11:42AM +0000, Fan Wu wrote:
> The ACPI notify handler ucsi_acpi_notify() calls
> ua->ucsi->ops->read_cci() and ucsi_notify_common(), both of which
> dereference ua->ucsi with no NULL guard. In ucsi_acpi_remove(),
> ucsi_destroy() frees ua->ucsi (kfree) before
> acpi_remove_notify_handler() is called, so a notify dispatch already
> in flight on another CPU may access the freed object after
> ucsi_destroy().
>
> CPU 0 (remove) | CPU 1 (ACPI notify wq)
> ucsi_destroy(ua->ucsi) | ucsi_acpi_notify(ua)
> kfree(ucsi) // FREE | ua->ucsi->ops->read_cci(...) // USE
>
> Move acpi_remove_notify_handler() before ucsi_destroy() in the remove
> path. It is kept after ucsi_unregister(): ucsi_unregister() cancels
> connector work whose handler issues GET_CONNECTOR_STATUS through
> ucsi_send_command_common(), which waits for a completion that is
> signalled from the notify path, so the handler must stay registered
> until that work has been cancelled.
>
> acpi_remove_notify_handler() drains in-flight notify dispatches before
> returning: it calls acpi_os_wait_events_complete(), which flushes
> kacpi_notify_wq. Because ACPI device-notify dispatch is deferred to that
> same workqueue (acpi_os_execute(OSL_NOTIFY_HANDLER, ...)), the flush
> guarantees any queued or running ucsi_acpi_notify() has returned before
> the function returns, so ucsi_destroy() frees an object no handler can
> reach. This mirrors commit 1f0bdc2884b6 ("usb: typec: ucsi: ccg: Fix
> use-after-free of ucsi on remove"), which moved free_irq() before
> ucsi_destroy() with the same ordering rationale.
>
> The probe error paths already order acpi_remove_notify_handler() (or
> omit it, when install failed) before ucsi_destroy(), and are unchanged.
>
> This issue was found by an in-house static analysis tool.
>
> Fixes: f56de278e8ec ("usb: typec: ucsi: acpi: Move to the new API")
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-5.6
> Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
> ---
> drivers/usb/typec/ucsi/ucsi_acpi.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
> index 60b12961e..1d56eadc9 100644
> --- a/drivers/usb/typec/ucsi/ucsi_acpi.c
> +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
> @@ -257,10 +257,10 @@ static void ucsi_acpi_remove(struct platform_device *pdev)
> struct ucsi_acpi *ua = platform_get_drvdata(pdev);
>
> ucsi_unregister(ua->ucsi);
> - ucsi_destroy(ua->ucsi);
>
> acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_DEVICE_NOTIFY,
> ucsi_acpi_notify);
> + ucsi_destroy(ua->ucsi);
> }
I don't think this is enough. You now create a window where the ucsi
is unregistered, but you can still call ucsi_notify_common(),
ucsi_connector_change(), etc. So you'll end up with even more problems.
If I understood correctly the long explanation (I'm guessing generated
by gpt-5.6), the problem is that ucsi_unregister() disables the
notification, but it does not flush them. My proposal is that you fix
that by setting the ua->ucsi to NULL after calling ucsi_unregister()
and then always check it in ucsi_acpi_notify(). You probable also need
a lock for that.
thanks,
--
heikki
next prev parent reply other threads:[~2026-07-21 8:27 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-18 2:11 [PATCH] usb: typec: ucsi: acpi: Fix use-after-free of ucsi on remove Fan Wu
2026-07-21 8:27 ` Heikki Krogerus [this message]
2026-07-21 14:47 ` Fan Wu
2026-07-22 15:51 ` Heikki Krogerus
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=al8thH8aWmMOUuAZ@kuha \
--to=heikki.krogerus@linux.intel.com \
--cc=fanwu01@zju.edu.cn \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stable@vger.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.