diff options
author | Jiewen Yao <jiewen.yao@intel.com> | 2019-02-22 21:30:36 +0800 |
---|---|---|
committer | Liming Gao <liming.gao@intel.com> | 2019-02-28 09:39:54 +0800 |
commit | 3eb69b081c683f9d825930d0c511e43c0485e5d2 (patch) | |
tree | 9d89e793207e6e82c98d09b20c12a8b7a728f1b4 /UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | |
parent | 0d25074cbcc272532d6ca5a47974ac5b31f4b6ec (diff) | |
download | edk2-3eb69b081c683f9d825930d0c511e43c0485e5d2.tar.gz edk2-3eb69b081c683f9d825930d0c511e43c0485e5d2.tar.bz2 edk2-3eb69b081c683f9d825930d0c511e43c0485e5d2.zip |
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>
Diffstat (limited to 'UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c')
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 85 |
1 files changed, 84 insertions, 1 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index 684b14dc28..48f5f954cb 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -1,6 +1,6 @@ /** @file
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -38,6 +38,23 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = { {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},
};
+UINTN mInternalGr3;
+
+/**
+ Set the internal page table base address.
+ If it is non zero, further MemoryAttribute modification will be on this page table.
+ If it is zero, further MemoryAttribute modification will be on real page table.
+
+ @param Cr3 page table base.
+**/
+VOID
+SetPageTableBase (
+ IN UINTN Cr3
+ )
+{
+ mInternalGr3 = Cr3;
+}
+
/**
Return page table base.
@@ -48,6 +65,9 @@ GetPageTableBase ( VOID
)
{
+ if (mInternalGr3 != 0) {
+ return mInternalGr3;
+ }
return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
}
@@ -220,6 +240,17 @@ ConvertPageEntryAttribute ( if ((Attributes & EFI_MEMORY_RO) != 0) {
if (IsSet) {
NewPageEntry &= ~(UINT64)IA32_PG_RW;
+ if (mInternalGr3 != 0) {
+ // Environment setup
+ // ReadOnly page need set Dirty bit for shadow stack
+ NewPageEntry |= IA32_PG_D;
+ // Clear user bit for supervisor shadow stack
+ NewPageEntry &= ~(UINT64)IA32_PG_U;
+ } else {
+ // Runtime update
+ // Clear dirty bit for non shadow stack, to protect RO page.
+ NewPageEntry &= ~(UINT64)IA32_PG_D;
+ }
} else {
NewPageEntry |= IA32_PG_RW;
}
@@ -661,7 +692,59 @@ SmmClearMemoryAttributes ( return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, NULL);
}
+/**
+ Set ShadowStack memory.
+
+ @param[in] Cr3 The page table base address.
+ @param[in] BaseAddress The physical address that is the start address of a memory region.
+ @param[in] Length The size in bytes of the memory region.
+
+ @retval EFI_SUCCESS The shadow stack memory is set.
+**/
+EFI_STATUS
+SetShadowStack (
+ IN UINTN Cr3,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ EFI_STATUS Status;
+
+ SetPageTableBase (Cr3);
+
+ Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);
+
+ SetPageTableBase (0);
+
+ return Status;
+}
+
+/**
+ Set not present memory.
+
+ @param[in] Cr3 The page table base address.
+ @param[in] BaseAddress The physical address that is the start address of a memory region.
+ @param[in] Length The size in bytes of the memory region.
+ @retval EFI_SUCCESS The not present memory is set.
+**/
+EFI_STATUS
+SetNotPresentPage (
+ IN UINTN Cr3,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ EFI_STATUS Status;
+
+ SetPageTableBase (Cr3);
+
+ Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RP);
+
+ SetPageTableBase (0);
+
+ return Status;
+}
/**
Retrieves a pointer to the system configuration table from the SMM System Table
|