]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
MdeModulePkg: Fix use-after-free error in InstallConfigurationTable()
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / InstallConfigurationTable.c
old mode 100644 (file)
new mode 100755 (executable)
index 26db2fb..dcdeb7f
@@ -1,94 +1,48 @@
-/** @file \r
-\r
+/** @file\r
   UEFI Miscellaneous boot Services InstallConfigurationTable service\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation                                                         \r
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+Copyright (c) 2006 - 2017, 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 **/\r
 \r
-#include <DxeMain.h>\r
+#include "DxeMain.h"\r
 \r
 #define CONFIG_TABLE_SIZE_INCREASED 0x10\r
 \r
 UINTN mSystemTableAllocateSize = 0;\r
 \r
+/**\r
+  Boot Service called to add, modify, or remove a system configuration table from\r
+  the EFI System Table.\r
 \r
-EFI_STATUS\r
-CoreGetConfigTable (\r
-  IN EFI_GUID *Guid,\r
-  OUT VOID    **Table\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Find a config table by name in system table's ConfigurationTable.\r
-\r
-Arguments:\r
-\r
-  Guid        - The table name to look for\r
-  \r
-  Table       - Pointer of the config table\r
-\r
-Returns: \r
-\r
-  EFI_NOT_FOUND       - Could not find the table in system table's ConfigurationTable.\r
-  \r
-  EFI_SUCCESS         - Table successfully found.\r
-\r
---*/\r
-{\r
-  UINTN Index;\r
-\r
-  for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) {\r
-    if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) {\r
-      *Table = gDxeCoreST->ConfigurationTable[Index].VendorTable;\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
+  @param  Guid           Pointer to the GUID for the entry to add, update, or\r
+                         remove\r
+  @param  Table          Pointer to the configuration table for the entry to add,\r
+                         update, or remove, may be NULL.\r
 \r
+  @return EFI_SUCCESS               Guid, Table pair added, updated, or removed.\r
+  @return EFI_INVALID_PARAMETER     Input GUID is NULL.\r
+  @return EFI_NOT_FOUND             Attempted to delete non-existant entry\r
+  @return EFI_OUT_OF_RESOURCES      Not enough memory available\r
 \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreInstallConfigurationTable (\r
   IN EFI_GUID *Guid,\r
   IN VOID     *Table\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Boot Service called to add, modify, or remove a system configuration table from \r
-  the EFI System Table.\r
-\r
-Arguments:\r
-\r
-  Guid     -  Pointer to the GUID for the entry to add, update, or remove\r
-  Table    -  Pointer to the configuration table for the entry to add, update, or\r
-              remove, may be NULL.\r
-\r
-Returns:\r
-  \r
-  EFI_SUCCESS               Guid, Table pair added, updated, or removed.\r
-  EFI_INVALID_PARAMETER     Input GUID not valid.\r
-  EFI_NOT_FOUND             Attempted to delete non-existant entry\r
-  EFI_OUT_OF_RESOURCES      Not enough memory available\r
-\r
---*/\r
 {\r
   UINTN                   Index;\r
   EFI_CONFIGURATION_TABLE *EfiConfigurationTable;\r
+  EFI_CONFIGURATION_TABLE *OldTable;\r
 \r
   //\r
   // If Guid is NULL, then this operation cannot be performed\r
@@ -115,7 +69,7 @@ Returns:
     if (Table != NULL) {\r
       //\r
       // If Table is not NULL, then this is a modify operation.\r
-      // Modify the table enty and return.\r
+      // Modify the table entry and return.\r
       //\r
       gDxeCoreST->ConfigurationTable[Index].VendorTable = Table;\r
 \r
@@ -162,7 +116,7 @@ Returns:
       // Allocate a table with one additional entry.\r
       //\r
       mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));\r
-      EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize);\r
+      EfiConfigurationTable = AllocateRuntimePool (mSystemTableAllocateSize);\r
       if (EfiConfigurationTable == NULL) {\r
         //\r
         // If a new table could not be allocated, then return an error.\r
@@ -181,21 +135,36 @@ Returns:
           );\r
 \r
         //\r
-        // Free Old Table\r
+        // Record the old table pointer.\r
         //\r
-        CoreFreePool (gDxeCoreST->ConfigurationTable);\r
-      }\r
+        OldTable = gDxeCoreST->ConfigurationTable;\r
 \r
-      //\r
-      // Update System Table\r
-      //\r
-      gDxeCoreST->ConfigurationTable = EfiConfigurationTable;\r
+        //\r
+        // As the CoreInstallConfigurationTable() may be re-entered by CoreFreePool()\r
+        // in its calling stack, updating System table to the new table pointer must\r
+        // be done before calling CoreFreePool() to free the old table.\r
+        // It can make sure the gDxeCoreST->ConfigurationTable point to the new table\r
+        // and avoid the errors of use-after-free to the old table by the reenter of\r
+        // CoreInstallConfigurationTable() in CoreFreePool()'s calling stack.\r
+        //\r
+        gDxeCoreST->ConfigurationTable = EfiConfigurationTable;\r
+\r
+        //\r
+        // Free the old table after updating System Table to the new table pointer.\r
+        //\r
+        CoreFreePool (OldTable);\r
+      } else {\r
+        //\r
+        // Update System Table\r
+        //\r
+        gDxeCoreST->ConfigurationTable = EfiConfigurationTable;\r
+      }\r
     }\r
 \r
     //\r
     // Fill in the new entry\r
     //\r
-    CopyMem ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid, sizeof (EFI_GUID));\r
+    CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid);\r
     EfiConfigurationTable[Index].VendorTable  = Table;\r
 \r
     //\r