]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
index 1f9c3b48360158be8b4bf499f0a108d0f63f1a5e..28d5180e011e51dca7614ec0174e3adcb6998bec 100644 (file)
@@ -1,6 +1,15 @@
 /** @file\r
+  LockBox SMM driver.\r
 \r
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Caution: This module requires additional review when modified.\r
+  This driver will have external input - communicate buffer in SMM mode.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()\r
+  will receive untrusted input and do basic validation.\r
+\r
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -21,49 +30,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/SmmMemLib.h>\r
 #include <Library/LockBoxLib.h>\r
+\r
 #include <Protocol/SmmReadyToLock.h>\r
 #include <Protocol/SmmCommunication.h>\r
-#include <Protocol/SmmAccess2.h>\r
 #include <Protocol/LockBox.h>\r
 #include <Guid/SmmLockBox.h>\r
 \r
 BOOLEAN              mLocked = FALSE;\r
 \r
-EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
-UINTN                mSmramRangeCount;\r
-\r
-/**\r
-  This function check if the address is in SMRAM.\r
-\r
-  @param Buffer  the buffer address to be checked.\r
-  @param Length  the buffer length to be checked.\r
-\r
-  @retval TRUE  this address is in SMRAM.\r
-  @retval FALSE this address is NOT in SMRAM.\r
-**/\r
-BOOLEAN\r
-IsAddressInSmram (\r
-  IN EFI_PHYSICAL_ADDRESS  Buffer,\r
-  IN UINT64                Length\r
-  )\r
-{\r
-  UINTN  Index;\r
-\r
-  for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
-    if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
-        ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
-      return TRUE;\r
-    }\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
 /**\r
   Dispatch function for SMM lock box save.\r
 \r
-  @param LockBoxParameterSave  parameter of lock box save \r
+  Caution: This function may receive untrusted input.\r
+  Restore buffer and length are external input, so this function will validate\r
+  it is in SMRAM.\r
+\r
+  @param LockBoxParameterSave  parameter of lock box save\r
 **/\r
 VOID\r
 SmmLockBoxSave (\r
@@ -71,6 +55,7 @@ SmmLockBoxSave (
   )\r
 {\r
   EFI_STATUS                  Status;\r
+  EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave;\r
 \r
   //\r
   // Sanity check\r
@@ -81,13 +66,24 @@ SmmLockBoxSave (
     return ;\r
   }\r
 \r
+  CopyMem (&TempLockBoxParameterSave, LockBoxParameterSave, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE));\r
+\r
+  //\r
+  // Sanity check\r
+  //\r
+  if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterSave.Buffer, (UINTN)TempLockBoxParameterSave.Length)) {\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));\r
+    LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
+    return ;\r
+  }\r
+\r
   //\r
   // Save data\r
   //\r
   Status = SaveLockBox (\r
-             &LockBoxParameterSave->Guid,\r
-             (VOID *)(UINTN)LockBoxParameterSave->Buffer,\r
-             (UINTN)LockBoxParameterSave->Length\r
+             &TempLockBoxParameterSave.Guid,\r
+             (VOID *)(UINTN)TempLockBoxParameterSave.Buffer,\r
+             (UINTN)TempLockBoxParameterSave.Length\r
              );\r
   LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;\r
   return ;\r
@@ -104,6 +100,7 @@ SmmLockBoxSetAttributes (
   )\r
 {\r
   EFI_STATUS                    Status;\r
+  EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes;\r
 \r
   //\r
   // Sanity check\r
@@ -114,12 +111,14 @@ SmmLockBoxSetAttributes (
     return ;\r
   }\r
 \r
+  CopyMem (&TempLockBoxParameterSetAttributes, LockBoxParameterSetAttributes, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES));\r
+\r
   //\r
   // Update data\r
   //\r
   Status = SetLockBoxAttributes (\r
-             &LockBoxParameterSetAttributes->Guid,\r
-             LockBoxParameterSetAttributes->Attributes\r
+             &TempLockBoxParameterSetAttributes.Guid,\r
+             TempLockBoxParameterSetAttributes.Attributes\r
              );\r
   LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;\r
   return ;\r
@@ -128,7 +127,11 @@ SmmLockBoxSetAttributes (
 /**\r
   Dispatch function for SMM lock box update.\r
 \r
-  @param LockBoxParameterUpdate  parameter of lock box update \r
+  Caution: This function may receive untrusted input.\r
+  Restore buffer and length are external input, so this function will validate\r
+  it is in SMRAM.\r
+\r
+  @param LockBoxParameterUpdate  parameter of lock box update\r
 **/\r
 VOID\r
 SmmLockBoxUpdate (\r
@@ -136,6 +139,7 @@ SmmLockBoxUpdate (
   )\r
 {\r
   EFI_STATUS                    Status;\r
+  EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate;\r
 \r
   //\r
   // Sanity check\r
@@ -146,14 +150,25 @@ SmmLockBoxUpdate (
     return ;\r
   }\r
 \r
+  CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE));\r
+\r
+  //\r
+  // Sanity check\r
+  //\r
+  if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) {\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));\r
+    LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
+    return ;\r
+  }\r
+\r
   //\r
   // Update data\r
   //\r
   Status = UpdateLockBox (\r
-             &LockBoxParameterUpdate->Guid,\r
-             (UINTN)LockBoxParameterUpdate->Offset,\r
-             (VOID *)(UINTN)LockBoxParameterUpdate->Buffer,\r
-             (UINTN)LockBoxParameterUpdate->Length\r
+             &TempLockBoxParameterUpdate.Guid,\r
+             (UINTN)TempLockBoxParameterUpdate.Offset,\r
+             (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer,\r
+             (UINTN)TempLockBoxParameterUpdate.Length\r
              );\r
   LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;\r
   return ;\r
@@ -162,7 +177,11 @@ SmmLockBoxUpdate (
 /**\r
   Dispatch function for SMM lock box restore.\r
 \r
-  @param LockBoxParameterRestore  parameter of lock box restore \r
+  Caution: This function may receive untrusted input.\r
+  Restore buffer and length are external input, so this function will validate\r
+  it is in SMRAM.\r
+\r
+  @param LockBoxParameterRestore  parameter of lock box restore\r
 **/\r
 VOID\r
 SmmLockBoxRestore (\r
@@ -170,12 +189,15 @@ SmmLockBoxRestore (
   )\r
 {\r
   EFI_STATUS                     Status;\r
+  EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore;\r
+\r
+  CopyMem (&TempLockBoxParameterRestore, LockBoxParameterRestore, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE));\r
 \r
   //\r
   // Sanity check\r
   //\r
-  if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) {\r
-    DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));\r
+  if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterRestore.Buffer, (UINTN)TempLockBoxParameterRestore.Length)) {\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));\r
     LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
     return ;\r
   }\r
