This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit b1a1ee593b0c924fb8ec9b7371843f815315f018
Author: chao an <[email protected]>
AuthorDate: Thu Oct 29 14:27:46 2026 +0800

    drivers/usbhost: Bound composite member writes
    
    Composite member allocation is based on the number of interfaces minus the
    interfaces merged by IAD descriptors.  Malformed interface or IAD records
    could make the second descriptor pass write more entries than were
    allocated.
    
    Validate interface and IAD descriptor sizes and ranges in both passes, and
    check the member index before writing to the members array.
    
    Signed-off-by: chao an <[email protected]>
---
 drivers/usbhost/usbhost_composite.c | 50 ++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/usbhost/usbhost_composite.c 
b/drivers/usbhost/usbhost_composite.c
index e8199e04caf..bfbc96518f8 100644
--- a/drivers/usbhost/usbhost_composite.c
+++ b/drivers/usbhost/usbhost_composite.c
@@ -611,6 +611,11 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
       desc = (FAR struct usb_desc_s *)&configdesc[offset];
       int len = desc->len;
 
+      if (len < sizeof(struct usb_desc_s) || len > desclen - offset)
+        {
+          return -EINVAL;
+        }
+
       if (offset + len <= desclen)
         {
           /* Is this an interface descriptor? */
@@ -620,7 +625,10 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
               FAR struct usb_ifdesc_s *ifdesc =
                 (FAR struct usb_ifdesc_s *)desc;
 
-              DEBUGASSERT(ifdesc->ifno < 32);
+              if (len < USB_SIZEOF_IFDESC || ifdesc->ifno >= 32)
+                {
+                  return -EINVAL;
+                }
 
               /* Increment the count of interfaces */
 
@@ -641,13 +649,18 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
                 (FAR struct usb_iaddesc_s *)desc;
               uint32_t mask;
 
+              if (len < USB_SIZEOF_IADDESC || iad->nifs == 0 ||
+                  iad->firstif >= 32 || iad->nifs > 32 - iad->firstif)
+                {
+                  return -EINVAL;
+                }
+
               /* Keep count of the number of interfaces that will be merged */
 
               nmerged += (iad->nifs - 1);
 
               /* Keep track of which interfaces will be merged */
 
-              DEBUGASSERT(iad->firstif + iad->nifs < 32);
               mask      = (1 << iad->nifs) - 1;
               mergeset |= mask << iad->firstif;
             }
@@ -727,6 +740,12 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
       desc = (FAR struct usb_desc_s *)&configdesc[offset];
       int len = desc->len;
 
+      if (len < sizeof(struct usb_desc_s) || len > desclen - offset)
+        {
+          ret = -EINVAL;
+          goto errout_with_members;
+        }
+
       if (offset + len <= desclen)
         {
           /* Is this an interface descriptor? */
@@ -738,9 +757,20 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
 
               /* Was the interface merged via an IAD descriptor? */
 
-              DEBUGASSERT(ifdesc->ifno < 32);
+              if (len < USB_SIZEOF_IFDESC || ifdesc->ifno >= 32)
+                {
+                  ret = -EINVAL;
+                  goto errout_with_members;
+                }
+
               if ((mergeset & (1 << ifdesc->ifno)) == 0)
                 {
+                  if (i >= nclasses)
+                    {
+                      ret = -EINVAL;
+                      goto errout_with_members;
+                    }
+
                   /* No, this interface was not merged.  Save the registry
                    * lookup information from the interface descriptor.
                    */
@@ -772,6 +802,14 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
               FAR struct usb_iaddesc_s *iad =
                 (FAR struct usb_iaddesc_s *)desc;
 
+              if (len < USB_SIZEOF_IADDESC || iad->nifs == 0 ||
+                  iad->firstif >= 32 || iad->nifs > 32 - iad->firstif ||
+                  i >= nclasses)
+                {
+                  ret = -EINVAL;
+                  goto errout_with_members;
+                }
+
               /* Yes.. Save the registry lookup information from the IAD. */
 
               member              = (FAR struct usbhost_member_s *)
@@ -800,6 +838,12 @@ int usbhost_composite(FAR struct usbhost_hubport_s *hport,
 
   DEBUGASSERT(i == nclasses);
 
+  if (i != nclasses)
+    {
+      ret = -EINVAL;
+      goto errout_with_members;
+    }
+
   /* Allocate a temporary buffer in which we can construct a custom
    * configuration descriptor for each member class.
    */

Reply via email to