From: Jian J Wang <jian.j.wang@intel.com>
To: edk2-devel@lists.01.org
Cc: Michael D Kinney <michael.d.kinney@intel.com>,
Liming Gao <liming.gao@intel.com>,
Jiewen Yao <jiewen.yao@intel.com>, Andrew Fish <afish@apple.com>
Subject: [PATCH] MdePkg/BaseStackCheckLib: add MSFT toolchain support
Date: Tue, 16 Oct 2018 08:55:18 +0800 [thread overview]
Message-ID: <20181016005518.5264-1-jian.j.wang@intel.com> (raw)
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.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Andrew Fish <afish@apple.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@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
next reply other threads:[~2018-10-16 0:55 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-16 0:55 Jian J Wang [this message]
2018-10-16 0:59 ` [PATCH] MdePkg/BaseStackCheckLib: add MSFT toolchain support Wang, Jian J
2018-10-18 1:18 ` Wang, Jian J
2018-10-18 1:22 ` Gao, Liming
2018-10-18 1:36 ` Kinney, Michael D
2018-10-18 2:15 ` Wang, Jian J
2018-10-18 23:16 ` Kinney, Michael D
2018-10-19 1:02 ` Wang, Jian J
2018-10-30 2:53 ` Wang, Jian J
2018-10-18 6:35 ` Wang, Jian J
2018-10-19 0:05 ` Kinney, Michael D
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181016005518.5264-1-jian.j.wang@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox