return FALSE;\r
}\r
\r
+/**\r
+ This function check if the address refered by Buffer and Length is valid.\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 valid.\r
+ @retval FALSE this address is NOT valid.\r
+**/\r
+BOOLEAN\r
+InternalIsAddressValid (\r
+ IN UINTN Buffer,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ if (Buffer > (MAX_ADDRESS - Length)) {\r
+ //\r
+ // Overflow happen\r
+ //\r
+ return FALSE;\r
+ }\r
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+}\r
\r
/**\r
Retrive the SMM FVB protocol interface by HANDLE.\r
VOID *PrivateData;\r
EFI_HANDLE SmmFvbHandle;\r
UINTN InfoSize;\r
+ UINTN CommBufferPayloadSize;\r
+ UINTN PrivateDataSize;\r
+ UINTN Length;\r
\r
\r
//\r
}\r
\r
if (*CommBufferSize < SMM_FTW_COMMUNICATE_HEADER_SIZE) {\r
+ DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+ CommBufferPayloadSize = *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE;\r
\r
- if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {\r
- DEBUG ((EFI_D_ERROR, "SMM communication buffer size is in SMRAM!\n"));\r
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, *CommBufferSize)) {\r
+ DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
return EFI_SUCCESS;\r
}\r
\r
\r
switch (SmmFtwFunctionHeader->Function) {\r
case FTW_FUNCTION_GET_MAX_BLOCK_SIZE:\r
- SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;\r
- InfoSize = sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER);\r
-\r
- //\r
- // SMRAM range check already covered before\r
- //\r
- if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {\r
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));\r
- Status = EFI_ACCESS_DENIED;\r
- break;\r
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER)) {\r
+ DEBUG ((EFI_D_ERROR, "GetMaxBlockSize: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
}\r
+ SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;\r
\r
Status = FtwGetMaxBlockSize (\r
&mFtwDevice->FtwInstance,\r
break;\r
\r
case FTW_FUNCTION_ALLOCATE:\r
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_ALLOCATE_HEADER)) {\r
+ DEBUG ((EFI_D_ERROR, "Allocate: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
SmmFtwAllocateHeader = (SMM_FTW_ALLOCATE_HEADER *) SmmFtwFunctionHeader->Data;\r
Status = FtwAllocate (\r
&mFtwDevice->FtwInstance,\r
break;\r
\r
case FTW_FUNCTION_WRITE:\r
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) {\r
+ DEBUG ((EFI_D_ERROR, "Write: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
SmmFtwWriteHeader = (SMM_FTW_WRITE_HEADER *) SmmFtwFunctionHeader->Data;\r
- if (SmmFtwWriteHeader->PrivateDataSize == 0) {\r
+ Length = SmmFtwWriteHeader->Length;\r
+ PrivateDataSize = SmmFtwWriteHeader->PrivateDataSize;\r
+ if (((UINTN)(~0) - Length < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) ||\r
+ ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length)) {\r
+ //\r
+ // Prevent InfoSize overflow\r
+ //\r
+ Status = EFI_ACCESS_DENIED;\r
+ break;\r
+ }\r
+ InfoSize = OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length + PrivateDataSize;\r
+\r
+ //\r
+ // SMRAM range check already covered before\r
+ //\r
+ if (InfoSize > CommBufferPayloadSize) {\r
+ DEBUG ((EFI_D_ERROR, "Write: Data size exceed communication buffer size limit!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ break;\r
+ }\r
+\r
+ if (PrivateDataSize == 0) {\r
PrivateData = NULL;\r
} else {\r
- PrivateData = (VOID *)&SmmFtwWriteHeader->Data[SmmFtwWriteHeader->Length];\r
+ PrivateData = (VOID *)&SmmFtwWriteHeader->Data[Length];\r
}\r
Status = GetFvbByAddressAndAttribute (\r
SmmFtwWriteHeader->FvbBaseAddress, \r
&mFtwDevice->FtwInstance,\r
SmmFtwWriteHeader->Lba,\r
SmmFtwWriteHeader->Offset,\r
- SmmFtwWriteHeader->Length,\r
+ Length,\r
PrivateData,\r
SmmFvbHandle,\r
SmmFtwWriteHeader->Data\r
break;\r
\r
case FTW_FUNCTION_RESTART:\r
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_RESTART_HEADER)) {\r
+ DEBUG ((EFI_D_ERROR, "Restart: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
SmmFtwRestartHeader = (SMM_FTW_RESTART_HEADER *) SmmFtwFunctionHeader->Data;\r
Status = GetFvbByAddressAndAttribute (\r
SmmFtwRestartHeader->FvbBaseAddress, \r
break;\r
\r
case FTW_FUNCTION_GET_LAST_WRITE:\r
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)) {\r
+ DEBUG ((EFI_D_ERROR, "GetLastWrite: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
SmmFtwGetLastWriteHeader = (SMM_FTW_GET_LAST_WRITE_HEADER *) SmmFtwFunctionHeader->Data;\r
- if ((UINTN)(~0) - SmmFtwGetLastWriteHeader->PrivateDataSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)){\r
+ PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;\r
+ if ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)){\r
//\r
// Prevent InfoSize overflow\r
//\r
Status = EFI_ACCESS_DENIED;\r
break;\r
}\r
- InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + SmmFtwGetLastWriteHeader->PrivateDataSize;\r
+ InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + PrivateDataSize;\r
\r
//\r
// SMRAM range check already covered before\r
//\r
- if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {\r
+ if (InfoSize > CommBufferPayloadSize) {\r
DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));\r
Status = EFI_ACCESS_DENIED;\r
break;\r
&SmmFtwGetLastWriteHeader->Lba,\r
&SmmFtwGetLastWriteHeader->Offset,\r
&SmmFtwGetLastWriteHeader->Length,\r
- &SmmFtwGetLastWriteHeader->PrivateDataSize,\r
+ &PrivateDataSize,\r
(VOID *)SmmFtwGetLastWriteHeader->Data,\r
&SmmFtwGetLastWriteHeader->Complete\r
);\r
+ SmmFtwGetLastWriteHeader->PrivateDataSize = PrivateDataSize;\r
break;\r
\r
default:\r
EFI_STATUS Status;\r
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
EFI_HANDLE SmmFtwHandle;\r
+ EFI_HANDLE FtwHandle;\r
\r
//\r
// Just return to avoid install SMM FaultTolerantWriteProtocol again\r
if (EFI_ERROR(Status)) {\r
return Status;\r
}\r
- \r
+\r
//\r
// Install protocol interface\r
//\r
);\r
ASSERT_EFI_ERROR (Status); \r
\r
+ ///\r
+ /// Register SMM FTW SMI handler\r
+ ///\r
+ Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
// Notify the Ftw wrapper driver SMM Ftw is ready\r
//\r
- SmmFtwHandle = NULL;\r
+ FtwHandle = NULL;\r
Status = gBS->InstallProtocolInterface (\r
- &SmmFtwHandle,\r
+ &FtwHandle,\r
&gEfiSmmFaultTolerantWriteProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
NULL\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_HANDLE FtwHandle;\r
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
UINTN Size;\r
VOID *SmmEndOfDxeRegistration;\r
ASSERT_EFI_ERROR (Status);\r
\r
FvbNotificationEvent (NULL, NULL, NULL);\r
-\r
- ///\r
- /// Register SMM FTW SMI handler\r
- ///\r
- Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &FtwHandle);\r
- ASSERT_EFI_ERROR (Status);\r
\r
return EFI_SUCCESS;\r
}\r