]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
MdeModulePkg/UsbBus: Reject descriptor whose length is bad
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbDesc.c
index 529b136188ace95104d6dfb9e069e0c9b202c165..9fc6422ab17ca84924df5f850dc91b23800e1238 100644 (file)
@@ -2,7 +2,7 @@
 \r
     Manage Usb Descriptor List\r
 \r
-Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -142,15 +142,15 @@ UsbFreeDevDesc (
 VOID *\r
 UsbCreateDesc (\r
   IN  UINT8               *DescBuf,\r
-  IN  INTN                Len,\r
+  IN  UINTN               Len,\r
   IN  UINT8               Type,\r
-  OUT INTN                *Consumed\r
+  OUT UINTN               *Consumed\r
   )\r
 {\r
   USB_DESC_HEAD           *Head;\r
-  INTN                    DescLen;\r
-  INTN                    CtrlLen;\r
-  INTN                    Offset;\r
+  UINTN                   DescLen;\r
+  UINTN                   CtrlLen;\r
+  UINTN                   Offset;\r
   VOID                    *Desc;\r
 \r
   DescLen   = 0;\r
@@ -177,6 +177,18 @@ UsbCreateDesc (
     DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
     CtrlLen = sizeof (USB_ENDPOINT_DESC);\r
     break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Total length is too small that cannot hold the single descriptor header plus data. \r
+  //\r
+  if (Len <= sizeof (USB_DESC_HEAD)) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, total length = %d!\n", Len));\r
+    return NULL;\r
   }\r
 \r
   //\r
@@ -184,16 +196,43 @@ UsbCreateDesc (
   // format. Skip the descriptor that isn't of this Type\r
   //\r
   Offset = 0;\r
-  Head   = (USB_DESC_HEAD*)DescBuf;\r
+  Head   = (USB_DESC_HEAD *)DescBuf;\r
+  while (Offset < Len - sizeof (USB_DESC_HEAD)) {\r
+    //\r
+    // Above condition make sure Head->Len and Head->Type are safe to access\r
+    //\r
+    Head = (USB_DESC_HEAD *)&DescBuf[Offset];\r
+\r
+    if (Head->Len == 0) {\r
+      DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Head->Len = 0!\n"));\r
+      return NULL;\r
+    }\r
+\r
+    //\r
+    // Make sure no overflow when adding Head->Len to Offset.\r
+    //\r
+    if (Head->Len > MAX_UINTN - Offset) {\r
+      DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
+      return NULL;\r
+    }\r
 \r
-  while ((Offset < Len) && (Head->Type != Type)) {\r
     Offset += Head->Len;\r
-    Head    = (USB_DESC_HEAD*)(DescBuf + Offset);\r
+\r
+    if (Head->Type == Type) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Head->Len is invalid resulting data beyond boundary, or\r
+  // Descriptor cannot be found: No such type.\r
+  //\r
+  if (Len < Offset) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Len));\r
   }\r
 \r
-  if ((Len <= Offset)      || (Len < Offset + DescLen) ||\r
-      (Head->Type != Type) || (Head->Len != DescLen)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));\r
+  if ((Head->Type != Type) || (Head->Len < DescLen)) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
     return NULL;\r
   }\r
 \r
@@ -204,7 +243,7 @@ UsbCreateDesc (
 \r
   CopyMem (Desc, Head, (UINTN) DescLen);\r
 \r
-  *Consumed = Offset + Head->Len;\r
+  *Consumed = Offset;\r
 \r
   return Desc;\r
 }\r
