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
+ //\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
AcquireLockOnlyAtBootTime(&mVariableServicesLock);\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
EFI_STATUS Status;\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
+ UINTN SmmCommBufPayloadSize;\r
\r
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // SMM Communication Buffer max payload size\r
+ //\r
+ SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\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
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
AcquireLockOnlyAtBootTime(&mVariableServicesLock);\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_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize; \r
+ if (*VariableNameSize > 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
+ }\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
+\r
+\r
Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
ASSERT (SmmGetNextVariableName != NULL);\r
\r
+ //\r
+ // SMM comm buffer->NameSize is buffer size for return string\r
+ //\r
SmmGetNextVariableName->NameSize = *VariableNameSize;\r
+\r
CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
- CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);\r
+ //\r
+ // Copy whole string\r
+ //\r
+ CopyMem (SmmGetNextVariableName->Name, VariableName, StrSize (VariableName));\r
\r
//\r
// Send data to SMM\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
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
\r
//\r