Revision: 14276
          http://edk2.svn.sourceforge.net/edk2/?rev=14276&view=rev
Author:   czhang46
Date:     2013-04-15 01:56:31 +0000 (Mon, 15 Apr 2013)
Log Message:
-----------
Fix SMM Variable driver stack GetVariable return INVALID_PARAMETER when 
DataSize is bigger than SMM communication buffer. 

Signed-off-by: Chao Zhang <[email protected]>
Reviewed-by  : Dong Guo   <[email protected]>
Reviewed-by  : Fu Siyuan  <[email protected]>

Modified Paths:
--------------
    
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
    
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c

Modified: 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
===================================================================
--- 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   
    2013-04-15 01:55:52 UTC (rev 14275)
+++ 
trunk/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   
    2013-04-15 01:56:31 UTC (rev 14276)
@@ -189,6 +189,8 @@
   EFI_STATUS                                Status;
   UINTN                                     PayloadSize;
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
+  UINTN                                     SmmCommBufPayloadSize;
+  UINTN                                     TempDataSize;
 
   if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -198,13 +200,16 @@
     return EFI_INVALID_PARAMETER;
   }
 
-  if (*DataSize >= mVariableBufferSize) {
-    //
-    // DataSize may be near MAX_ADDRESS incorrectly, this can cause the 
computed PayLoadSize to
-    // overflow to a small value and pass the check in InitCommunicateBuffer().
-    // To protect against this vulnerability, return EFI_INVALID_PARAMETER if 
DataSize is >= mVariableBufferSize.
-    // And there will be further check to ensure the total size is also not > 
mVariableBufferSize.
-    //
+  //
+  // SMM Communication Buffer max payload size
+  //
+  SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + 
SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);
+  TempDataSize          = *DataSize;
+
+  //
+  // If VariableName exceeds SMM payload limit. Return failure
+  //
+  if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     return EFI_INVALID_PARAMETER;
   }
 
@@ -214,7 +219,14 @@
   // Init the communicate buffer. The buffer data size is:
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + 
PayloadSize.
   //
-  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + 
StrSize (VariableName) + *DataSize;
+  if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName)) {
+    //
+    // If output data buffer exceed SMM payload limit. Trim output buffer to 
SMM payload size
+    //
+    TempDataSize = SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName);
+  }
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + 
StrSize (VariableName) + TempDataSize;
+
   Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, 
SMM_VARIABLE_FUNCTION_GET_VARIABLE);
   if (EFI_ERROR (Status)) {
     goto Done;
@@ -222,7 +234,7 @@
   ASSERT (SmmVariableHeader != NULL);
 
   CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
-  SmmVariableHeader->DataSize   = *DataSize;
+  SmmVariableHeader->DataSize   = TempDataSize;
   SmmVariableHeader->NameSize   = StrSize (VariableName);
   if (Attributes == NULL) {
     SmmVariableHeader->Attributes = 0;
@@ -239,7 +251,13 @@
   //
   // Get data from SMM.
   //
-  *DataSize = SmmVariableHeader->DataSize;
+  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
+    //
+    // SMM CommBuffer DataSize can be a trimed value
+    // Only update DataSize when needed
+    //
+    *DataSize = SmmVariableHeader->DataSize;
+  }
   if (Attributes != NULL) {
     *Attributes = SmmVariableHeader->Attributes;
   }

Modified: 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
===================================================================
--- 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c 
    2013-04-15 01:55:52 UTC (rev 14275)
+++ 
trunk/edk2/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c 
    2013-04-15 01:56:31 UTC (rev 14276)
@@ -205,6 +205,8 @@
   EFI_STATUS                                Status;
   UINTN                                     PayloadSize;
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
+  UINTN                                     SmmCommBufPayloadSize;
+  UINTN                                     TempDataSize;
 
   if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -214,13 +216,16 @@
     return EFI_INVALID_PARAMETER;
   }
 
-  if (*DataSize >= mVariableBufferSize) {
-    //
-    // DataSize may be near MAX_ADDRESS incorrectly, this can cause the 
computed PayLoadSize to
-    // overflow to a small value and pass the check in InitCommunicateBuffer().
-    // To protect against this vulnerability, return EFI_INVALID_PARAMETER if 
DataSize is >= mVariableBufferSize.
-    // And there will be further check to ensure the total size is also not > 
mVariableBufferSize.
-    //
+  //
+  // SMM Communication Buffer max payload size
+  //
+  SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + 
SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);
+  TempDataSize          = *DataSize;
+
+  //
+  // If VariableName exceeds SMM payload limit. Return failure
+  //
+  if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     return EFI_INVALID_PARAMETER;
   }
 
@@ -230,7 +235,14 @@
   // Init the communicate buffer. The buffer data size is:
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + 
PayloadSize.
   //
-  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + 
StrSize (VariableName) + *DataSize;
+  if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName)) {
+    //
+    // If output data buffer exceed SMM payload limit. Trim output buffer to 
SMM payload size
+    //
+    TempDataSize = SmmCommBufPayloadSize - OFFSET_OF 
(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName);
+  }
+  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + 
StrSize (VariableName) + TempDataSize;
+
   Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, 
SMM_VARIABLE_FUNCTION_GET_VARIABLE);
   if (EFI_ERROR (Status)) {
     goto Done;
@@ -238,7 +250,7 @@
   ASSERT (SmmVariableHeader != NULL);
 
   CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
-  SmmVariableHeader->DataSize   = *DataSize;
+  SmmVariableHeader->DataSize   = TempDataSize;
   SmmVariableHeader->NameSize   = StrSize (VariableName);
   if (Attributes == NULL) {
     SmmVariableHeader->Attributes = 0;
@@ -255,7 +267,13 @@
   //
   // Get data from SMM.
   //
-  *DataSize = SmmVariableHeader->DataSize;
+  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
+    //
+    // SMM CommBuffer DataSize can be a trimed value
+    // Only update DataSize when needed
+    //
+    *DataSize = SmmVariableHeader->DataSize;
+  }
   if (Attributes != NULL) {
     *Attributes = SmmVariableHeader->Attributes;
   }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to