@@ -223,16 +262,16 @@ UsbCreateDesc (
 USB_INTERFACE_SETTING *\r
 UsbParseInterfaceDesc (\r
   IN  UINT8               *DescBuf,\r
-  IN  INTN                Len,\r
-  OUT INTN                *Consumed\r
+  IN  UINTN               Len,\r
+  OUT UINTN               *Consumed\r
   )\r
 {\r
   USB_INTERFACE_SETTING   *Setting;\r
   USB_ENDPOINT_DESC       *Ep;\r
   UINTN                   Index;\r
   UINTN                   NumEp;\r
-  INTN                    Used;\r
-  INTN                    Offset;\r
+  UINTN                   Used;\r
+  UINTN                   Offset;\r
 \r
   *Consumed = 0;\r
   Setting   = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);\r
@@ -265,7 +304,7 @@ UsbParseInterfaceDesc (
   //\r
   // Create the endpoints for this interface\r
   //\r
-  for (Index = 0; Index < NumEp; Index++) {\r
+  for (Index = 0; (Index < NumEp) && (Offset < Len); Index++) {\r
     Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);\r
 \r
     if (Ep == NULL) {\r
@@ -300,7 +339,7 @@ ON_ERROR:
 USB_CONFIG_DESC *\r
 UsbParseConfigDesc (\r
   IN UINT8                *DescBuf,\r
-  IN INTN                 Len\r
+  IN UINTN                Len\r
   )\r
 {\r
   USB_CONFIG_DESC         *Config;\r
@@ -308,7 +347,7 @@ UsbParseConfigDesc (
   USB_INTERFACE_DESC      *Interface;\r
   UINTN                   Index;\r
   UINTN                   NumIf;\r
-  INTN                    Consumed;\r
+  UINTN                   Consumed;\r
 \r
   ASSERT (DescBuf != NULL);\r
 \r
@@ -353,15 +392,15 @@ UsbParseConfigDesc (
   Len     -= Consumed;\r
 \r
   //\r
-  // Make allowances for devices that return extra data at the \r
+  // Make allowances for devices that return extra data at the\r
   // end of their config descriptors\r
   //\r
   while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {\r
     Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);\r
 \r
     if (Setting == NULL) {\r
-      DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));\r
-      goto ON_ERROR;\r
+      DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));\r
+      break;\r
 \r
     } else if (Setting->Desc.InterfaceNumber >= NumIf) {\r
       DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));\r
@@ -531,7 +570,7 @@ UsbGetMaxPacketSize0 (
     Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);\r
 \r
     if (!EFI_ERROR (Status)) {\r
-      if ((DevDesc.BcdUSB == 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {\r
+      if ((DevDesc.BcdUSB >= 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {\r
         UsbDev->MaxPacket0 = 1 << 9;\r
         return EFI_SUCCESS;\r
       }\r
@@ -681,7 +720,7 @@ UsbBuildLangTable (
 \r
   Max   = (Desc->Length - 2) / 2;\r
   Max   = MIN(Max, USB_MAX_LANG_ID);\r
-  \r
+\r
   Point = Desc->String;\r
   for (Index = 0; Index < Max; Index++) {\r
     UsbDev->LangId[Index] = *Point;\r
@@ -733,6 +772,13 @@ UsbGetOneConfig (
 \r
   DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));\r
 \r
+  //\r
+  // Reject if TotalLength even cannot cover itself.\r
+  //\r
+  if (Desc.TotalLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (Desc.TotalLength)) {\r
+    return NULL;\r
+  }\r
+\r
   Buf = AllocateZeroPool (Desc.TotalLength);\r
 \r
   if (Buf == NULL) {\r
@@ -786,10 +832,13 @@ UsbBuildDescTable (
     return Status;\r
   }\r
 \r
-  DevDesc          = UsbDev->DevDesc;\r
-  NumConfig        = DevDesc->Desc.NumConfigurations;\r
-  DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));\r
+  DevDesc   = UsbDev->DevDesc;\r
+  NumConfig = DevDesc->Desc.NumConfigurations;\r
+  if (NumConfig == 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 \r
+  DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));\r
   if (DevDesc->Configs == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -844,7 +893,7 @@ UsbBuildDescTable (
   Status = UsbBuildLangTable (UsbDev);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: get language ID table %r\n", Status));\r
+    DEBUG (( EFI_D_INFO, "UsbBuildDescTable: get language ID table %r\n", Status));\r
   }\r
 \r
   return EFI_SUCCESS;\r