]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
EdkCompatibilityPkg SmmBaseHelper: In SmmHandlerEntry(), add check to ensure CommBuff...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / SmmBaseHelper / SmmBaseHelper.c
index 99dccab8e9f7d7803a60a1c39d7701e64814d413..193ab197561c64047f0bc263d7a4e3d86b19be22 100644 (file)
@@ -4,7 +4,14 @@
   This driver is the counterpart of the SMM Base On SMM Base2 Thunk driver. It\r
   provides helping services in SMM to the SMM Base On SMM Base2 Thunk driver.\r
 \r
-  Copyright (c) 2009 - 2011, 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
+  SmmHandlerEntry() will receive untrusted input and do validation.\r
+\r
+  Copyright (c) 2009 - 2012, 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,6 +42,7 @@
 #include <Protocol/MpService.h>\r
 #include <Protocol/LoadPe32Image.h>\r
 #include <Protocol/SmmReadyToLock.h>\r
+#include <Protocol/SmmAccess2.h>\r
 \r
 ///\r
 /// Structure for tracking paired information of registered Framework SMI handler\r
@@ -78,6 +86,8 @@ SPIN_LOCK                          mPFLock;
 UINT64                             mPhyMask;\r
 VOID                               *mOriginalHandler;\r
 EFI_SMM_CPU_SAVE_STATE             *mShadowSaveState;\r
+EFI_SMRAM_DESCRIPTOR               *mSmramRanges;\r
+UINTN                              mSmramRangeCount;\r
 \r
 LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead);\r
 \r
@@ -695,6 +705,32 @@ LoadImage (
   return Status;\r
 }\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
   Thunk service of EFI_SMM_BASE_PROTOCOL.Register().\r
@@ -998,6 +1034,10 @@ HelperCommunicate (
 \r
   This SMI handler provides services for the SMM Base Thunk driver.\r
 \r
+  Caution: This function may receive untrusted input during runtime.\r
+  The communicate buffer is external input, so this function will do operations only if the communicate\r
+  buffer is outside of SMRAM so that returning the status code in the buffer won't overwrite anywhere in SMRAM.\r
+\r
   @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
   @param[in]     RegisterContext Points to an optional handler context which was specified when the\r
                                  handler was registered.\r
@@ -1025,32 +1065,35 @@ SmmHandlerEntry (
   SMMBASE_FUNCTION_DATA *FunctionData;\r
 \r
   ASSERT (CommBuffer != NULL);\r
-  ASSERT (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA));\r
-\r
-  FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;\r
-\r
-  switch (FunctionData->Function) {\r
-    case SmmBaseFunctionRegister:\r
-      Register (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionUnregister:\r
-      UnRegister (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionRegisterCallback:\r
-      RegisterCallback (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionAllocatePool:\r
-      HelperAllocatePool (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionFreePool:\r
-      HelperFreePool (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionCommunicate:\r
-      HelperCommunicate (FunctionData);\r
-      break;\r
-    default:\r
-      ASSERT (FALSE);\r
-      FunctionData->Status = EFI_UNSUPPORTED;\r
+  ASSERT (CommBufferSize != NULL);\r
+\r
+  if (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA) &&\r
+      !IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {\r
+    FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;\r
+\r
+    switch (FunctionData->Function) {\r
+      case SmmBaseFunctionRegister:\r
+        Register (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionUnregister:\r
+        UnRegister (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionRegisterCallback:\r
+        RegisterCallback (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionAllocatePool:\r
+        HelperAllocatePool (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionFreePool:\r
+        HelperFreePool (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionCommunicate:\r
+        HelperCommunicate (FunctionData);\r
+        break;\r
+      default:\r
+        DEBUG ((EFI_D_WARN, "SmmBaseHelper: invalid SMM Base function.\n"));\r
+        FunctionData->Status = EFI_UNSUPPORTED;\r
+    }\r
   }\r
   return EFI_SUCCESS;\r
 }\r
@@ -1099,6 +1142,8 @@ SmmBaseHelperMain (
   EFI_HANDLE                 Handle;\r
   UINTN                      NumberOfEnabledProcessors;\r
   VOID                       *Registration;\r
+  EFI_SMM_ACCESS2_PROTOCOL   *SmmAccess;\r
+  UINTN                      Size;\r
   \r
   Handle = NULL;\r
   ///\r
@@ -1143,6 +1188,28 @@ SmmBaseHelperMain (
   mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst;\r
   mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry;\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 SMM Ready To Lock Protocol notification\r
   //\r