]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Apr 2023 13:42:01 +0000 (15:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Apr 2023 13:42:01 +0000 (15:42 +0200)
added patches:
usb-ucsi-fix-ucsi-connector-race.patch

queue-6.1/series
queue-6.1/usb-ucsi-fix-ucsi-connector-race.patch [new file with mode: 0644]

index b152aaa6a4dae4b44e97b9ebd6deba99754788e9..a4ce154a95644c38d61df749c4e0afe27001d9a5 100644 (file)
@@ -175,3 +175,4 @@ selftests-bpf-test-btf-dump-for-struct-with-padding-.patch
 libbpf-fix-btf-to-c-converter-s-padding-logic.patch
 selftests-bpf-add-few-corner-cases-to-test-padding-h.patch
 libbpf-fix-btf_dump-s-packed-struct-determination.patch
+usb-ucsi-fix-ucsi-connector-race.patch
diff --git a/queue-6.1/usb-ucsi-fix-ucsi-connector-race.patch b/queue-6.1/usb-ucsi-fix-ucsi-connector-race.patch
new file mode 100644 (file)
index 0000000..022b6bd
--- /dev/null
@@ -0,0 +1,112 @@
+From 0482c34ec6f8557e06cd0f8e2d0e20e8ede6a22c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 8 Mar 2023 16:42:43 +0100
+Subject: usb: ucsi: Fix ucsi->connector race
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 0482c34ec6f8557e06cd0f8e2d0e20e8ede6a22c upstream.
+
+ucsi_init() which runs from a workqueue sets ucsi->connector and
+on an error will clear it again.
+
+ucsi->connector gets dereferenced by ucsi_resume(), this checks for
+ucsi->connector being NULL in case ucsi_init() has not finished yet;
+or in case ucsi_init() has failed.
+
+ucsi_init() setting ucsi->connector and then clearing it again on
+an error creates a race where the check in ucsi_resume() may pass,
+only to have ucsi->connector free-ed underneath it when ucsi_init()
+hits an error.
+
+Fix this race by making ucsi_init() store the connector array in
+a local variable and only assign it to ucsi->connector on success.
+
+Fixes: bdc62f2bae8f ("usb: typec: ucsi: Simplified registration and I/O API")
+Cc: stable@vger.kernel.org
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20230308154244.722337-3-hdegoede@redhat.com
+Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |   22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -1039,9 +1039,8 @@ static struct fwnode_handle *ucsi_find_f
+       return NULL;
+ }
+-static int ucsi_register_port(struct ucsi *ucsi, int index)
++static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
+ {
+-      struct ucsi_connector *con = &ucsi->connector[index];
+       struct typec_capability *cap = &con->typec_cap;
+       enum typec_accessory *accessory = cap->accessory;
+       enum usb_role u_role = USB_ROLE_NONE;
+@@ -1062,7 +1061,6 @@ static int ucsi_register_port(struct ucs
+       init_completion(&con->complete);
+       mutex_init(&con->lock);
+       INIT_LIST_HEAD(&con->partner_tasks);
+-      con->num = index + 1;
+       con->ucsi = ucsi;
+       cap->fwnode = ucsi_find_fwnode(con);
+@@ -1204,7 +1202,7 @@ out_unlock:
+  */
+ static int ucsi_init(struct ucsi *ucsi)
+ {
+-      struct ucsi_connector *con;
++      struct ucsi_connector *con, *connector;
+       u64 command, ntfy;
+       int ret;
+       int i;
+@@ -1235,16 +1233,16 @@ static int ucsi_init(struct ucsi *ucsi)
+       }
+       /* Allocate the connectors. Released in ucsi_unregister() */
+-      ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
+-                                sizeof(*ucsi->connector), GFP_KERNEL);
+-      if (!ucsi->connector) {
++      connector = kcalloc(ucsi->cap.num_connectors + 1, sizeof(*connector), GFP_KERNEL);
++      if (!connector) {
+               ret = -ENOMEM;
+               goto err_reset;
+       }
+       /* Register all connectors */
+       for (i = 0; i < ucsi->cap.num_connectors; i++) {
+-              ret = ucsi_register_port(ucsi, i);
++              connector[i].num = i + 1;
++              ret = ucsi_register_port(ucsi, &connector[i]);
+               if (ret)
+                       goto err_unregister;
+       }
+@@ -1256,11 +1254,12 @@ static int ucsi_init(struct ucsi *ucsi)
+       if (ret < 0)
+               goto err_unregister;
++      ucsi->connector = connector;
+       ucsi->ntfy = ntfy;
+       return 0;
+ err_unregister:
+-      for (con = ucsi->connector; con->port; con++) {
++      for (con = connector; con->port; con++) {
+               ucsi_unregister_partner(con);
+               ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
+               ucsi_unregister_port_psy(con);
+@@ -1269,10 +1268,7 @@ err_unregister:
+               typec_unregister_port(con->port);
+               con->port = NULL;
+       }
+-
+-      kfree(ucsi->connector);
+-      ucsi->connector = NULL;
+-
++      kfree(connector);
+ err_reset:
+       memset(&ucsi->cap, 0, sizeof(ucsi->cap));
+       ucsi_reset_ppm(ucsi);