REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1239
Regards, Jian > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] > Sent: Tuesday, October 16, 2018 8:55 AM > To: edk2-devel@lists.01.org > Cc: Kinney, Michael D <michael.d.kin...@intel.com>; Yao, Jiewen > <jiewen....@intel.com>; Andrew Fish <af...@apple.com>; Gao, Liming > <liming....@intel.com> > Subject: [edk2] [PATCH] MdePkg/BaseStackCheckLib: add MSFT toolchain > support > > This patch adds stack check support for MSFT toolchain, with > compiler option /GS and /RTCs. This functionality is similar > to the original ones supported by GCC toolchain. > > Usage example: > This is a NULL library instance. Add it under a [LibraryClasses] > section in dsc file to let it be built into all modules employed > in a platform. > > [LibraryClasses] > NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf > > Please note all not modules can be built against this library. Most > of them are SEC type of modules, such as > > OvmfPkg/ResetVector/ResetVector.inf > > In this case, this library should not be added to a common > [LibraryClasses] section but to specific ones, like > [LibraryClasses.common.PEI_CORE/PEIM/...]. > > In addition, /GS and/or /RTCs should be added to compiler command line. > This can be done by adding something like below under [BuildOptions] > section in dsc file. > > [BuildOptions] > MSFT:DEBUG_*_*_CC_FLAGS = /GS /GL- > MSFT:DEBUG_*_*_CC_FLAGS = /RTCs /Od > > Note: /GL- is required for /GS, and /Od is required for /RTCs. > Note: The flash layout might be needed to update to accommodate larger > image size due to /Od is enforced. > > Pass tests: > a. Overwrite a local buffer variable (in a 32-bit and 64-bit driver)and > check if it's caught by new code (on both real platform and virtual > platform) > b. Boot Windows 10 and Ubuntu 18.04 on real platform with this > lib built-in > > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Liming Gao <liming....@intel.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Andrew Fish <af...@apple.com> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Jian J Wang <jian.j.w...@intel.com> > --- > .../BaseStackCheckLib/BaseStackCheckLib.inf | 11 +- > .../Library/BaseStackCheckLib/BaseStackCheckMsft.c | 221 > +++++++++++++++++++++ > .../Library/BaseStackCheckLib/BaseStackCheckNull.c | 15 -- > .../BaseStackCheckLib/Ia32/StackCheckStubAsm.nasm | 76 +++++++ > .../BaseStackCheckLib/X64/StackCheckStubAsm.nasm | 54 +++++ > 5 files changed, 360 insertions(+), 17 deletions(-) > create mode 100644 > MdePkg/Library/BaseStackCheckLib/BaseStackCheckMsft.c > delete mode 100644 MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c > create mode 100644 > MdePkg/Library/BaseStackCheckLib/Ia32/StackCheckStubAsm.nasm > create mode 100644 > MdePkg/Library/BaseStackCheckLib/X64/StackCheckStubAsm.nasm > > diff --git a/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf > b/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf > index e280651b11..1c9e6710c6 100644 > --- a/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf > +++ b/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf > @@ -4,6 +4,7 @@ > # Stack Check Library > # > # Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> > +# Copyright (c) 2018, 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 > @@ -26,13 +27,19 @@ > > > # > -# VALID_ARCHITECTURES = ARM AARCH64 > +# VALID_ARCHITECTURES = ARM AARCH64 IA32 X64 > # > > [Sources] > BaseStackCheckGcc.c | GCC > BaseStackCheckGcc.c | RVCT > - BaseStackCheckNull.c | MSFT > + BaseStackCheckMsft.c | MSFT > + > +[Sources.IA32] > + Ia32/StackCheckStubAsm.nasm | MSFT > + > +[Sources.X64] > + X64/StackCheckStubAsm.nasm | MSFT > > [Packages] > MdePkg/MdePkg.dec > diff --git a/MdePkg/Library/BaseStackCheckLib/BaseStackCheckMsft.c > b/MdePkg/Library/BaseStackCheckLib/BaseStackCheckMsft.c > new file mode 100644 > index 0000000000..951154f0cd > --- /dev/null > +++ b/MdePkg/Library/BaseStackCheckLib/BaseStackCheckMsft.c > @@ -0,0 +1,221 @@ > +/** @file > + Base Stack Check library for MSFT toolchains compiler options: /GS, RTCs. > + > +Copyright (c) 2018, 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 that accompanies this > distribution. > +The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php. > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > + > +**/ > + > +#include <Base.h> > + > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/PcdLib.h> > + > +// > +// cookie value that is inserted by the MSFT compiler into the stack frame. > +// > +extern UINTN __security_cookie; > + > +// > +// Data structure used by MSFT compiler to record local variable information. > +// > + > +typedef struct _RTC_vardesc { > + int Addr; > + int Size; > + char *Name; > +} _RTC_vardesc; > + > +typedef struct _RTC_framedesc { > + int VarCount; > + _RTC_vardesc *Variables; > +} _RTC_framedesc; > + > +#define RTC_STACK_CHECK_COOKIE 0xCCCCCCCC > + > +/** > + Function called upon unexpected stack pointer change. > + > + @param Ip Instruction address where the check happened. > + > +**/ > +VOID > +__cdecl > +_RTC_Failure ( > + VOID *Ip > + ) > +{ > + DEBUG ((DEBUG_ERROR, "\nSTACK FAULT: Suspicious stack pointer > (IP:%p).\n\n", Ip)); > + > + // > + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings even if > + // BaseDebugLibNull is in use. > + // > + if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { > + CpuBreakpoint (); > + } else { > + // > + // Usually the boot should stop here if check failure. Due to the fact > + // that the normal Stack Switch happened in boot will also fail the stack > + // pointer check. So no dead loop here. > + // > + } > + return; > +} > + > +/** > + Function reporting stack buffer overlow. > + > + @param Name Local varible name. > + @param Ip Instruction address where the check happened. > + > +**/ > +STATIC > +VOID > +_RTC_StackFailure ( > + CHAR8 *Name, > + VOID *Ip > + ) > +{ > + DEBUG ((DEBUG_ERROR, "\nSTACK FAULT: Local variable '%a' overflow > (IP:%p).\n\n", Name, Ip)); > + > + // > + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings even if > + // BaseDebugLibNull is in use. > + // > + if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { > + CpuBreakpoint (); > + } else if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { > + CpuDeadLoop (); > + } > + return ; > +} > + > +/** > + Function called upon stack buffer overflow. (/RTCs) > + > + @param _Esp Stack frame pointer. > + @param _Fd Pointer to local variable information. > + > +**/ > +VOID > +__fastcall > +_RTC_CheckStackVars ( > + VOID *_Esp, > + _RTC_framedesc *_Fd > + ) > +{ > + INTN Index; > + UINT8 *Addr; > + > + for (Index = 0; Index < _Fd->VarCount; Index++) { > + Addr = (UINT8 *)_Esp + _Fd->Variables[Index].Addr - sizeof(UINT32); > + if (*(UINT32 *)Addr != RTC_STACK_CHECK_COOKIE) { > + _RTC_StackFailure (_Fd->Variables[Index].Name, RETURN_ADDRESS(0)); > + } > + > + Addr = (UINT8 *)_Esp + _Fd->Variables[Index].Addr + _Fd- > >Variables[Index].Size; > + if (*(UINT32 *)Addr != RTC_STACK_CHECK_COOKIE) { > + _RTC_StackFailure (_Fd->Variables[Index].Name, RETURN_ADDRESS(0)); > + } > + } > +} > + > +/** > + Function required by linker but not implemented by firmware image loader. > (/RTCs) > + > +**/ > +VOID > +__cdecl > +_RTC_Shutdown ( > + VOID > + ) > +{ > + return; > +} > + > +/** > + Function required by linker but not implemented by firmware image loader. > (/RTCs) > + > +**/ > +VOID > +__cdecl > +_RTC_InitBase ( > + VOID > + ) > +{ > + return; > +} > + > + > +/** > + Function called upon stack frame overflow detected. (/GS) > + > + @param StackCookie Actual cookie value got from stack boundary. > + @param Ip Instruction address where the check happened. > + > +**/ > +NORETURN > +VOID > +__cdecl > +__report_gsfailure ( > + UINTN StackCookie, > + VOID *Ip > + ) > +{ > + DEBUG ((DEBUG_ERROR, "\nSTACK FAULT: Stack overflow check failed in > cookie checker (IP:%p).\n\n", Ip)); > + > + // > + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings even if > + // BaseDebugLibNull is in use. > + // > + if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { > + CpuBreakpoint (); > + } else if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { > + CpuDeadLoop (); > + } > +} > + > +/** > + Function called upon failure at local array range check . (/GS) > + > +**/ > +NORETURN > +VOID > +__cdecl > +__report_rangecheckfailure ( > + VOID > + ) > +{ > + DEBUG((DEBUG_ERROR, "\nSTACK FAULT: Range check check failed in cookie > checker.\n\n")); > + > + // > + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings even if > + // BaseDebugLibNull is in use. > + // > + if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { > + CpuBreakpoint (); > + } else if ((PcdGet8 (PcdDebugPropertyMask) & > DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { > + CpuDeadLoop (); > + } > +} > + > +/** > + Function required by linker but not implemented by firmware image loader. > (/GS) > + > +**/ > +VOID > +__GSHandlerCheck ( > + VOID > + ) > +{ > + return; > +} > + > diff --git a/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c > b/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c > deleted file mode 100644 > index 7c27c73e23..0000000000 > --- a/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c > +++ /dev/null > @@ -1,15 +0,0 @@ > -/** @file > - This file is purely empty as a work around for BaseStackCheck to pass MSVC > build. > - > - Copyright (c) 2018, 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 > - http://opensource.org/licenses/bsd-license.php. > - > - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > - > -**/ > - > -extern int __BaseStackCheckNull; > diff --git a/MdePkg/Library/BaseStackCheckLib/Ia32/StackCheckStubAsm.nasm > b/MdePkg/Library/BaseStackCheckLib/Ia32/StackCheckStubAsm.nasm > new file mode 100644 > index 0000000000..d3c8d32161 > --- /dev/null > +++ b/MdePkg/Library/BaseStackCheckLib/Ia32/StackCheckStubAsm.nasm > @@ -0,0 +1,76 @@ > +;------------------------------------------------------------------------------ > ; > +; Copyright (c) 2018, 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 > +; http://opensource.org/licenses/bsd-license.php. > +; > +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +; > +; Module Name: > +; > +; StackCheckStubAsm.nasm > +; > +; Abstract: > +; > +; Stub globals and functions for compiler options /GS, /RTCs > +; > +; Notes: > +; > +;------------------------------------------------------------------------------ > + > +; > +; __declspec(noreturn) void __cdecl __report_gsfailure(UINTN cookie, void > *ip); > +; > +extern ___report_gsfailure > +; > +; void __cdecl _RTC_Failure (void *Ip); > +; > +extern __RTC_Failure > + > +SECTION .data > + > +; > +; UINTN __security_cookie; > +; > +global ___security_cookie > +___security_cookie: > + DW 987974FAh > + > +SECTION .text > + > +; > +; void __fastcall __security_check_cookie(UINTN cookie) > +; > +; Note: __fastcall calling convention uses ecx/edx to pass first two > parameters > +; > +global @__security_check_cookie@4 > +@__security_check_cookie@4: > + push ebp > + mov ebp, esp > + cmp ecx, [___security_cookie] > + je .1 > + push dword [ebp] ; pass return address as the second parameter > + push ecx ; cookie value in stack is the first parameter > + call ___report_gsfailure > +.1: > + mov esp, ebp > + pop ebp > + ret > + > +; > +; void __declspec(naked) __cdecl _RTC_CheckEsp(void) > +; > +global __RTC_CheckEsp > +__RTC_CheckEsp: > + push ebp > + mov ebp, esp > + je .1 > + push dword [ebp] ; pass return address to __RTC_Failure > + call __RTC_Failure > +.1: > + mov esp, ebp > + pop ebp > + ret > + > diff --git a/MdePkg/Library/BaseStackCheckLib/X64/StackCheckStubAsm.nasm > b/MdePkg/Library/BaseStackCheckLib/X64/StackCheckStubAsm.nasm > new file mode 100644 > index 0000000000..1c8601f09c > --- /dev/null > +++ b/MdePkg/Library/BaseStackCheckLib/X64/StackCheckStubAsm.nasm > @@ -0,0 +1,54 @@ > +;------------------------------------------------------------------------------ > ; > +; Copyright (c) 2018, 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 > +; http://opensource.org/licenses/bsd-license.php. > +; > +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +; > +; Module Name: > +; > +; StackCheckStubAsm.nasm > +; > +; Abstract: > +; > +; Stub globals and functions for compiler options /GS, /RTCs > +; > +; Notes: > +; > +;------------------------------------------------------------------------------ > + > +; > +; __declspec(noreturn) void __cdecl __report_gsfailure(UINTN cookie, void > *ip); > +; > +extern __report_gsfailure > + > +DEFAULT REL > + > +SECTION .data > + > +; > +; UINTN __security_cookie; > +; > +global __security_cookie > +__security_cookie: > + DQ 0CFE3FE6A3F5C5A88h > + > +SECTION .text > + > +; > +; void __fastcall __security_check_cookie(UINTN cookie) > +; > +; Note: __fastcall calling convention uses ecx/edx to pass first two > parameters > +; > +global __security_check_cookie > +__security_check_cookie: > + cmp rcx, qword [__security_cookie] > + je .1 > + mov rdx, [esp] ; pass return address as the second parameter > + call __report_gsfailure > +.1 > + ret > + > -- > 2.16.2.windows.1 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel