]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
1. Use the check IsAddressValid() to prevent SMM communication buffer overflow in...
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / VariableSmmRuntimeDxe.c
index 5a02b77d537942a99814ca98767665eadc5062db..cdd407d66bea70b3b75dcd2ed992c916b80b8f0f 100644 (file)
@@ -207,6 +207,7 @@ RuntimeServiceGetVariable (
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;\r
   UINTN                                     SmmCommBufPayloadSize;\r
   UINTN                                     TempDataSize;\r
+  UINTN                                     VariableNameSize;\r
 \r
   if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -221,11 +222,12 @@ RuntimeServiceGetVariable (
   //\r
   SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\r
   TempDataSize          = *DataSize;\r
+  VariableNameSize      = StrSize (VariableName);\r
 \r
   //\r
   // If VariableName exceeds SMM payload limit. Return failure\r
   //\r
-  if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+  if (VariableNameSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -235,13 +237,13 @@ RuntimeServiceGetVariable (
   // Init the communicate buffer. The buffer data size is:\r
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
   //\r
-  if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName)) {\r
+  if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {\r
     //\r
     // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
     //\r
-    TempDataSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName);\r
+    TempDataSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;\r
   }\r
-  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + TempDataSize;\r
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;\r
 \r
   Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
   if (EFI_ERROR (Status)) {\r
@@ -251,7 +253,7 @@ RuntimeServiceGetVariable (
 \r
   CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
   SmmVariableHeader->DataSize   = TempDataSize;\r
-  SmmVariableHeader->NameSize   = StrSize (VariableName);\r
+  SmmVariableHeader->NameSize   = VariableNameSize;\r
   if (Attributes == NULL) {\r
     SmmVariableHeader->Attributes = 0;\r
   } else {\r
@@ -315,6 +317,8 @@ RuntimeServiceGetNextVariableName (
   UINTN                                           PayloadSize;\r
   SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
   UINTN                                           SmmCommBufPayloadSize;\r
+  UINTN                                           OutVariableNameSize;\r
+  UINTN                                           InVariableNameSize;\r
 \r
   if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -324,11 +328,13 @@ RuntimeServiceGetNextVariableName (
   // SMM Communication Buffer max payload size\r
   //\r
   SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\r
+  OutVariableNameSize   = *VariableNameSize;\r
+  InVariableNameSize    = StrSize (VariableName);\r
 \r
   //\r
   // If input string exceeds SMM payload limit. Return failure\r
   //\r
-  if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+  if (InVariableNameSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -338,16 +344,16 @@ RuntimeServiceGetNextVariableName (
   // Init the communicate buffer. The buffer data size is:\r
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
   //\r
-  if (*VariableNameSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+  if (OutVariableNameSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
     //\r
     // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
     //\r
-    *VariableNameSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
+    OutVariableNameSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
   }\r
   //\r
   // Payload should be Guid + NameSize + MAX of Input & Output buffer\r
   //\r
-  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (*VariableNameSize, StrSize (VariableName));\r
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);\r
 \r
   Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
   if (EFI_ERROR (Status)) {\r
@@ -358,13 +364,16 @@ RuntimeServiceGetNextVariableName (
   //\r
   // SMM comm buffer->NameSize is buffer size for return string\r
   //\r
-  SmmGetNextVariableName->NameSize = *VariableNameSize;\r
+  SmmGetNextVariableName->NameSize = OutVariableNameSize;\r
 \r
   CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
   //\r
   // Copy whole string\r
   //\r
-  CopyMem (SmmGetNextVariableName->Name, VariableName, StrSize (VariableName));\r
+  CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);\r
+  if (OutVariableNameSize > InVariableNameSize) {\r
+    ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);\r
+  }\r
 \r
   //\r
   // Send data to SMM\r
@@ -374,7 +383,13 @@ RuntimeServiceGetNextVariableName (
   //\r
   // Get data from SMM.\r
   //\r
-  *VariableNameSize = SmmGetNextVariableName->NameSize;    \r
+  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+    //\r
+    // SMM CommBuffer NameSize can be a trimed value\r
+    // Only update VariableNameSize when needed\r
+    //\r
+    *VariableNameSize = SmmGetNextVariableName->NameSize;\r
+  }\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
@@ -420,6 +435,7 @@ RuntimeServiceSetVariable (
   EFI_STATUS                                Status;\r
   UINTN                                     PayloadSize; \r
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;\r
+  UINTN                                     VariableNameSize;\r
     \r
   //\r
   // Check input parameters.\r
@@ -441,8 +457,9 @@ RuntimeServiceSetVariable (
     //\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  VariableNameSize      = StrSize (VariableName);\r
 \r
-  if ((UINTN)(~0) - StrSize (VariableName) < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + DataSize) {\r
+  if ((UINTN)(~0) - VariableNameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + DataSize) {\r
     //\r
     // Prevent PayloadSize overflow\r
     //\r
@@ -455,7 +472,7 @@ RuntimeServiceSetVariable (
   // Init the communicate buffer. The buffer data size is:\r
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
   //\r
-  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;\r
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;\r
   Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
@@ -464,7 +481,7 @@ RuntimeServiceSetVariable (
 \r
   CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);\r
   SmmVariableHeader->DataSize   = DataSize;\r
-  SmmVariableHeader->NameSize   = StrSize (VariableName);\r
+  SmmVariableHeader->NameSize   = VariableNameSize;\r
   SmmVariableHeader->Attributes = Attributes;\r
   CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
   CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);\r