SecurityPkg OpalPasswordSupportLib: Add check to avoid potential buffer overflow.
Current code not check the CommunicationBuffer size before use it. Attacker can read beyond the end of the (untrusted) commbuffer into controlled memory. Attacker can get access outside of valid SMM memory regions. This patch add check before use it. bugz: https://bugzilla.tianocore.org/show_bug.cgi?id=198 Cc: Yao Jiewen <jiewen.yao@intel.com> Cc: Wu Hao <hao.a.wu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Yao Jiewen <jiewen.yao@intel.com>
This commit is contained in:
@@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Protocol/DevicePath.h>
|
#include <Protocol/DevicePath.h>
|
||||||
#include <Library/TcgStorageOpalLib.h>
|
#include <Library/TcgStorageOpalLib.h>
|
||||||
|
|
||||||
|
#define OPAL_PASSWORD_MAX_LENGTH 32
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
LIST_ENTRY Link;
|
LIST_ENTRY Link;
|
||||||
|
|
||||||
UINT8 Password[32];
|
UINT8 Password[OPAL_PASSWORD_MAX_LENGTH];
|
||||||
UINT8 PasswordLength;
|
UINT8 PasswordLength;
|
||||||
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
|
||||||
|
@@ -14,8 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include "OpalPasswordSupportNotify.h"
|
#include "OpalPasswordSupportNotify.h"
|
||||||
|
|
||||||
#define OPAL_PASSWORD_MAX_LENGTH 32
|
|
||||||
|
|
||||||
LIST_ENTRY mDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mDeviceList);
|
LIST_ENTRY mDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mDeviceList);
|
||||||
BOOLEAN gInSmm = FALSE;
|
BOOLEAN gInSmm = FALSE;
|
||||||
EFI_GUID gOpalPasswordNotifyProtocolGuid = OPAL_PASSWORD_NOTIFY_PROTOCOL_GUID;
|
EFI_GUID gOpalPasswordNotifyProtocolGuid = OPAL_PASSWORD_NOTIFY_PROTOCOL_GUID;
|
||||||
@@ -663,34 +661,53 @@ SmmOpalPasswordHandler (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
OPAL_SMM_COMMUNICATE_HEADER *SmmFunctionHeader;
|
OPAL_SMM_COMMUNICATE_HEADER *SmmFunctionHeader;
|
||||||
UINTN TempCommBufferSize;
|
UINTN TempCommBufferSize;
|
||||||
UINT8 *NewPassword;
|
UINTN RemainedDevicePathSize;
|
||||||
UINT8 PasswordLength;
|
OPAL_COMM_DEVICE_LIST *DeviceBuffer;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
||||||
|
|
||||||
if (CommBuffer == NULL || CommBufferSize == NULL) {
|
if (CommBuffer == NULL || CommBufferSize == NULL) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
DeviceBuffer = NULL;
|
||||||
|
|
||||||
TempCommBufferSize = *CommBufferSize;
|
TempCommBufferSize = *CommBufferSize;
|
||||||
if (TempCommBufferSize < OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)) {
|
if (TempCommBufferSize < OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *)CommBuffer;
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *)CommBuffer;
|
|
||||||
|
|
||||||
DevicePath = &((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->OpalDevicePath;
|
|
||||||
PasswordLength = ((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->PasswordLength;
|
|
||||||
NewPassword = ((OPAL_COMM_DEVICE_LIST*)(SmmFunctionHeader->Data))->Password;
|
|
||||||
|
|
||||||
switch (SmmFunctionHeader->Function) {
|
switch (SmmFunctionHeader->Function) {
|
||||||
case SMM_FUNCTION_SET_OPAL_PASSWORD:
|
case SMM_FUNCTION_SET_OPAL_PASSWORD:
|
||||||
if (OpalPasswordIsFullZero (NewPassword) || PasswordLength == 0) {
|
if (TempCommBufferSize <= OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath)) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
return EFI_SUCCESS;
|
||||||
goto EXIT;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Status = OpalSavePasswordToSmm (DevicePath, NewPassword, PasswordLength);
|
DeviceBuffer = AllocateCopyPool (TempCommBufferSize - OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data), SmmFunctionHeader->Data);
|
||||||
|
if (DeviceBuffer == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate the DevicePath.
|
||||||
|
//
|
||||||
|
RemainedDevicePathSize = TempCommBufferSize - OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)
|
||||||
|
- OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath);
|
||||||
|
if (!IsDevicePathValid(&DeviceBuffer->OpalDevicePath, RemainedDevicePathSize) ||
|
||||||
|
(RemainedDevicePathSize != GetDevicePathSize (&DeviceBuffer->OpalDevicePath))) {
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OpalPasswordIsFullZero (DeviceBuffer->Password) ||
|
||||||
|
DeviceBuffer->PasswordLength == 0 ||
|
||||||
|
DeviceBuffer->PasswordLength > OPAL_PASSWORD_MAX_LENGTH) {
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = OpalSavePasswordToSmm (&DeviceBuffer->OpalDevicePath, DeviceBuffer->Password, DeviceBuffer->PasswordLength);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -701,6 +718,10 @@ SmmOpalPasswordHandler (
|
|||||||
EXIT:
|
EXIT:
|
||||||
SmmFunctionHeader->ReturnStatus = Status;
|
SmmFunctionHeader->ReturnStatus = Status;
|
||||||
|
|
||||||
|
if (DeviceBuffer != NULL) {
|
||||||
|
FreePool (DeviceBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return EFI_SUCCESS cause only one handler can be trigged.
|
// Return EFI_SUCCESS cause only one handler can be trigged.
|
||||||
// so return EFI_WARN_INTERRUPT_SOURCE_PENDING to make all handler can be trigged.
|
// so return EFI_WARN_INTERRUPT_SOURCE_PENDING to make all handler can be trigged.
|
||||||
|
@@ -41,7 +41,7 @@ typedef struct {
|
|||||||
} OPAL_SMM_COMMUNICATE_HEADER;
|
} OPAL_SMM_COMMUNICATE_HEADER;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 Password[32];
|
UINT8 Password[OPAL_PASSWORD_MAX_LENGTH];
|
||||||
UINT8 PasswordLength;
|
UINT8 PasswordLength;
|
||||||
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL OpalDevicePath;
|
||||||
|
@@ -64,10 +64,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
// The payload Length of HDD related ATA commands
|
// The payload Length of HDD related ATA commands
|
||||||
//
|
//
|
||||||
#define HDD_PAYLOAD 512
|
#define HDD_PAYLOAD 512
|
||||||
//
|
|
||||||
// According to ATA spec, the max Length of hdd password is 32 bytes
|
|
||||||
//
|
|
||||||
#define OPAL_PASSWORD_MAX_LENGTH 32
|
|
||||||
|
|
||||||
extern VOID *mBuffer;
|
extern VOID *mBuffer;
|
||||||
|
|
||||||
@@ -124,7 +120,7 @@ typedef struct {
|
|||||||
|
|
||||||
UINT32 NvmeNamespaceId;
|
UINT32 NvmeNamespaceId;
|
||||||
|
|
||||||
UINT8 Password[32];
|
UINT8 Password[OPAL_PASSWORD_MAX_LENGTH];
|
||||||
UINT8 PasswordLength;
|
UINT8 PasswordLength;
|
||||||
|
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
|
Reference in New Issue
Block a user