EFI_STATUS Status;\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
+ UINTN SmmCommBufPayloadSize;\r
+ UINTN TempDataSize;\r
\r
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (*DataSize >= mVariableBufferSize) {\r
- //\r
- // DataSize may be near MAX_ADDRESS incorrectly, this can cause the computed PayLoadSize to\r
- // overflow to a small value and pass the check in InitCommunicateBuffer().\r
- // To protect against this vulnerability, return EFI_INVALID_PARAMETER if DataSize is >= mVariableBufferSize.\r
- // And there will be further check to ensure the total size is also not > mVariableBufferSize.\r
- //\r
+ //\r
+ // SMM Communication Buffer max payload size\r
+ //\r
+ SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\r
+ TempDataSize = *DataSize;\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
return EFI_INVALID_PARAMETER;\r
}\r
\r
// 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
+ if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName)) {\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
+ }\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + TempDataSize;\r
+\r
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
ASSERT (SmmVariableHeader != NULL);\r
\r
CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
- SmmVariableHeader->DataSize = *DataSize;\r
+ SmmVariableHeader->DataSize = TempDataSize;\r
SmmVariableHeader->NameSize = StrSize (VariableName);\r
if (Attributes == NULL) {\r
SmmVariableHeader->Attributes = 0;\r
//\r
// Get data from SMM.\r
//\r
- *DataSize = SmmVariableHeader->DataSize;\r
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // SMM CommBuffer DataSize can be a trimed value\r
+ // Only update DataSize when needed\r
+ //\r
+ *DataSize = SmmVariableHeader->DataSize;\r
+ }\r
if (Attributes != NULL) {\r
*Attributes = SmmVariableHeader->Attributes;\r
}\r