@@ -183,11 +205,22 @@ SmmLockBoxRestore (
   //\r
   // Restore data\r
   //\r
-  Status = RestoreLockBox (\r
-             &LockBoxParameterRestore->Guid,\r
-             (VOID *)(UINTN)LockBoxParameterRestore->Buffer,\r
-             (UINTN *)&LockBoxParameterRestore->Length\r
-             );\r
+  if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) {\r
+    Status = RestoreLockBox (\r
+               &TempLockBoxParameterRestore.Guid,\r
+               NULL,\r
+               NULL\r
+               );\r
+  } else {\r
+    Status = RestoreLockBox (\r
+               &TempLockBoxParameterRestore.Guid,\r
+               (VOID *)(UINTN)TempLockBoxParameterRestore.Buffer,\r
+               (UINTN *)&TempLockBoxParameterRestore.Length\r
+               );\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      LockBoxParameterRestore->Length = TempLockBoxParameterRestore.Length;\r
+    }\r
+  }\r
   LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;\r
   return ;\r
 }\r
@@ -212,6 +245,9 @@ SmmLockBoxRestoreAllInPlace (
 /**\r
   Dispatch function for a Software SMI handler.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
   @param DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
   @param Context         Points to an optional handler context which was specified when the\r
                          handler was registered.\r
@@ -232,40 +268,83 @@ SmmLockBoxHandler (
   )\r
 {\r
   EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;\r
+  UINTN                             TempCommBufferSize;\r
+\r
+  DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Enter\n"));\r
 \r
-  DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));\r
+  //\r
+  // If input is invalid, stop processing this SMI\r
+  //\r
+  if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TempCommBufferSize = *CommBufferSize;\r
+\r
+  //\r
+  // Sanity check\r
+  //\r
+  if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
+  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
   LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);\r
 \r
   LockBoxParameterHeader->ReturnStatus = (UINT64)-1;\r
 \r
-  DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));\r
+  DEBUG ((DEBUG_INFO, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));\r
 \r
-  DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));\r
+  DEBUG ((DEBUG_INFO, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));\r
 \r
   switch (LockBoxParameterHeader->Command) {\r
   case EFI_SMM_LOCK_BOX_COMMAND_SAVE:\r
+    if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));\r
+      break;\r
+    }\r
     SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);\r
     break;\r
   case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:\r
+    if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));\r
+      break;\r
+    }\r
     SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);\r
     break;\r
   case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:\r
+    if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));\r
+      break;\r
+    }\r
     SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);\r
     break;\r
   case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:\r
+    if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) {\r
+      DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));\r
+      break;\r
+    }\r
     SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);\r
     break;\r
   case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:\r
+    if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));\r
+      break;\r
+    }\r
     SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);\r
     break;\r
   default:\r
+    DEBUG ((EFI_D_ERROR, "SmmLockBox Command invalid!\n"));\r
     break;\r
   }\r
 \r
   LockBoxParameterHeader->Command = (UINT32)-1;\r
 \r
-  DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n"));\r
+  DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Exit\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -274,7 +353,7 @@ SmmLockBoxHandler (
   Smm Ready To Lock event notification handler.\r
 \r
   It sets a flag indicating that SMRAM has been locked.\r
-  \r
+\r
   @param[in] Protocol   Points to the protocol's unique identifier.\r
   @param[in] Interface  Points to the interface instance.\r
   @param[in] Handle     The handle on which the interface was installed.\r
@@ -299,7 +378,7 @@ SmmReadyToLockEventNotify (
   @param[in] ImageHandle  Image handle of this driver.\r
   @param[in] SystemTable  A Pointer to the EFI System Table.\r
 \r
-  @retval EFI_SUCEESS     \r
+  @retval EFI_SUCEESS\r
   @return Others          Some error occurs.\r
 **/\r
 EFI_STATUS\r
@@ -312,30 +391,6 @@ SmmLockBoxEntryPoint (
   EFI_STATUS                    Status;\r
   EFI_HANDLE                    DispatchHandle;\r
   VOID                          *Registration;\r
-  EFI_SMM_ACCESS2_PROTOCOL      *SmmAccess;\r
-  UINTN                         Size;\r
-\r
-  //\r
-  // Get SMRAM information\r
-  //\r
-  Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Size = 0;\r
-  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
-  ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
-\r
-  Status = gSmst->SmmAllocatePool (\r
-                    EfiRuntimeServicesData,\r
-                    Size,\r
-                    (VOID **)&mSmramRanges\r
-                    );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
 \r
   //\r
   // Register LockBox communication handler\r