From 01850da3e4647cd708c16ad3b8ee63b38a6f53b7 Mon Sep 17 00:00:00 2001 From: Lwazi Dube Date: Thu, 11 May 2023 19:13:13 -0400 Subject: [PATCH] usbhost_hub: Prevent crash when the last hub port is used. An off-by-one error caused invalid memory to be accessed when the last port was used. The first entry, at index 0, was never used. The USB standard uses 1-based numbering for hub ports. This number was used to index an array. This change converts the port number to a zero-based port index when the array is accessed. The zero-based value in the port field of the usbhost_hubport_s structure is also converted before printing. For testing, this bug was exposed on a 4 port hub when port 4 was used after changing USBHUB_MAX_PORTS to 4 in hub.h. The bug should also be triggered without changing hub.h if a 7 port hub is available. --- drivers/usbhost/usbhost_hub.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/usbhost/usbhost_hub.c b/drivers/usbhost/usbhost_hub.c index 98f3f52705569..3fcf0395898e0 100644 --- a/drivers/usbhost/usbhost_hub.c +++ b/drivers/usbhost/usbhost_hub.c @@ -93,6 +93,14 @@ #define INTIN_BUFSIZE ((USBHUB_MAX_PORTS + 8) >> 3) +/* Convert 0-based index to port number. */ + +#define PORT_NO(x) ((x) + 1) + +/* Convert port number to 0-based index. */ + +#define PORT_INDX(x) ((x) - 1) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -223,7 +231,7 @@ static struct usbhost_registry_s g_hub = static void usbhost_hport_deactivate(FAR struct usbhost_hubport_s *hport) { uinfo("Deactivating: %s port %d\n", - ROOTHUB(hport) ? "Root" : "Hub", hport->port); + ROOTHUB(hport) ? "Root" : "Hub", PORT_NO(hport->port)); /* Don't free the control pipe of root hub ports! */ @@ -268,7 +276,7 @@ static int usbhost_hport_activate(FAR struct usbhost_hubport_s *hport) struct usbhost_epdesc_s epdesc; int ret; - uinfo("Activating port %d\n", hport->port); + uinfo("Activating port %d\n", PORT_NO(hport->port)); epdesc.hport = hport; epdesc.addr = 0; @@ -907,7 +915,7 @@ static void usbhost_hub_event(FAR void *arg) DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); } - connport = &priv->hport[port]; + connport = &priv->hport[PORT_INDX(port)]; if ((status & USBHUB_PORT_STAT_HIGH_SPEED) != 0) { connport->speed = USB_SPEED_HIGH; @@ -961,7 +969,7 @@ static void usbhost_hub_event(FAR void *arg) /* Free any devices classes connect on this hub port */ - connport = &priv->hport[port]; + connport = &priv->hport[PORT_INDX(port)]; if (connport->devclass != NULL) { CLASS_DISCONNECTED(connport->devclass); @@ -1071,7 +1079,7 @@ static void usbhost_disconnect_event(FAR void *arg) priv = &((FAR struct usbhost_hubclass_s *)hubclass)->hubpriv; hport = hubclass->hport; - uinfo("Destroying hub on port %d\n", hport->port); + uinfo("Destroying hub on port %d\n", PORT_NO(hport->port)); /* Set an indication to any users of the device that the device is no * longer available.