]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg/Variable: [CVE-2017-5753] Fix bounds check bypass
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmm.c
index fb16af31b1a999863077ebe81dd527e124336124..6dc19c24dbc23276369a2da7bee091af93b17500 100644 (file)
@@ -14,7 +14,7 @@
   VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2016, 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
@@ -35,7 +35,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/SmmMemLib.h>\r
 \r
 #include <Guid/SmmVariableCommon.h>\r
-#include <Guid/ZeroGuid.h>\r
 #include "Variable.h"\r
 \r
 extern VARIABLE_INFO_ENTRY                           *gVariableInfo;\r
@@ -200,7 +199,7 @@ ReleaseLockOnlyAtBootTime (
 }\r
 \r
 /**\r
-  Retrive the SMM Fault Tolerent Write protocol interface.\r
+  Retrieve the SMM Fault Tolerent Write protocol interface.\r
 \r
   @param[out] FtwProtocol       The interface of SMM Ftw protocol\r
 \r
@@ -229,7 +228,7 @@ GetFtwProtocol (
 \r
 \r
 /**\r
-  Retrive the SMM FVB protocol interface by HANDLE.\r
+  Retrieve the SMM FVB protocol interface by HANDLE.\r
 \r
   @param[in]  FvBlockHandle     The handle of SMM FVB protocol that provides services for\r
                                 reading, writing, and erasing the target block.\r
@@ -350,9 +349,10 @@ SmmVariableGetStatistics (
   )\r
 {\r
   VARIABLE_INFO_ENTRY                                  *VariableInfo;\r
-  UINTN                                                NameLength;\r
+  UINTN                                                NameSize;\r
   UINTN                                                StatisticsInfoSize;\r
   CHAR16                                               *InfoName;\r
+  UINTN                                                InfoNameMaxSize;\r
   EFI_GUID                                             VendorGuid;\r
 \r
   if (InfoEntry == NULL) {\r
@@ -364,21 +364,28 @@ SmmVariableGetStatistics (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY);\r
   if (*InfoSize < StatisticsInfoSize) {\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
   InfoName = (CHAR16 *)(InfoEntry + 1);\r
+  InfoNameMaxSize = (*InfoSize - sizeof (VARIABLE_INFO_ENTRY));\r
 \r
   CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);\r
 \r
-  if (CompareGuid (&VendorGuid, &gZeroGuid)) {\r
+  if (IsZeroGuid (&VendorGuid)) {\r
     //\r
     // Return the first variable info\r
     //\r
+    NameSize = StrSize (VariableInfo->Name);\r
+    StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
+    if (*InfoSize < StatisticsInfoSize) {\r
+      *InfoSize = StatisticsInfoSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
     CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
-    CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+    CopyMem (InfoName, VariableInfo->Name, NameSize);\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_SUCCESS;\r
   }\r
@@ -388,9 +395,9 @@ SmmVariableGetStatistics (
   //\r
   while (VariableInfo != NULL) {\r
     if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {\r
-      NameLength = StrSize (VariableInfo->Name);\r
-      if (NameLength == StrSize (InfoName)) {\r
-        if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {\r
+      NameSize = StrSize (VariableInfo->Name);\r
+      if (NameSize <= InfoNameMaxSize) {\r
+        if (CompareMem (VariableInfo->Name, InfoName, NameSize) == 0) {\r
           //\r
           // Find the match one\r
           //\r
@@ -410,14 +417,15 @@ SmmVariableGetStatistics (
   //\r
   // Output the new variable info\r
   //\r
-  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+  NameSize = StrSize (VariableInfo->Name);\r
+  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
   if (*InfoSize < StatisticsInfoSize) {\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
   CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
-  CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+  CopyMem (InfoName, VariableInfo->Name, NameSize);\r
   *InfoSize = StatisticsInfoSize;\r
 \r
   return EFI_SUCCESS;\r
@@ -529,6 +537,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The MemoryLoadFence() call here is to ensure the previous range/content\r
+      // checks for the CommBuffer have been completed before the subsequent\r
+      // consumption of the CommBuffer content.\r
+      //\r
+      MemoryLoadFence ();\r
       if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -623,6 +637,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The MemoryLoadFence() call here is to ensure the previous range/content\r
+      // checks for the CommBuffer have been completed before the subsequent\r
+      // consumption of the CommBuffer content.\r
+      //\r
+      MemoryLoadFence ();\r
       if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -671,6 +691,7 @@ SmmVariableHandler (
         break;\r
       }\r
       if (!mEndOfDxe) {\r
+        MorLockInitAtEndOfDxe ();\r
         mEndOfDxe = TRUE;\r
         VarCheckLibInitializeAtEndOfDxe (NULL);\r
         //\r
@@ -696,11 +717,10 @@ SmmVariableHandler (
       // It is covered by previous CommBuffer check\r
       //\r
 \r
-      if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {\r
-        DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));\r
-        Status = EFI_ACCESS_DENIED;\r
-        goto EXIT;\r
-      }\r
+      //\r
+      // Do not need to check CommBufferSize buffer as it should point to SMRAM\r
+      // that was used by SMM core to cache CommSize from SmmCommunication protocol.\r
+      //\r
 \r
       Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
       *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
@@ -758,6 +778,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The MemoryLoadFence() call here is to ensure the previous range/content\r
+      // checks for the CommBuffer have been completed before the subsequent\r
+      // consumption of the CommBuffer content.\r
+      //\r
+      MemoryLoadFence ();\r
       if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -804,6 +830,7 @@ SmmEndOfDxeCallback (
   )\r
 {\r
   DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+  MorLockInitAtEndOfDxe ();\r
   mEndOfDxe = TRUE;\r
   VarCheckLibInitializeAtEndOfDxe (NULL);\r
   //\r
@@ -946,7 +973,7 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +\r
+  mVariableBufferPayloadSize = GetMaxVariableSize () +\r
                                OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
 \r
   Status = gSmst->SmmAllocatePool (\r