]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: typec: ucsi: Fix NULL pointer access
authorAndrei Kuchynski <akuchynski@chromium.org>
Wed, 5 Mar 2025 11:17:39 +0000 (11:17 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 Apr 2025 08:05:46 +0000 (10:05 +0200)
commit b13abcb7ddd8d38de769486db5bd917537b32ab1 upstream.

Resources should be released only after all threads that utilize them
have been destroyed.
This commit ensures that resources are not released prematurely by waiting
for the associated workqueue to complete before deallocating them.

Cc: stable <stable@kernel.org>
Fixes: b9aa02ca39a4 ("usb: typec: ucsi: Add polling mechanism for partner tasks like alt mode checking")
Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250305111739.1489003-2-akuchynski@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/ucsi/ucsi.c

index 9c82dc94da813e75565a47e91479d5896dc89749..2adf5fdc0c56393e09bc7ad67b4856e4a81c55cb 100644 (file)
@@ -1313,11 +1313,11 @@ static int ucsi_init(struct ucsi *ucsi)
 
 err_unregister:
        for (con = connector; con->port; con++) {
+               if (con->wq)
+                       destroy_workqueue(con->wq);
                ucsi_unregister_partner(con);
                ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
                ucsi_unregister_port_psy(con);
-               if (con->wq)
-                       destroy_workqueue(con->wq);
                typec_unregister_port(con->port);
                con->port = NULL;
        }
@@ -1479,10 +1479,6 @@ void ucsi_unregister(struct ucsi *ucsi)
 
        for (i = 0; i < ucsi->cap.num_connectors; i++) {
                cancel_work_sync(&ucsi->connector[i].work);
-               ucsi_unregister_partner(&ucsi->connector[i]);
-               ucsi_unregister_altmodes(&ucsi->connector[i],
-                                        UCSI_RECIPIENT_CON);
-               ucsi_unregister_port_psy(&ucsi->connector[i]);
 
                if (ucsi->connector[i].wq) {
                        struct ucsi_work *uwork;
@@ -1497,6 +1493,11 @@ void ucsi_unregister(struct ucsi *ucsi)
                        mutex_unlock(&ucsi->connector[i].lock);
                        destroy_workqueue(ucsi->connector[i].wq);
                }
+
+               ucsi_unregister_partner(&ucsi->connector[i]);
+               ucsi_unregister_altmodes(&ucsi->connector[i],
+                                        UCSI_RECIPIENT_CON);
+               ucsi_unregister_port_psy(&ucsi->connector[i]);
                typec_unregister_port(ucsi->connector[i].port);
        }