]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
MdeModulePkg: Cleanup gEfiSmmAccess2ProtocolGuid reference.
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
index 35862c62232c2847db15c46ae67e04e4546ded21..f1880d464d1f143200488e8a884374d6737810d0 100644 (file)
@@ -1,6 +1,15 @@
 /** @file\r
+  LockBox SMM driver.\r
+  \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 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2015, 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,48 +30,23 @@ 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
+  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
@@ -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,6 +127,10 @@ SmmLockBoxSetAttributes (
 /**\r
   Dispatch function for SMM lock box update.\r
 \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
@@ -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,6 +177,10 @@ SmmLockBoxUpdate (
 /**\r
   Dispatch function for SMM lock box restore.\r
 \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
@@ -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,17 +205,17 @@ SmmLockBoxRestore (
   //\r
   // Restore data\r
   //\r
-  if ((LockBoxParameterRestore->Length == 0) && (LockBoxParameterRestore->Buffer == 0)) {\r
+  if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) {\r
     Status = RestoreLockBox (\r
-               &LockBoxParameterRestore->Guid,\r
+               &TempLockBoxParameterRestore.Guid,\r
                NULL,\r
                NULL\r
                );\r
   } else {\r
     Status = RestoreLockBox (\r
-               &LockBoxParameterRestore->Guid,\r
-               (VOID *)(UINTN)LockBoxParameterRestore->Buffer,\r
-               (UINTN *)&LockBoxParameterRestore->Length\r
+               &TempLockBoxParameterRestore.Guid,\r
+               (VOID *)(UINTN)TempLockBoxParameterRestore.Buffer,\r
+               (UINTN *)&TempLockBoxParameterRestore.Length\r
                );\r
   }\r
   LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;\r
@@ -220,6 +242,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
@@ -240,9 +265,31 @@ SmmLockBoxHandler (
   )\r
 {\r
   EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;\r
+  UINTN                             TempCommBufferSize;\r
 \r
   DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));\r
 \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
@@ -253,21 +300,42 @@ SmmLockBoxHandler (
 \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
@@ -320,30 +388,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