2015-10-19 21:13:13 +02:00
|
|
|
/** @file
|
|
|
|
Page table manipulation functions for IA-32 processors
|
|
|
|
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
|
2017-02-26 18:43:07 +01:00
|
|
|
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
|
|
|
|
2019-04-04 01:07:22 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2015-10-19 21:13:13 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "PiSmmCpuDxeSmm.h"
|
|
|
|
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
/**
|
|
|
|
Disable CET.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
DisableCet (
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Enable CET.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
EnableCet (
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
2015-10-19 21:13:13 +02:00
|
|
|
/**
|
|
|
|
Create PageTable for SMM use.
|
|
|
|
|
|
|
|
@return PageTable Address
|
|
|
|
|
|
|
|
**/
|
|
|
|
UINT32
|
|
|
|
SmmInitPageTable (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN PageFaultHandlerHookAddress;
|
|
|
|
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
2016-11-16 15:25:56 +01:00
|
|
|
EFI_STATUS Status;
|
2015-10-19 21:13:13 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize spin lock
|
|
|
|
//
|
2016-03-22 03:15:53 +01:00
|
|
|
InitializeSpinLock (mPFLock);
|
2015-10-19 21:13:13 +02:00
|
|
|
|
2017-08-24 04:59:14 +02:00
|
|
|
mPhysicalAddressBits = 32;
|
|
|
|
|
2018-08-20 05:35:58 +02:00
|
|
|
if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||
|
|
|
|
HEAP_GUARD_NONSTOP_MODE ||
|
|
|
|
NULL_DETECTION_NONSTOP_MODE) {
|
2015-10-19 21:13:13 +02:00
|
|
|
//
|
|
|
|
// Set own Page Fault entry instead of the default one, because SMM Profile
|
|
|
|
// feature depends on IRET instruction to do Single Step
|
|
|
|
//
|
|
|
|
PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
|
|
|
|
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
|
|
|
|
IdtEntry += EXCEPT_IA32_PAGE_FAULT;
|
|
|
|
IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
|
|
|
|
IdtEntry->Bits.Reserved_0 = 0;
|
|
|
|
IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
|
|
|
IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
|
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// Register SMM Page Fault Handler
|
|
|
|
//
|
2016-11-16 15:25:56 +01:00
|
|
|
Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Additional SMM IDT initialization for SMM stack guard
|
|
|
|
//
|
|
|
|
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
|
|
|
|
InitializeIDTSmmStackGuard ();
|
|
|
|
}
|
2016-10-23 17:19:52 +02:00
|
|
|
return Gen4GPageTable (TRUE);
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Page Fault handler for SMM use.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
SmiDefaultPFHandler (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
ThePage Fault handler wrapper for SMM use.
|
|
|
|
|
|
|
|
@param InterruptType Defines the type of interrupt or exception that
|
|
|
|
occurred on the processor.This parameter is processor architecture specific.
|
|
|
|
@param SystemContext A pointer to the processor context when
|
|
|
|
the interrupt occurred on the processor.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
SmiPFHandler (
|
2017-04-01 13:39:22 +02:00
|
|
|
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
|
|
IN EFI_SYSTEM_CONTEXT SystemContext
|
2015-10-19 21:13:13 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN PFAddress;
|
2016-11-22 08:05:11 +01:00
|
|
|
UINTN GuardPageAddress;
|
|
|
|
UINTN CpuIndex;
|
2015-10-19 21:13:13 +02:00
|
|
|
|
|
|
|
ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
|
|
|
|
|
2016-03-22 03:15:53 +01:00
|
|
|
AcquireSpinLock (mPFLock);
|
2015-10-19 21:13:13 +02:00
|
|
|
|
|
|
|
PFAddress = AsmReadCr2 ();
|
|
|
|
|
2016-11-22 08:05:11 +01:00
|
|
|
//
|
|
|
|
// If a page fault occurs in SMRAM range, it might be in a SMM stack guard page,
|
|
|
|
// or SMM page protection violation.
|
|
|
|
//
|
|
|
|
if ((PFAddress >= mCpuHotPlugData.SmrrBase) &&
|
2015-10-19 21:13:13 +02:00
|
|
|
(PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
|
2017-04-01 13:39:22 +02:00
|
|
|
DumpCpuContext (InterruptType, SystemContext);
|
2016-11-22 08:05:11 +01:00
|
|
|
CpuIndex = GetCpuIndex ();
|
|
|
|
GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize);
|
|
|
|
if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
|
|
|
|
(PFAddress >= GuardPageAddress) &&
|
|
|
|
(PFAddress < (GuardPageAddress + EFI_PAGE_SIZE))) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n"));
|
|
|
|
} else {
|
|
|
|
if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%x)\n", PFAddress));
|
|
|
|
DEBUG_CODE (
|
|
|
|
DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
DEBUG ((DEBUG_ERROR, "SMM exception at access (0x%x)\n", PFAddress));
|
|
|
|
DEBUG_CODE (
|
|
|
|
DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
|
|
|
|
);
|
|
|
|
}
|
2018-08-20 05:35:58 +02:00
|
|
|
|
|
|
|
if (HEAP_GUARD_NONSTOP_MODE) {
|
|
|
|
GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
|
|
|
|
goto Exit;
|
|
|
|
}
|
2016-11-22 08:05:11 +01:00
|
|
|
}
|
2015-10-19 21:13:13 +02:00
|
|
|
CpuDeadLoop ();
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
goto Exit;
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2017-12-06 12:02:04 +01:00
|
|
|
// If a page fault occurs in non-SMRAM range.
|
2015-10-19 21:13:13 +02:00
|
|
|
//
|
|
|
|
if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
|
|
|
|
(PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
|
|
|
|
if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
|
2017-12-06 12:02:04 +01:00
|
|
|
DumpCpuContext (InterruptType, SystemContext);
|
2016-10-23 17:19:52 +02:00
|
|
|
DEBUG ((DEBUG_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
|
2015-10-19 21:13:13 +02:00
|
|
|
DEBUG_CODE (
|
|
|
|
DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
|
|
|
|
);
|
|
|
|
CpuDeadLoop ();
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
goto Exit;
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
2018-08-20 05:35:58 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// If NULL pointer was just accessed
|
|
|
|
//
|
|
|
|
if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&
|
|
|
|
(PFAddress < EFI_PAGE_SIZE)) {
|
|
|
|
DumpCpuContext (InterruptType, SystemContext);
|
|
|
|
DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));
|
|
|
|
DEBUG_CODE (
|
|
|
|
DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
|
|
|
|
);
|
|
|
|
|
|
|
|
if (NULL_DETECTION_NONSTOP_MODE) {
|
|
|
|
GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
CpuDeadLoop ();
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
goto Exit;
|
2018-08-20 05:35:58 +02:00
|
|
|
}
|
|
|
|
|
2016-11-24 06:36:56 +01:00
|
|
|
if (IsSmmCommBufferForbiddenAddress (PFAddress)) {
|
2017-12-06 12:02:04 +01:00
|
|
|
DumpCpuContext (InterruptType, SystemContext);
|
2016-11-24 06:36:56 +01:00
|
|
|
DEBUG ((DEBUG_ERROR, "Access SMM communication forbidden address (0x%x)!\n", PFAddress));
|
|
|
|
DEBUG_CODE (
|
|
|
|
DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
|
|
|
|
);
|
|
|
|
CpuDeadLoop ();
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
goto Exit;
|
2016-11-24 06:36:56 +01:00
|
|
|
}
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
|
|
|
SmmProfilePFHandler (
|
|
|
|
SystemContext.SystemContextIa32->Eip,
|
|
|
|
SystemContext.SystemContextIa32->ExceptionData
|
|
|
|
);
|
|
|
|
} else {
|
2017-04-01 13:39:22 +02:00
|
|
|
DumpCpuContext (InterruptType, SystemContext);
|
2015-10-19 21:13:13 +02:00
|
|
|
SmiDefaultPFHandler ();
|
|
|
|
}
|
|
|
|
|
2018-08-20 05:35:58 +02:00
|
|
|
Exit:
|
2016-03-22 03:15:53 +01:00
|
|
|
ReleaseSpinLock (mPFLock);
|
2015-10-19 21:13:13 +02:00
|
|
|
}
|
2016-10-23 17:19:52 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
This function sets memory attribute for page table.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
SetPageTableAttributes (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN Index2;
|
|
|
|
UINTN Index3;
|
|
|
|
UINT64 *L1PageTable;
|
|
|
|
UINT64 *L2PageTable;
|
|
|
|
UINT64 *L3PageTable;
|
|
|
|
BOOLEAN IsSplitted;
|
|
|
|
BOOLEAN PageTableSplitted;
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
BOOLEAN CetEnabled;
|
2016-10-23 17:19:52 +02:00
|
|
|
|
2017-11-20 09:14:10 +01:00
|
|
|
//
|
2017-12-07 10:00:48 +01:00
|
|
|
// Don't mark page table to read-only if heap guard is enabled.
|
2017-11-20 09:14:10 +01:00
|
|
|
//
|
|
|
|
// BIT2: SMM page guard enabled
|
|
|
|
// BIT3: SMM pool guard enabled
|
|
|
|
//
|
|
|
|
if ((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) != 0) {
|
2017-12-07 10:00:48 +01:00
|
|
|
DEBUG ((DEBUG_INFO, "Don't mark page table to read-only as heap guard is enabled\n"));
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Don't mark page table to read-only if SMM profile is enabled.
|
|
|
|
//
|
|
|
|
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
|
|
|
DEBUG ((DEBUG_INFO, "Don't mark page table to read-only as SMM profile is enabled\n"));
|
2017-11-20 09:14:10 +01:00
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
2016-10-23 17:19:52 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Disable write protection, because we need mark page table to be write protected.
|
|
|
|
// We need *write* page table memory, to mark itself to be *read only*.
|
|
|
|
//
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
CetEnabled = ((AsmReadCr4() & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
|
|
|
|
if (CetEnabled) {
|
|
|
|
//
|
|
|
|
// CET must be disabled if WP is disabled.
|
|
|
|
//
|
|
|
|
DisableCet();
|
|
|
|
}
|
2016-10-23 17:19:52 +02:00
|
|
|
AsmWriteCr0 (AsmReadCr0() & ~CR0_WP);
|
|
|
|
|
|
|
|
do {
|
|
|
|
DEBUG ((DEBUG_INFO, "Start...\n"));
|
|
|
|
PageTableSplitted = FALSE;
|
|
|
|
|
|
|
|
L3PageTable = (UINT64 *)GetPageTableBase ();
|
|
|
|
|
|
|
|
SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
|
|
|
|
PageTableSplitted = (PageTableSplitted || IsSplitted);
|
|
|
|
|
|
|
|
for (Index3 = 0; Index3 < 4; Index3++) {
|
2017-02-26 18:43:07 +01:00
|
|
|
L2PageTable = (UINT64 *)(UINTN)(L3PageTable[Index3] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
|
2016-10-23 17:19:52 +02:00
|
|
|
if (L2PageTable == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
|
|
|
|
PageTableSplitted = (PageTableSplitted || IsSplitted);
|
|
|
|
|
|
|
|
for (Index2 = 0; Index2 < SIZE_4KB/sizeof(UINT64); Index2++) {
|
|
|
|
if ((L2PageTable[Index2] & IA32_PG_PS) != 0) {
|
|
|
|
// 2M
|
|
|
|
continue;
|
|
|
|
}
|
2017-02-26 18:43:07 +01:00
|
|
|
L1PageTable = (UINT64 *)(UINTN)(L2PageTable[Index2] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
|
2016-10-23 17:19:52 +02:00
|
|
|
if (L1PageTable == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
|
|
|
|
PageTableSplitted = (PageTableSplitted || IsSplitted);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (PageTableSplitted);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Enable write protection, after page table updated.
|
|
|
|
//
|
|
|
|
AsmWriteCr0 (AsmReadCr0() | CR0_WP);
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
if (CetEnabled) {
|
|
|
|
//
|
|
|
|
// re-enable CET.
|
|
|
|
//
|
|
|
|
EnableCet();
|
|
|
|
}
|
2016-10-23 17:19:52 +02:00
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
2019-04-01 10:16:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
This function returns with no action for 32 bit.
|
|
|
|
|
|
|
|
@param[out] *Cr2 Pointer to variable to hold CR2 register value.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
SaveCr2 (
|
|
|
|
OUT UINTN *Cr2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
This function returns with no action for 32 bit.
|
|
|
|
|
|
|
|
@param[in] Cr2 Value to write into CR2 register.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
RestoreCr2 (
|
|
|
|
IN UINTN Cr2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return ;
|
|
|
|
}
|