From: Greg Kroah-Hartman Date: Mon, 3 Apr 2023 13:42:01 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v4.14.312~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1ee74e16d22ac5d117ffd37be9b8cc5ec04104f4;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: usb-ucsi-fix-ucsi-connector-race.patch --- diff --git a/queue-6.1/series b/queue-6.1/series index b152aaa6a4d..a4ce154a956 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 00000000000..022b6bd5fda --- /dev/null +++ b/queue-6.1/usb-ucsi-fix-ucsi-connector-race.patch @@ -0,0 +1,112 @@ +From 0482c34ec6f8557e06cd0f8e2d0e20e8ede6a22c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 8 Mar 2023 16:42:43 +0100 +Subject: usb: ucsi: Fix ucsi->connector race + +From: Hans de Goede + +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 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20230308154244.722337-3-hdegoede@redhat.com +Signed-off-by: Joakim Tjernlund +Signed-off-by: Greg Kroah-Hartman +--- + 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);