2015-10-19 21:12:53 +02:00
|
|
|
/** @file
|
|
|
|
Provides services to access SMRAM Save State Map
|
|
|
|
|
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) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
|
2023-04-07 06:29:07 +02:00
|
|
|
Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
|
|
|
|
2019-04-04 01:07:22 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2015-10-19 21:12:53 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <PiSmm.h>
|
|
|
|
|
|
|
|
#include <Library/SmmCpuFeaturesLib.h>
|
|
|
|
|
|
|
|
#include <Library/BaseLib.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
|
|
#include <Library/SmmServicesTableLib.h>
|
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
|
2016-11-28 23:13:24 +01:00
|
|
|
#include "PiSmmCpuDxeSmm.h"
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
UINT64 Signature; // Offset 0x00
|
|
|
|
UINT16 Reserved1; // Offset 0x08
|
|
|
|
UINT16 Reserved2; // Offset 0x0A
|
|
|
|
UINT16 Reserved3; // Offset 0x0C
|
|
|
|
UINT16 SmmCs; // Offset 0x0E
|
|
|
|
UINT16 SmmDs; // Offset 0x10
|
|
|
|
UINT16 SmmSs; // Offset 0x12
|
|
|
|
UINT16 SmmOtherSegment; // Offset 0x14
|
|
|
|
UINT16 Reserved4; // Offset 0x16
|
|
|
|
UINT64 Reserved5; // Offset 0x18
|
|
|
|
UINT64 Reserved6; // Offset 0x20
|
|
|
|
UINT64 Reserved7; // Offset 0x28
|
|
|
|
UINT64 SmmGdtPtr; // Offset 0x30
|
|
|
|
UINT32 SmmGdtSize; // Offset 0x38
|
|
|
|
UINT32 Reserved8; // Offset 0x3C
|
|
|
|
UINT64 Reserved9; // Offset 0x40
|
|
|
|
UINT64 Reserved10; // Offset 0x48
|
|
|
|
UINT16 Reserved11; // Offset 0x50
|
|
|
|
UINT16 Reserved12; // Offset 0x52
|
|
|
|
UINT32 Reserved13; // Offset 0x54
|
|
|
|
UINT64 Reserved14; // Offset 0x58
|
|
|
|
} PROCESSOR_SMM_DESCRIPTOR;
|
|
|
|
|
|
|
|
extern CONST PROCESSOR_SMM_DESCRIPTOR gcPsd;
|
|
|
|
|
2015-10-19 21:12:53 +02:00
|
|
|
//
|
|
|
|
// EFER register LMA bit
|
|
|
|
//
|
|
|
|
#define LMA BIT10
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Variables from SMI Handler
|
|
|
|
///
|
2018-02-01 23:01:08 +01:00
|
|
|
X86_ASSEMBLY_PATCH_LABEL gPatchSmbase;
|
2018-02-01 23:23:59 +01:00
|
|
|
X86_ASSEMBLY_PATCH_LABEL gPatchSmiStack;
|
2018-02-01 23:40:29 +01:00
|
|
|
X86_ASSEMBLY_PATCH_LABEL gPatchSmiCr3;
|
2018-02-01 23:01:08 +01:00
|
|
|
extern volatile UINT8 gcSmiHandlerTemplate[];
|
|
|
|
extern CONST UINT16 gcSmiHandlerSize;
|
2015-10-19 21:12:53 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Variables used by SMI Handler
|
|
|
|
//
|
|
|
|
IA32_DESCRIPTOR gSmiHandlerIdtr;
|
|
|
|
|
|
|
|
///
|
|
|
|
/// The mode of the CPU at the time an SMI occurs
|
|
|
|
///
|
|
|
|
UINT8 mSmmSaveStateRegisterLma;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Get the size of the SMI Handler in bytes.
|
|
|
|
|
|
|
|
@retval The size, in bytes, of the SMI Handler.
|
|
|
|
|
|
|
|
**/
|
|
|
|
UINTN
|
|
|
|
EFIAPI
|
|
|
|
GetSmiHandlerSize (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN Size;
|
|
|
|
|
|
|
|
Size = SmmCpuFeaturesGetSmiHandlerSize ();
|
|
|
|
if (Size != 0) {
|
|
|
|
return Size;
|
|
|
|
}
|
2021-12-05 23:54:17 +01:00
|
|
|
|
2015-10-19 21:12:53 +02:00
|
|
|
return gcSmiHandlerSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Install the SMI handler for the CPU specified by CpuIndex. This function
|
|
|
|
is called by the CPU that was elected as monarch during System Management
|
|
|
|
Mode initialization.
|
|
|
|
|
|
|
|
@param[in] CpuIndex The index of the CPU to install the custom SMI handler.
|
|
|
|
The value must be between 0 and the NumberOfCpus field
|
|
|
|
in the System Management System Table (SMST).
|
|
|
|
@param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
|
|
|
|
@param[in] SmiStack The stack to use when an SMI is processed by the
|
|
|
|
the CPU specified by CpuIndex.
|
|
|
|
@param[in] StackSize The size, in bytes, if the stack used when an SMI is
|
|
|
|
processed by the CPU specified by CpuIndex.
|
|
|
|
@param[in] GdtBase The base address of the GDT to use when an SMI is
|
|
|
|
processed by the CPU specified by CpuIndex.
|
|
|
|
@param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
|
|
|
|
processed by the CPU specified by CpuIndex.
|
|
|
|
@param[in] IdtBase The base address of the IDT to use when an SMI is
|
|
|
|
processed by the CPU specified by CpuIndex.
|
|
|
|
@param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
|
|
|
|
processed by the CPU specified by CpuIndex.
|
|
|
|
@param[in] Cr3 The base address of the page tables to use when an SMI
|
|
|
|
is processed by the CPU specified by CpuIndex.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
InstallSmiHandler (
|
|
|
|
IN UINTN CpuIndex,
|
|
|
|
IN UINT32 SmBase,
|
|
|
|
IN VOID *SmiStack,
|
|
|
|
IN UINTN StackSize,
|
|
|
|
IN UINTN GdtBase,
|
|
|
|
IN UINTN GdtSize,
|
|
|
|
IN UINTN IdtBase,
|
|
|
|
IN UINTN IdtSize,
|
|
|
|
IN UINT32 Cr3
|
|
|
|
)
|
|
|
|
{
|
2016-11-28 23:13:24 +01:00
|
|
|
PROCESSOR_SMM_DESCRIPTOR *Psd;
|
2018-02-01 23:23:59 +01:00
|
|
|
UINT32 CpuSmiStack;
|
2016-11-28 23:13:24 +01:00
|
|
|
|
2016-12-06 01:53:33 +01:00
|
|
|
//
|
|
|
|
// Initialize PROCESSOR_SMM_DESCRIPTOR
|
|
|
|
//
|
2017-02-17 04:54:10 +01:00
|
|
|
Psd = (PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + SMM_PSD_OFFSET);
|
2016-12-06 01:53:33 +01:00
|
|
|
CopyMem (Psd, &gcPsd, sizeof (gcPsd));
|
|
|
|
Psd->SmmGdtPtr = (UINT64)GdtBase;
|
|
|
|
Psd->SmmGdtSize = (UINT32)GdtSize;
|
|
|
|
|
2015-10-19 21:12:53 +02:00
|
|
|
if (SmmCpuFeaturesGetSmiHandlerSize () != 0) {
|
|
|
|
//
|
|
|
|
// Install SMI handler provided by library
|
|
|
|
//
|
|
|
|
SmmCpuFeaturesInstallSmiHandler (
|
|
|
|
CpuIndex,
|
|
|
|
SmBase,
|
|
|
|
SmiStack,
|
|
|
|
StackSize,
|
|
|
|
GdtBase,
|
|
|
|
GdtSize,
|
|
|
|
IdtBase,
|
|
|
|
IdtSize,
|
|
|
|
Cr3
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
InitShadowStack (CpuIndex, (VOID *)((UINTN)SmiStack + StackSize));
|
|
|
|
|
2015-10-19 21:12:53 +02:00
|
|
|
//
|
|
|
|
// Initialize values in template before copy
|
|
|
|
//
|
2018-02-01 23:23:59 +01:00
|
|
|
CpuSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
|
|
|
|
PatchInstructionX86 (gPatchSmiStack, CpuSmiStack, 4);
|
2018-02-01 23:40:29 +01:00
|
|
|
PatchInstructionX86 (gPatchSmiCr3, Cr3, 4);
|
2018-02-01 23:01:08 +01:00
|
|
|
PatchInstructionX86 (gPatchSmbase, SmBase, 4);
|
2015-10-19 21:12:53 +02:00
|
|
|
gSmiHandlerIdtr.Base = IdtBase;
|
|
|
|
gSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set the value at the top of the CPU stack to the CPU Index
|
|
|
|
//
|
2018-02-01 23:23:59 +01:00
|
|
|
*(UINTN *)(UINTN)CpuSmiStack = CpuIndex;
|
2015-10-19 21:12:53 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Copy template to CPU specific SMI handler location
|
|
|
|
//
|
|
|
|
CopyMem (
|
2017-02-17 04:54:10 +01:00
|
|
|
(VOID *)((UINTN)SmBase + SMM_HANDLER_OFFSET),
|
2015-10-19 21:12:53 +02:00
|
|
|
(VOID *)gcSmiHandlerTemplate,
|
|
|
|
gcSmiHandlerSize
|
|
|
|
);
|
|
|
|
}
|