├── .gitignore ├── Compiler-Impl ├── Makefile ├── configure.sh ├── sanitizer_common.patch ├── scripts │ ├── cmake_debug.sh │ ├── cmake_release.sh │ ├── cxx_build.sh │ ├── debug_libunwind_cmake.sh │ ├── get_llvm_src_tree.sh │ ├── install-shadowstack-files.sh │ ├── libcxx_cmake.sh │ ├── libcxxabi_cmake.sh │ ├── libunwind_cmake.sh │ ├── libunwind_release_cmake.sh │ ├── rebuild_debug.sh │ ├── release_libcxx_cmake.sh │ └── release_libcxxabi_cmake.sh └── src │ ├── CommonArgs.cpp │ ├── Makefile │ ├── NOTES │ ├── ShadowStackConstants.h │ ├── ShadowStackFeatures.h │ ├── UnwindRegistersRestore.S │ ├── X86.h │ ├── X86FunctionCountPass.cpp │ ├── X86MCInstLower.cpp │ ├── X86RegisterInfo.cpp │ ├── X86ShadowStackCon.cpp │ ├── X86ShadowStackMPX.cpp │ ├── X86ShadowStackMem.cpp │ ├── X86ShadowStackReg.cpp │ ├── X86ShadowStackSeg.cpp │ ├── X86TargetMachine.cpp │ ├── crash_clang.c │ ├── crt-lib-CMakeLists.txt │ ├── exceptions.cpp │ ├── fib.c │ ├── fib_driver.c │ ├── fib_mpk.c │ ├── longjmp.s │ ├── main.c │ ├── mpk.h │ ├── mpk_example.c │ ├── no_exceptions.cpp │ ├── pthread_create.c │ ├── setjmp.s │ ├── shadowstack │ ├── CMakeLists.txt │ ├── config_mpx.h │ ├── mpk.h │ ├── mpxrt-utils.c │ ├── mpxrt-utils.h │ ├── mpxrt.h │ └── shadow_stack.c │ ├── stackoverflow.c │ └── x86-CMakeLists.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore cloned repositories 2 | Compiler-Impl/clang/ 3 | Compiler-Impl/compiler-rt/ 4 | Compiler-Impl/debug-build/ 5 | Compiler-Impl/libcxx/ 6 | Compiler-Impl/libcxxabi/ 7 | Compiler-Impl/libunwind-debug-build/ 8 | Compiler-Impl/libunwind-release-build/ 9 | Compiler-Impl/libunwind/ 10 | Compiler-Impl/llvm/ 11 | Compiler-Impl/musl/ 12 | 13 | # Ignore generated setjmp/longjmp assembly files 14 | Compiler-Impl/src/shadowstack/longjmp.s 15 | Compiler-Impl/src/shadowstack/setjmp.s 16 | 17 | # Ignore build/install directories 18 | Compiler-Impl/debug-build/ 19 | Compiler-Impl/debug-install/ 20 | Compiler-Impl/release-build/ 21 | Compiler-Impl/release-install/ -------------------------------------------------------------------------------- /Compiler-Impl/Makefile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | all: 4 | rm -rf debug-install 5 | mkdir debug-install 6 | ninja -C ./debug-build install 7 | ninja -C ./libunwind-debug-build install 8 | 9 | #ninja -C ./libcxxabi-debug-build clean 10 | #ninja -C ./libcxx-debug-build clean 11 | 12 | #ninja -C ./libcxxabi-debug-build install 13 | #ninja -C ./libcxx-debug-build install 14 | 15 | release: 16 | ninja -C ./release-build install 17 | ninja -C ./libunwind-release-build install 18 | ninja -C ./libcxxabi-release-build clean 19 | ninja -C ./libcxx-release-build clean 20 | ninja -C ./libcxxabi-release-build install 21 | ninja -C ./libcxx-release-build install 22 | -------------------------------------------------------------------------------- /Compiler-Impl/configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export base=`pwd` 5 | 6 | scripts/get_llvm_src_tree.sh 7 | scripts/install-shadowstack-files.sh 8 | 9 | 10 | mkdir -p debug-build 11 | mkdir -p release-build 12 | 13 | cd debug-build 14 | ../scripts/cmake_debug.sh 15 | 16 | cd ../release-build 17 | ../scripts/cmake_release.sh 18 | 19 | #cd ../musl 20 | #CC=$base/debug-install/bin/clang ./configure --enable-debug --disable-shared --prefix=$base/debug-install 21 | -------------------------------------------------------------------------------- /Compiler-Impl/sanitizer_common.patch: -------------------------------------------------------------------------------- 1 | diff -Naur /home/matthew/git/hexhive/ShadowStack/Compiler-Impl/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc 2 | --- /home/matthew/git/hexhive/ShadowStack/Compiler-Impl/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc 2020-05-02 00:34:47.291702306 +0000 3 | +++ compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc 2020-05-01 02:46:00.589308186 +0000 4 | @@ -159,7 +159,7 @@ 5 | # include 6 | #endif 7 | #include 8 | -#include 9 | + 10 | #include 11 | #include 12 | #include 13 | @@ -253,7 +253,19 @@ 14 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD 15 | 16 | #if SANITIZER_LINUX && !SANITIZER_ANDROID 17 | - unsigned struct_ustat_sz = sizeof(struct ustat); 18 | + // Use pre-computed size of struct ustat to avoid which 19 | + // has been removed from glibc 2.28. 20 | +#if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \ 21 | + || defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \ 22 | + || defined(__x86_64__) 23 | +#define SIZEOF_STRUCT_USTAT 32 24 | +#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \ 25 | + || defined(__powerpc__) || defined(__s390__) 26 | +#define SIZEOF_STRUCT_USTAT 20 27 | +#else 28 | +#error Unknown size of struct ustat 29 | +#endif 30 | + unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT; 31 | unsigned struct_rlimit64_sz = sizeof(struct rlimit64); 32 | unsigned struct_statvfs64_sz = sizeof(struct statvfs64); 33 | #endif // SANITIZER_LINUX && !SANITIZER_ANDROID 34 | @@ -1139,15 +1151,16 @@ 35 | CHECK_SIZE_AND_OFFSET(ipc_perm, key); 36 | CHECK_SIZE_AND_OFFSET(ipc_perm, seq); 37 | # else 38 | -CHECK_SIZE_AND_OFFSET(ipc_perm, __key); 39 | -CHECK_SIZE_AND_OFFSET(ipc_perm, __seq); 40 | +// CHECK_SIZE_AND_OFFSET(ipc_perm, __key); 41 | +// CHECK_SIZE_AND_OFFSET(ipc_perm, __seq); 42 | # endif 43 | CHECK_SIZE_AND_OFFSET(ipc_perm, uid); 44 | CHECK_SIZE_AND_OFFSET(ipc_perm, gid); 45 | CHECK_SIZE_AND_OFFSET(ipc_perm, cuid); 46 | CHECK_SIZE_AND_OFFSET(ipc_perm, cgid); 47 | -#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21) 48 | -/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */ 49 | +#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31) 50 | +/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit 51 | + on many architectures. */ 52 | CHECK_SIZE_AND_OFFSET(ipc_perm, mode); 53 | #endif 54 | 55 | diff -Naur /home/matthew/git/hexhive/ShadowStack/Compiler-Impl/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h 56 | --- /home/matthew/git/hexhive/ShadowStack/Compiler-Impl/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h 2020-05-02 00:34:47.291702306 +0000 57 | +++ compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h 2020-05-01 02:46:23.905674284 +0000 58 | @@ -213,25 +213,18 @@ 59 | u64 __unused1; 60 | u64 __unused2; 61 | #elif defined(__sparc__) 62 | -#if defined(__arch64__) 63 | + 64 | unsigned mode; 65 | - unsigned short __pad1; 66 | -#else 67 | - unsigned short __pad1; 68 | + 69 | unsigned short mode; 70 | unsigned short __pad2; 71 | -#endif 72 | + 73 | unsigned short __seq; 74 | unsigned long long __unused1; 75 | unsigned long long __unused2; 76 | -#elif defined(__mips__) || defined(__aarch64__) || defined(__s390x__) 77 | - unsigned int mode; 78 | - unsigned short __seq; 79 | - unsigned short __pad1; 80 | - unsigned long __unused1; 81 | - unsigned long __unused2; 82 | + 83 | #else 84 | - unsigned short mode; 85 | + unsigned int mode; 86 | unsigned short __pad1; 87 | unsigned short __seq; 88 | unsigned short __pad2; 89 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/cmake_debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | $base/scripts/libunwind_cmake.sh 4 | echo "base = "$base 5 | cd $base 6 | INSTALL_PATH=$PWD/debug-install 7 | mkdir -p $INSTALL_PATH 8 | mkdir -p debug-build 9 | cd debug-build 10 | 11 | cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug \ 12 | -DCMAKE_C_COMPILER=clang \ 13 | -DCMAKE_CXX_COMPILER=clang++ \ 14 | -DLLVM_ENABLE_ASSERTIONS=ON \ 15 | -DLLVM_BUILD_TESTS=OFF \ 16 | -DLLVM_BUILD_EXAMPLES=OFF \ 17 | -DLLVM_INCLUDE_TESTS=OFF\ 18 | -DLLVM_INCLUDE_EXAMPLES=OFF \ 19 | -DLLVM_TARGETS_TO_BUILD="X86" \ 20 | -DLLVM_ENABLE_LTO=OFF \ 21 | -DLLVM_PARALLEL_LINK_JOBS="4" \ 22 | -DCMAKE_C_FLAGS=-fstandalone-debug \ 23 | -DCMAKE_CXX_FLAGS=-fstandalone-debug \ 24 | -DBUILD_SHARED_LIBS=ON \ 25 | -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH \ 26 | -DLLVM_BINUTILS_INCDIR=/usr/include \ 27 | $base/llvm 28 | 29 | #cmake --build . 30 | 31 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/cmake_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | $base/scripts/libunwind_release_cmake.sh 5 | cd $base 6 | INSTALL_PATH=$PWD/release-install 7 | mkdir -p $INSTALL_PATH 8 | mkdir -p release-build 9 | cd release-build 10 | 11 | cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release \ 12 | -DCMAKE_C_COMPILER=/usr/bin/clang \ 13 | -DCMAKE_CXX_COMPILER=/usr/bin/clang++ \ 14 | -DLLVM_ENABLE_ASSERTIONS=OFF \ 15 | -DLLVM_BUILD_TESTS=OFF \ 16 | -DLLVM_BUILD_EXAMPLES=OFF \ 17 | -DLLVM_INCLUDE_TESTS=OFF\ 18 | -DLLVM_INCLUDE_EXAMPLES=OFF \ 19 | -DLLVM_TARGETS_TO_BUILD="X86" \ 20 | -DLLVM_PARALLEL_LINK_JOBS="4" \ 21 | -DBUILD_SHARED_LIBS=OFF \ 22 | -DLLVM_ENABLE_LTO=OFF \ 23 | -DLLVM_ENABLE_LLD=ON \ 24 | -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH \ 25 | -DLLVM_BINUTILS_INCDIR=/usr/include \ 26 | $base/llvm 27 | 28 | #cmake --build . 29 | 30 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/cxx_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | #cd .. 6 | rm -rf libcxx-build libcxxabi-build libunwind-build 7 | 8 | #order matters here 9 | mkdir libunwind-build 10 | cd libunwind-build 11 | ../scripts/libunwind_cmake.sh 12 | ninja 13 | ninja install 14 | cd .. 15 | 16 | mkdir libcxxabi-build 17 | cd libcxxabi-build 18 | ../scripts/libcxxabi_cmake.sh 19 | ninja 20 | ninja install 21 | cd .. 22 | 23 | mkdir libcxx-build 24 | cd libcxx-build 25 | ../scripts/libcxx_cmake.sh 26 | ninja 27 | ninja install 28 | cd .. 29 | 30 | set +x 31 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/debug_libunwind_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/debug-install 4 | HS_RT=$HS_SYSROOT/lib/clang/7.0.0/lib/linux 5 | cd libunwind-debug-build 6 | 7 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 8 | -DCMAKE_BUILD_TYPE=Debug \ 9 | -DCMAKE_CXX_COMPILER=$HS_SYSROOT/bin/clang++ \ 10 | -DCMAKE_C_COMPILER=$HS_SYSROOT/bin/clang \ 11 | -DCMAKE_C_FLAGS="-O0 -v" \ 12 | -DCMAKE_CXX_FLAGS="-O0 -v" \ 13 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 14 | -DLIBUNWIND_ENABLE_SHARED=ON \ 15 | ../libunwind 16 | 17 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/get_llvm_src_tree.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | command -v curl >/dev/null 2>&1 || { sudo apt-get install curl; } 3 | command -v wget >/dev/null 2>&1 || { sudo apt-get install wget; } 4 | command -v cmake >/dev/null 2>&1 || { sudo apt-get install cmake; } 5 | command -v ninja >/dev/null 2>&1 || { sudo apt-get install ninja-build; } 6 | dpkg -l libgtest-dev>/dev/null 2>&1 || { yes | sudo apt-get install libgtest-dev; } 7 | dpkg -l binutils-dev>/dev/null 2>&1 || { yes | sudo apt-get install binutils-dev; } 8 | 9 | LLVM_COMMIT=20230f9b42887e7a3a13c81731656a9bfd90c93a 10 | CLANG_COMMIT=81684cc58243b49af786438d33fcbbf12a596c56 11 | COMPILER_RT_COMMIT=e27398661ef8ea118124519a2f97ec345fcc2d6a 12 | 13 | #get LLVM 14 | git clone https://github.com/llvm-mirror/llvm.git 15 | cd llvm 16 | git checkout $LLVM_COMMIT 17 | cd .. 18 | 19 | #get Clang 20 | git clone https://github.com/llvm-mirror/clang.git 21 | cd clang 22 | git checkout $CLANG_COMMIT 23 | cd .. 24 | 25 | #get compiler-rt 26 | git clone https://github.com/llvm-mirror/compiler-rt.git 27 | cd compiler-rt 28 | git checkout $COMPILER_RT_COMMIT 29 | cd .. 30 | patch -p7 -u < sanitizer_common.patch 31 | 32 | #get libc++ 33 | wget --retry-connrefused --tries=100 releases.llvm.org/5.0.1/libcxx-5.0.1.src.tar.xz 34 | tar -xf libcxx-5.0.1.src.tar.xz 35 | mv libcxx-5.0.1.src libcxx 36 | rm libcxx-5.0.1.src.tar.xz 37 | 38 | #get libc++abi 39 | wget --retry-connrefused --tries=100 releases.llvm.org/5.0.1/libcxxabi-5.0.1.src.tar.xz 40 | tar -xf libcxxabi-5.0.1.src.tar.xz 41 | mv libcxxabi-5.0.1.src libcxxabi 42 | rm libcxxabi-5.0.1.src.tar.xz 43 | 44 | #get libunwind 45 | wget --retry-connrefused --tries=100 releases.llvm.org/5.0.1/libunwind-5.0.1.src.tar.xz 46 | tar -xf libunwind-5.0.1.src.tar.xz 47 | mv libunwind-5.0.1.src libunwind 48 | rm libunwind-5.0.1.src.tar.xz 49 | 50 | #get musl 51 | wget --retry-connrefused --tries=100 https://www.musl-libc.org/releases/musl-1.1.16.tar.gz 52 | tar -xf musl-1.1.16.tar.gz 53 | mv musl-1.1.16 musl 54 | rm musl-1.1.16.tar.gz 55 | 56 | #Set up llvm, clang, compiler-rt for inline build (will musl / libcxx separately) 57 | cd llvm/tools 58 | ln -s ../../clang . 59 | cd ../projects 60 | ln -s ../../compiler-rt . 61 | cd .. 62 | cd .. 63 | 64 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/install-shadowstack-files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #This script softlinks our modified files into the LLVM source tree 4 | 5 | #Path to llvm source tree 6 | llvm=`pwd`/llvm 7 | clang=`pwd`/clang 8 | src=`pwd`/src 9 | runtime=`pwd`/compiler-rt 10 | musl=`pwd`/musl 11 | unwind=`pwd`/libunwind 12 | 13 | #clang codegen 14 | ccg=$clang/lib/CodeGen 15 | 16 | #clang driver 17 | cdriver=$clang/lib/Driver 18 | 19 | #llvm include 20 | llvminc=$llvm/include/llvm 21 | 22 | #llvm codegen 23 | lcg=$llvm/lib/CodeGen 24 | 25 | #llvm IR 26 | lir=$llvm/lib/IR 27 | 28 | ltrans=$llvm/lib/Transforms 29 | 30 | #compiler-rt directory 31 | crtlib=$runtime/lib 32 | 33 | rm -f $llvm/lib/Target/X86/X86.h 34 | ln -s $src/X86.h $llvm/lib/Target/X86/X86.h 35 | 36 | 37 | rm -f $llvm/lib/Target/X86/X86TargetMachine.cpp 38 | ln -s $src/X86TargetMachine.cpp $llvm/lib/Target/X86/X86TargetMachine.cpp 39 | 40 | ln -s $src/X86ShadowStackMem.cpp $llvm/lib/Target/X86/X86ShadowStackMem.cpp 41 | ln -s $src/X86ShadowStackCon.cpp $llvm/lib/Target/X86/X86ShadowStackCon.cpp 42 | ln -s $src/X86ShadowStackReg.cpp $llvm/lib/Target/X86/X86ShadowStackReg.cpp 43 | ln -s $src/X86ShadowStackSeg.cpp $llvm/lib/Target/X86/X86ShadowStackSeg.cpp 44 | 45 | ln -s $src/X86ShadowStackMPX.cpp $llvm/lib/Target/X86/X86ShadowStackMPX.cpp 46 | ln -s $src/X86FunctionCountPass.cpp $llvm/lib/Target/X86/X86FunctionCountPass.cpp 47 | 48 | rm -f $llvm/lib/Target/X86/X86RegisterInfo.cpp 49 | ln -s $src/X86RegisterInfo.cpp $llvm/lib/Target/X86/ 50 | 51 | rm -f $llvm/lib/Target/X86/X86MCInstLower.cpp 52 | ln -s $src/X86MCInstLower.cpp $llvm/lib/Target/X86/ 53 | 54 | rm -f $llvm/lib/Target/X86/CMakeLists.txt 55 | ln -s $src/x86-CMakeLists.txt $llvm/lib/Target/X86/CMakeLists.txt 56 | 57 | rm -f $crtlib/CMakeLists.txt 58 | ln -s $src/crt-lib-CMakeLists.txt $crtlib/CMakeLists.txt 59 | 60 | #rm -r $crtlib/shadowstack 61 | ln -s $src/shadowstack $crtlib/shadowstack 62 | 63 | rm $cdriver/ToolChains/CommonArgs.cpp 64 | ln -s $src/CommonArgs.cpp $cdriver/ToolChains 65 | 66 | mkdir -p $llvm/include/ShadowStack 67 | ln -s $src/ShadowStackConstants.h $llvm/include/ShadowStack/ShadowStackConstants.h 68 | ln -s $src/ShadowStackFeatures.h $llvm/include/ShadowStack/ShadowStackFeatures.h 69 | 70 | rm -f $musl/src/setjmp/x86_64/longjmp.s 71 | ln -s $src/longjmp.s $musl/src/setjmp/x86_64/ 72 | 73 | rm -f $unwind/src/UnwindRegistersRestore.S 74 | ln -s $src/UnwindRegistersRestore.S $unwind/src 75 | 76 | rm -f $src/shadowstack/setjmp.s 77 | rm -f $src/shadowstack/longjmp.s 78 | ln -s ../setjmp.s $src/shadowstack 79 | ln -s ../longjmp.s $src/shadowstack 80 | 81 | #rm $ltrans/Instrumentation/CMakeLists.txt 82 | #ln -s $src/llvm-Transforms-CMakeLists.txt $ltrans/Instrumentation/CMakeLists.txt 83 | # 84 | #rm $ccg/BackendUtil.cpp 85 | #ln -s $src/BackendUtil.cpp $ccg/BackendUtil.cpp 86 | # 87 | #rm $ltrans/Instrumentation/OTITypeTreePass.cpp 88 | #ln -s $src/pass/OTITypeTreePass.cpp $ltrans/Instrumentation 89 | # 90 | #rm $llvminc/InitializePasses.h 91 | #ln -s $src/InitializePasses.h $llvminc 92 | # 93 | #rm $llvminc/LinkAllPasses.h 94 | #ln -s $src/LinkAllPasses.h $llvminc 95 | # 96 | #rm $llvminc/Transforms/Instrumentation.h 97 | #ln -s $src/Instrumentation.h $llvminc/Transforms 98 | # 99 | #rm $llvminc/Transforms/OTI 100 | #ln -s $src/OTI $llvminc/Transforms 101 | # 102 | #rm $ccg/CGDecl.cpp 103 | #ln -s $src/CGDecl.cpp $ccg 104 | # 105 | #rm $ccg/CGExprCXX.cpp 106 | #ln -s $src/CGExprCXX.cpp $ccg 107 | # 108 | #rm $ccg/CGClass.cpp 109 | #ln -s $src/CGClass.cpp $ccg 110 | # 111 | #rm $ccg/CodeGenFunction.h 112 | #ln -s $src/CodeGenFunction.h $ccg 113 | # 114 | #rm $ccg/ItaniumCXXABI.cpp 115 | #ln -s $src/ItaniumCXXABI.cpp $ccg 116 | # 117 | #rm $ccg/CodeGenModule.h 118 | #ln -s $src/CodeGenModule.h $ccg 119 | # 120 | #rm $lcg/TargetPassConfig.cpp 121 | #ln -s $src/TargetPassConfig.cpp $lcg 122 | # 123 | 124 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/libcxx_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/debug-install 4 | cd libcxx-debug-build 5 | mkdir -p libcxx-debug-build 6 | 7 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 8 | -DCMAKE_BUILD_TYPE=Debug \ 9 | -DCMAKE_C_COMPILER=$HS_SYSROOT/bin/clang \ 10 | -DCMAKE_CXX_COMPILER=$HS_SYSROOT/bin/clang++ \ 11 | -DCMAKE_CXX_FLAGS="-O0 -v" \ 12 | -DCMAKE_C_FLAGS="-O0 -v" \ 13 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 14 | -DLIBCXX_CXX_ABI_INCLUDE_PATHS=$HS_HOME/libcxxabi/include \ 15 | -DLIBCXX_CXX_ABI=libcxxabi \ 16 | -DLIBCXX_CXX_ABI_LIBRARY_PATH=$HS_SYSROOT/lib \ 17 | -DLIBCXX_HAS_GCC_S_LIB=ON \ 18 | -DLIBCXX_ENABLE_SHARED=ON \ 19 | ../libcxx 20 | 21 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/libcxxabi_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/debug-install 4 | mkdir -p libcxxabi-debug-build 5 | cd libcxxabi-debug-build 6 | 7 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 8 | -DCMAKE_C_FLAGS="-O0 -v" \ 9 | -DCMAKE_CXX_FLAGS="-O0 -v" \ 10 | -DCMAKE_BUILD_TYPE=Debug \ 11 | -DCMAKE_C_COMPILER=$HOME/ShadowStack-MPK/Compiler-Impl/debug-install/bin/clang \ 12 | -DCMAKE_CXX_COMPILER=$HOME/ShadowStack-MPK/Compiler-Impl/debug-install/bin/clang++ \ 13 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 14 | -DLIBCXXABI_LIBCXX_PATH=$HS_HOME/libcxx \ 15 | -DLIBCXXABI_LIBCXX_INCLUDES=$HS_HOME/libcxx/include \ 16 | -DLIBCXXABI_LIBUNWIND_PATH=$HS_HOME/libunwind \ 17 | -DLIBCXXABI_LIBUNWIND_INCLUDES=$HS_HOME/libunwind/include \ 18 | -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ 19 | -DLIBCXXABI_ENABLE_SHARED=ON \ 20 | ../libcxxabi 21 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/libunwind_cmake.sh: -------------------------------------------------------------------------------- 1 | echo $base 2 | cd $base 3 | HS_HOME=$base 4 | HS_SYSROOT=$HS_HOME/debug-install 5 | HS_RT=$HS_SYSROOT/lib/clang/7.0.0/lib/linux 6 | mkdir -p libunwind-debug-build 7 | cd libunwind-debug-build 8 | 9 | cmake -G Ninja -DLLVM_PATH=$HS_HOME/llvm \ 10 | -DCMAKE_BUILD_TYPE=Debug \ 11 | -DCMAKE_CXX_COMPILER=clang++ \ 12 | -DCMAKE_C_COMPILER=clang \ 13 | -DCMAKE_C_FLAGS="-O0 -v" \ 14 | -DCMAKE_CXX_FLAGS="-O0 -v" \ 15 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 16 | -DLIBUNWIND_ENABLE_SHARED=ON \ 17 | ../libunwind 18 | 19 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/libunwind_release_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/release-install 4 | HS_RT=$HS_SYSROOT/lib/clang/7.0.0/lib/linux 5 | mkdir -p libunwind-release-build 6 | cd libunwind-release-build 7 | 8 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 9 | -DCMAKE_BUILD_TYPE=Release \ 10 | -DCMAKE_CXX_COMPILER=clang++ \ 11 | -DCMAKE_C_COMPILER=clang \ 12 | -DCMAKE_C_FLAGS="-v" \ 13 | -DCMAKE_CXX_FLAGS="-v" \ 14 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 15 | -DLIBUNWIND_ENABLE_SHARED=ON \ 16 | ../libunwind 17 | 18 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/rebuild_debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #rebuild debug version of clang 3 | make 4 | #rebuild release version of clang 5 | ninja -C release-build install 6 | #rebuild musl 7 | make -C musl clean 8 | make -C musl 9 | make -C musl install 10 | 11 | #rebuild debug version of libunwind 12 | ninja -C libunwind-debug-build clean 13 | ninja -C libunwind-debug-build install 14 | 15 | ninja -C libcxxabi-debug-build clean 16 | ninja -C libcxx-debug-build clean 17 | 18 | ninja -C libcxxabi-debug-build install 19 | ninja -C libcxx-debug-build install 20 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/release_libcxx_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/release-install 4 | mkdir -p libcxx-release-build 5 | cd libcxx-release-build 6 | 7 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 8 | -DCMAKE_BUILD_TYPE=Release \ 9 | -DCMAKE_CXX_COMPILER=clang++ \ 10 | -DCMAKE_C_COMPILER=clang \ 11 | -DCMAKE_CXX_FLAGS="-v" \ 12 | -DCMAKE_C_FLAGS="-v" \ 13 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 14 | -DLIBCXX_CXX_ABI_INCLUDE_PATHS=$HS_HOME/libcxxabi/include \ 15 | -DLIBCXX_CXX_ABI=libcxxabi \ 16 | -DLIBCXX_CXX_ABI_LIBRARY_PATH=$HS_SYSROOT/lib \ 17 | -DLIBCXX_HAS_GCC_S_LIB=ON \ 18 | -DLIBCXX_ENABLE_SHARED=ON \ 19 | ../libcxx 20 | 21 | -------------------------------------------------------------------------------- /Compiler-Impl/scripts/release_libcxxabi_cmake.sh: -------------------------------------------------------------------------------- 1 | cd .. 2 | HS_HOME=$PWD 3 | HS_SYSROOT=$HS_HOME/release-install 4 | mkdir -p libcxxabi-release-build 5 | cd libcxxabi-release-build 6 | 7 | cmake -GNinja -DLLVM_PATH=$HS_HOME/llvm \ 8 | -DCMAKE_C_FLAGS="-v" \ 9 | -DCMAKE_CXX_FLAGS="-v" \ 10 | -DCMAKE_BUILD_TYPE=Release \ 11 | -DCMAKE_CXX_COMPILER=clang++ \ 12 | -DCMAKE_C_COMPILER=clang \ 13 | -DCMAKE_INSTALL_PREFIX=$HS_SYSROOT \ 14 | -DLIBCXXABI_LIBCXX_PATH=$HS_HOME/libcxx \ 15 | -DLIBCXXABI_LIBCXX_INCLUDES=$HS_HOME/libcxx/include \ 16 | -DLIBCXXABI_LIBUNWIND_PATH=$HS_HOME/libunwind \ 17 | -DLIBCXXABI_LIBUNWIND_INCLUDES=$HS_HOME/libunwind/include \ 18 | -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ 19 | -DLIBCXXABI_ENABLE_SHARED=ON \ 20 | ../libcxxabi 21 | -------------------------------------------------------------------------------- /Compiler-Impl/src/Makefile: -------------------------------------------------------------------------------- 1 | all: fib_driver mpk_example pthread_create.so protected unprotected 2 | 3 | 4 | 5 | cc = clang 6 | my = ../debug-build/bin/clang 7 | CFLAGS = -Wall -g 8 | OPT = -O0 9 | mpk_example: mpk_example.c 10 | $(cc) mpk_example.c -o mpk_example -Wall 11 | 12 | protected: stackoverflow.c 13 | $(my) $(CFLAGS) $(OPT) stackoverflow.c -o protected -lpthread 14 | 15 | unprotected: stackoverflow.c 16 | $(cc) $(CFLAGS) $(OPT) stackoverflow.c -o unprotected -lpthread 17 | 18 | pthread_create.so: pthread_create.c ShadowStackConstants.h 19 | $(cc) $(CFLAGS) $(OPT) -g -shared -fPIC pthread_create.c -ldl -o pthread_create.so -lpthread 20 | 21 | fib_mpk.o: fib_mpk.c 22 | $(my) $(CFLAGS) $(OPT) -c fib_mpk.c 23 | 24 | fib.o: fib.c 25 | $(cc) $(CFLAGS) $(OPT) -c fib.c 26 | 27 | fib_driver: fib_mpk.o fib.o fib_driver.c 28 | $(my) $(CFLAGS) $(OPT) fib_driver.c fib.o fib_mpk.o -o fib_driver -lpthread 29 | 30 | clean: 31 | rm -f *.o *.so mpk_example protected unprotected fib fib_mpk fib_driver 32 | -------------------------------------------------------------------------------- /Compiler-Impl/src/NOTES: -------------------------------------------------------------------------------- 1 | Move modified source files here from the normal tree. Then update scripts/install-shadowstack-files.sh to symlink them in. 2 | -------------------------------------------------------------------------------- /Compiler-Impl/src/ShadowStackConstants.h: -------------------------------------------------------------------------------- 1 | #define SHADOW_STACK_OFFSET (-(1<<30)) 2 | #define PKEY 1 3 | #define NO_PROTECTION 0 4 | #define WRITE_PROTECTION 8 5 | #define PATCH_CALL 6 | #define SHADOW_STACK_PTR ((char*)0x7ffff690d000) 7 | // #define SHADOW_STACK_REG_CLAVE ((char*)0x7ffff7fc0000) 8 | #define SHADOW_STACK_SENTINEL ((char*)0x40000000U) 9 | #define MAX_ADDR 0xFFFFFFFFFFFFFFFFL 10 | #define PRACTICAL_STACK_SIZE 0x800000L 11 | 12 | -------------------------------------------------------------------------------- /Compiler-Impl/src/ShadowStackFeatures.h: -------------------------------------------------------------------------------- 1 | //#define COUNT_FUNCTION_CALLS //Ignore this one 2 | #define SHADOW_STACK_REG //uncomment to use register scheme 3 | // #define SHADOW_STACK_PARR //uncomment to enable mirroring ss, only valid for some schemes 4 | // #define SHADOW_STACK_MEM_SCHEME //uncomment to enable global var scheme 5 | // #define SHADOW_STACK_SEG //uncomment to enable segment scheme 6 | // #define SHADOW_STACK_CON //uncomment to enable constant offset 7 | // #define SHADOW_STACK_MPK //uncomment to enable MPK protection 8 | // #define SHADOW_STACK_MPX //uncomment to enable MPX protection 9 | -------------------------------------------------------------------------------- /Compiler-Impl/src/UnwindRegistersRestore.S: -------------------------------------------------------------------------------- 1 | //===-------------------- UnwindRegistersRestore.S ------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is dual licensed under the MIT and the University of Illinois Open 6 | // Source Licenses. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include "assembly.h" 11 | 12 | .text 13 | 14 | #if defined(__i386__) 15 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) 16 | # 17 | # void libunwind::Registers_x86::jumpto() 18 | # 19 | # On entry: 20 | # + + 21 | # +-----------------------+ 22 | # + thread_state pointer + 23 | # +-----------------------+ 24 | # + return address + 25 | # +-----------------------+ <-- SP 26 | # + + 27 | movl 4(%esp), %eax 28 | # set up eax and ret on new stack location 29 | movl 28(%eax), %edx # edx holds new stack pointer 30 | subl $8,%edx 31 | movl %edx, 28(%eax) 32 | movl 0(%eax), %ebx 33 | movl %ebx, 0(%edx) 34 | movl 40(%eax), %ebx 35 | movl %ebx, 4(%edx) 36 | # we now have ret and eax pushed onto where new stack will be 37 | # restore all registers 38 | movl 4(%eax), %ebx 39 | movl 8(%eax), %ecx 40 | movl 12(%eax), %edx 41 | movl 16(%eax), %edi 42 | movl 20(%eax), %esi 43 | movl 24(%eax), %ebp 44 | movl 28(%eax), %esp 45 | # skip ss 46 | # skip eflags 47 | pop %eax # eax was already pushed on new stack 48 | ret # eip was already pushed on new stack 49 | # skip cs 50 | # skip ds 51 | # skip es 52 | # skip fs 53 | # skip gs 54 | 55 | #elif defined(__x86_64__) 56 | .intel_syntax noprefix 57 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) 58 | # 59 | # void libunwind::Registers_x86_64::jumpto() 60 | # 61 | # On entry, thread_state pointer is in rdi 62 | 63 | #xor eax, eax 64 | #xor ecx, ecx 65 | #xor edx, edx 66 | #wrpkru 67 | mov r15, gs:[8] 68 | #lea r15, [r15+0x10] 69 | #mov rax, [rdx] 70 | 71 | 72 | //get recoreded RSP with RA 73 | mov rcx, [rdi+0x38] 74 | 2: 75 | cmp qword ptr[r15], 0 76 | je 3f 77 | cmp rcx, [r15+8] 78 | jge 4f 79 | add r15, 16 80 | jmp 2b 81 | 3: 82 | int 3 83 | 4: 84 | #mov gs:[0], r15 85 | //stack frame should be in sync 86 | //put shadow stack ptr back 87 | #mov [rdx], rax 88 | #mov eax, 8 89 | #xor ecx, ecx 90 | #xor edx, edx 91 | #wrpkru 92 | 93 | mov rax,QWORD PTR [rdi+0x38] # rax holds new stack pointer 94 | sub rax,0x10 95 | mov QWORD PTR [rdi+0x38],rax 96 | mov rbx,QWORD PTR [rdi+0x20] # store new rdi on new stack 97 | mov QWORD PTR [rax],rbx 98 | mov rbx,QWORD PTR [rdi+0x80] # store new rip on new stack 99 | mov QWORD PTR [rax+0x8],rbx 100 | # restore all registers 101 | mov rax,QWORD PTR [rdi] 102 | mov rbx,QWORD PTR [rdi+0x8] 103 | mov rcx,QWORD PTR [rdi+0x10] 104 | mov rdx,QWORD PTR [rdi+0x18] 105 | 106 | # restore rdi later 107 | mov rsi,QWORD PTR [rdi+0x28] 108 | mov rbp,QWORD PTR [rdi+0x30] 109 | 110 | # restore rsp later 111 | mov r8,QWORD PTR [rdi+0x40] 112 | mov r9,QWORD PTR [rdi+0x48] 113 | mov r10,QWORD PTR [rdi+0x50] 114 | mov r11,QWORD PTR [rdi+0x58] 115 | mov r12,QWORD PTR [rdi+0x60] 116 | mov r13,QWORD PTR [rdi+0x68] 117 | mov r14,QWORD PTR [rdi+0x70] 118 | #mov r15,QWORD PTR [rdi+0x78] 119 | 120 | # skip rflags 121 | # skip cs 122 | # skip fs 123 | # skip gs 124 | mov rsp,QWORD PTR [rdi+0x38] # cut back rsp to new location 125 | pop rdi # rdi was saved here earlier 126 | ret # rip was saved here 127 | 128 | 129 | #elif defined(__ppc__) 130 | 131 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) 132 | ; 133 | ; void libunwind::Registers_ppc::jumpto() 134 | ; 135 | ; On entry: 136 | ; thread_state pointer is in r3 137 | ; 138 | 139 | ; restore integral registerrs 140 | ; skip r0 for now 141 | ; skip r1 for now 142 | lwz r2, 16(r3) 143 | ; skip r3 for now 144 | ; skip r4 for now 145 | ; skip r5 for now 146 | lwz r6, 32(r3) 147 | lwz r7, 36(r3) 148 | lwz r8, 40(r3) 149 | lwz r9, 44(r3) 150 | lwz r10, 48(r3) 151 | lwz r11, 52(r3) 152 | lwz r12, 56(r3) 153 | lwz r13, 60(r3) 154 | lwz r14, 64(r3) 155 | lwz r15, 68(r3) 156 | lwz r16, 72(r3) 157 | lwz r17, 76(r3) 158 | lwz r18, 80(r3) 159 | lwz r19, 84(r3) 160 | lwz r20, 88(r3) 161 | lwz r21, 92(r3) 162 | lwz r22, 96(r3) 163 | lwz r23,100(r3) 164 | lwz r24,104(r3) 165 | lwz r25,108(r3) 166 | lwz r26,112(r3) 167 | lwz r27,116(r3) 168 | lwz r28,120(r3) 169 | lwz r29,124(r3) 170 | lwz r30,128(r3) 171 | lwz r31,132(r3) 172 | 173 | ; restore float registers 174 | lfd f0, 160(r3) 175 | lfd f1, 168(r3) 176 | lfd f2, 176(r3) 177 | lfd f3, 184(r3) 178 | lfd f4, 192(r3) 179 | lfd f5, 200(r3) 180 | lfd f6, 208(r3) 181 | lfd f7, 216(r3) 182 | lfd f8, 224(r3) 183 | lfd f9, 232(r3) 184 | lfd f10,240(r3) 185 | lfd f11,248(r3) 186 | lfd f12,256(r3) 187 | lfd f13,264(r3) 188 | lfd f14,272(r3) 189 | lfd f15,280(r3) 190 | lfd f16,288(r3) 191 | lfd f17,296(r3) 192 | lfd f18,304(r3) 193 | lfd f19,312(r3) 194 | lfd f20,320(r3) 195 | lfd f21,328(r3) 196 | lfd f22,336(r3) 197 | lfd f23,344(r3) 198 | lfd f24,352(r3) 199 | lfd f25,360(r3) 200 | lfd f26,368(r3) 201 | lfd f27,376(r3) 202 | lfd f28,384(r3) 203 | lfd f29,392(r3) 204 | lfd f30,400(r3) 205 | lfd f31,408(r3) 206 | 207 | ; restore vector registers if any are in use 208 | lwz r5,156(r3) ; test VRsave 209 | cmpwi r5,0 210 | beq Lnovec 211 | 212 | subi r4,r1,16 213 | rlwinm r4,r4,0,0,27 ; mask low 4-bits 214 | ; r4 is now a 16-byte aligned pointer into the red zone 215 | ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer 216 | 217 | 218 | #define LOAD_VECTOR_UNALIGNEDl(_index) \ 219 | andis. r0,r5,(1<<(15-_index)) @\ 220 | beq Ldone ## _index @\ 221 | lwz r0, 424+_index*16(r3) @\ 222 | stw r0, 0(r4) @\ 223 | lwz r0, 424+_index*16+4(r3) @\ 224 | stw r0, 4(r4) @\ 225 | lwz r0, 424+_index*16+8(r3) @\ 226 | stw r0, 8(r4) @\ 227 | lwz r0, 424+_index*16+12(r3)@\ 228 | stw r0, 12(r4) @\ 229 | lvx v ## _index,0,r4 @\ 230 | Ldone ## _index: 231 | 232 | #define LOAD_VECTOR_UNALIGNEDh(_index) \ 233 | andi. r0,r5,(1<<(31-_index)) @\ 234 | beq Ldone ## _index @\ 235 | lwz r0, 424+_index*16(r3) @\ 236 | stw r0, 0(r4) @\ 237 | lwz r0, 424+_index*16+4(r3) @\ 238 | stw r0, 4(r4) @\ 239 | lwz r0, 424+_index*16+8(r3) @\ 240 | stw r0, 8(r4) @\ 241 | lwz r0, 424+_index*16+12(r3)@\ 242 | stw r0, 12(r4) @\ 243 | lvx v ## _index,0,r4 @\ 244 | Ldone ## _index: 245 | 246 | 247 | LOAD_VECTOR_UNALIGNEDl(0) 248 | LOAD_VECTOR_UNALIGNEDl(1) 249 | LOAD_VECTOR_UNALIGNEDl(2) 250 | LOAD_VECTOR_UNALIGNEDl(3) 251 | LOAD_VECTOR_UNALIGNEDl(4) 252 | LOAD_VECTOR_UNALIGNEDl(5) 253 | LOAD_VECTOR_UNALIGNEDl(6) 254 | LOAD_VECTOR_UNALIGNEDl(7) 255 | LOAD_VECTOR_UNALIGNEDl(8) 256 | LOAD_VECTOR_UNALIGNEDl(9) 257 | LOAD_VECTOR_UNALIGNEDl(10) 258 | LOAD_VECTOR_UNALIGNEDl(11) 259 | LOAD_VECTOR_UNALIGNEDl(12) 260 | LOAD_VECTOR_UNALIGNEDl(13) 261 | LOAD_VECTOR_UNALIGNEDl(14) 262 | LOAD_VECTOR_UNALIGNEDl(15) 263 | LOAD_VECTOR_UNALIGNEDh(16) 264 | LOAD_VECTOR_UNALIGNEDh(17) 265 | LOAD_VECTOR_UNALIGNEDh(18) 266 | LOAD_VECTOR_UNALIGNEDh(19) 267 | LOAD_VECTOR_UNALIGNEDh(20) 268 | LOAD_VECTOR_UNALIGNEDh(21) 269 | LOAD_VECTOR_UNALIGNEDh(22) 270 | LOAD_VECTOR_UNALIGNEDh(23) 271 | LOAD_VECTOR_UNALIGNEDh(24) 272 | LOAD_VECTOR_UNALIGNEDh(25) 273 | LOAD_VECTOR_UNALIGNEDh(26) 274 | LOAD_VECTOR_UNALIGNEDh(27) 275 | LOAD_VECTOR_UNALIGNEDh(28) 276 | LOAD_VECTOR_UNALIGNEDh(29) 277 | LOAD_VECTOR_UNALIGNEDh(30) 278 | LOAD_VECTOR_UNALIGNEDh(31) 279 | 280 | Lnovec: 281 | lwz r0, 136(r3) ; __cr 282 | mtocrf 255,r0 283 | lwz r0, 148(r3) ; __ctr 284 | mtctr r0 285 | lwz r0, 0(r3) ; __ssr0 286 | mtctr r0 287 | lwz r0, 8(r3) ; do r0 now 288 | lwz r5,28(r3) ; do r5 now 289 | lwz r4,24(r3) ; do r4 now 290 | lwz r1,12(r3) ; do sp now 291 | lwz r3,20(r3) ; do r3 last 292 | bctr 293 | 294 | #elif defined(__arm64__) || defined(__aarch64__) 295 | 296 | // 297 | // void libunwind::Registers_arm64::jumpto() 298 | // 299 | // On entry: 300 | // thread_state pointer is in x0 301 | // 302 | .p2align 2 303 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) 304 | // skip restore of x0,x1 for now 305 | ldp x2, x3, [x0, #0x010] 306 | ldp x4, x5, [x0, #0x020] 307 | ldp x6, x7, [x0, #0x030] 308 | ldp x8, x9, [x0, #0x040] 309 | ldp x10,x11, [x0, #0x050] 310 | ldp x12,x13, [x0, #0x060] 311 | ldp x14,x15, [x0, #0x070] 312 | ldp x16,x17, [x0, #0x080] 313 | ldp x18,x19, [x0, #0x090] 314 | ldp x20,x21, [x0, #0x0A0] 315 | ldp x22,x23, [x0, #0x0B0] 316 | ldp x24,x25, [x0, #0x0C0] 317 | ldp x26,x27, [x0, #0x0D0] 318 | ldp x28,x29, [x0, #0x0E0] 319 | ldr x30, [x0, #0x100] // restore pc into lr 320 | ldr x1, [x0, #0x0F8] 321 | mov sp,x1 // restore sp 322 | 323 | ldp d0, d1, [x0, #0x110] 324 | ldp d2, d3, [x0, #0x120] 325 | ldp d4, d5, [x0, #0x130] 326 | ldp d6, d7, [x0, #0x140] 327 | ldp d8, d9, [x0, #0x150] 328 | ldp d10,d11, [x0, #0x160] 329 | ldp d12,d13, [x0, #0x170] 330 | ldp d14,d15, [x0, #0x180] 331 | ldp d16,d17, [x0, #0x190] 332 | ldp d18,d19, [x0, #0x1A0] 333 | ldp d20,d21, [x0, #0x1B0] 334 | ldp d22,d23, [x0, #0x1C0] 335 | ldp d24,d25, [x0, #0x1D0] 336 | ldp d26,d27, [x0, #0x1E0] 337 | ldp d28,d29, [x0, #0x1F0] 338 | ldr d30, [x0, #0x200] 339 | ldr d31, [x0, #0x208] 340 | 341 | ldp x0, x1, [x0, #0x000] // restore x0,x1 342 | ret x30 // jump to pc 343 | 344 | #elif defined(__arm__) && !defined(__APPLE__) 345 | 346 | #if !defined(__ARM_ARCH_ISA_ARM) 347 | .thumb 348 | #endif 349 | 350 | @ 351 | @ void libunwind::Registers_arm::restoreCoreAndJumpTo() 352 | @ 353 | @ On entry: 354 | @ thread_state pointer is in r0 355 | @ 356 | .p2align 2 357 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) 358 | #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 359 | @ r8-r11: ldm into r1-r4, then mov to r8-r11 360 | adds r0, #0x20 361 | ldm r0!, {r1-r4} 362 | subs r0, #0x30 363 | mov r8, r1 364 | mov r9, r2 365 | mov r10, r3 366 | mov r11, r4 367 | @ r12 does not need loading, it it the intra-procedure-call scratch register 368 | ldr r2, [r0, #0x34] 369 | ldr r3, [r0, #0x3c] 370 | mov sp, r2 371 | mov lr, r3 @ restore pc into lr 372 | ldm r0, {r0-r7} 373 | #else 374 | @ Use lr as base so that r0 can be restored. 375 | mov lr, r0 376 | @ 32bit thumb-2 restrictions for ldm: 377 | @ . the sp (r13) cannot be in the list 378 | @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction 379 | ldm lr, {r0-r12} 380 | ldr sp, [lr, #52] 381 | ldr lr, [lr, #60] @ restore pc into lr 382 | #endif 383 | JMP(lr) 384 | 385 | @ 386 | @ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) 387 | @ 388 | @ On entry: 389 | @ values pointer is in r0 390 | @ 391 | .p2align 2 392 | .fpu vfpv3-d16 393 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy) 394 | @ VFP and iwMMX instructions are only available when compiling with the flags 395 | @ that enable them. We do not want to do that in the library (because we do not 396 | @ want the compiler to generate instructions that access those) but this is 397 | @ only accessed if the personality routine needs these registers. Use of 398 | @ these registers implies they are, actually, available on the target, so 399 | @ it's ok to execute. 400 | @ So, generate the instruction using the corresponding coprocessor mnemonic. 401 | vldmia r0, {d0-d15} 402 | JMP(lr) 403 | 404 | @ 405 | @ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) 406 | @ 407 | @ On entry: 408 | @ values pointer is in r0 409 | @ 410 | .p2align 2 411 | .fpu vfpv3-d16 412 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy) 413 | vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia 414 | JMP(lr) 415 | 416 | @ 417 | @ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) 418 | @ 419 | @ On entry: 420 | @ values pointer is in r0 421 | @ 422 | .p2align 2 423 | .fpu vfpv3 424 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) 425 | vldmia r0, {d16-d31} 426 | JMP(lr) 427 | 428 | #if defined(__ARM_WMMX) 429 | 430 | @ 431 | @ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) 432 | @ 433 | @ On entry: 434 | @ values pointer is in r0 435 | @ 436 | .p2align 2 437 | .arch armv5te 438 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) 439 | ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 440 | ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 441 | ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 442 | ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 443 | ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 444 | ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 445 | ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 446 | ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 447 | ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 448 | ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 449 | ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 450 | ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 451 | ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 452 | ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 453 | ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 454 | ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 455 | JMP(lr) 456 | 457 | @ 458 | @ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) 459 | @ 460 | @ On entry: 461 | @ values pointer is in r0 462 | @ 463 | .p2align 2 464 | .arch armv5te 465 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) 466 | ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 467 | ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 468 | ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 469 | ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 470 | JMP(lr) 471 | 472 | #endif 473 | 474 | #elif defined(__or1k__) 475 | 476 | DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) 477 | # 478 | # void libunwind::Registers_or1k::jumpto() 479 | # 480 | # On entry: 481 | # thread_state pointer is in r3 482 | # 483 | 484 | # restore integral registerrs 485 | l.lwz r0, 0(r3) 486 | l.lwz r1, 4(r3) 487 | l.lwz r2, 8(r3) 488 | # skip r3 for now 489 | l.lwz r4, 16(r3) 490 | l.lwz r5, 20(r3) 491 | l.lwz r6, 24(r3) 492 | l.lwz r7, 28(r3) 493 | l.lwz r8, 32(r3) 494 | l.lwz r9, 36(r3) 495 | l.lwz r10, 40(r3) 496 | l.lwz r11, 44(r3) 497 | l.lwz r12, 48(r3) 498 | l.lwz r13, 52(r3) 499 | l.lwz r14, 56(r3) 500 | l.lwz r15, 60(r3) 501 | l.lwz r16, 64(r3) 502 | l.lwz r17, 68(r3) 503 | l.lwz r18, 72(r3) 504 | l.lwz r19, 76(r3) 505 | l.lwz r20, 80(r3) 506 | l.lwz r21, 84(r3) 507 | l.lwz r22, 88(r3) 508 | l.lwz r23, 92(r3) 509 | l.lwz r24, 96(r3) 510 | l.lwz r25,100(r3) 511 | l.lwz r26,104(r3) 512 | l.lwz r27,108(r3) 513 | l.lwz r28,112(r3) 514 | l.lwz r29,116(r3) 515 | l.lwz r30,120(r3) 516 | l.lwz r31,124(r3) 517 | 518 | # at last, restore r3 519 | l.lwz r3, 12(r3) 520 | 521 | # jump to pc 522 | l.jr r9 523 | l.nop 524 | 525 | #endif 526 | 527 | NO_EXEC_STACK_DIRECTIVE 528 | 529 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86.h: -------------------------------------------------------------------------------- 1 | //===-- X86.h - Top-level interface for X86 representation ------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains the entry points for global functions defined in the x86 11 | // target library, as used by the LLVM JIT. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef LLVM_LIB_TARGET_X86_X86_H 16 | #define LLVM_LIB_TARGET_X86_X86_H 17 | 18 | #include "llvm/Support/CodeGen.h" 19 | 20 | namespace llvm { 21 | 22 | class FunctionPass; 23 | class ImmutablePass; 24 | class InstructionSelector; 25 | class ModulePass; 26 | class PassRegistry; 27 | class X86RegisterBankInfo; 28 | class X86Subtarget; 29 | class X86TargetMachine; 30 | 31 | /// This pass converts a legalized DAG into a X86-specific DAG, ready for 32 | /// instruction scheduling. 33 | FunctionPass *createX86ISelDag(X86TargetMachine &TM, 34 | CodeGenOpt::Level OptLevel); 35 | 36 | /// This pass initializes a global base register for PIC on x86-32. 37 | FunctionPass *createX86GlobalBaseRegPass(); 38 | 39 | /// This pass combines multiple accesses to local-dynamic TLS variables so that 40 | /// the TLS base address for the module is only fetched once per execution path 41 | /// through the function. 42 | FunctionPass *createCleanupLocalDynamicTLSPass(); 43 | 44 | /// This function returns a pass which converts floating-point register 45 | /// references and pseudo instructions into floating-point stack references and 46 | /// physical instructions. 47 | FunctionPass *createX86FloatingPointStackifierPass(); 48 | 49 | /// This pass inserts AVX vzeroupper instructions before each call to avoid 50 | /// transition penalty between functions encoded with AVX and SSE. 51 | FunctionPass *createX86IssueVZeroUpperPass(); 52 | 53 | /// This pass instruments the function prolog to save the return address to a 54 | /// 'shadow call stack' and the function epilog to check that the return address 55 | /// did not change during function execution. 56 | FunctionPass *createShadowCallStackPass(); 57 | 58 | /// This pass inserts ENDBR instructions before indirect jump/call 59 | /// destinations as part of CET IBT mechanism. 60 | FunctionPass *createX86IndirectBranchTrackingPass(); 61 | 62 | /// Return a pass that pads short functions with NOOPs. 63 | /// This will prevent a stall when returning on the Atom. 64 | FunctionPass *createX86PadShortFunctions(); 65 | 66 | /// Return a pass that selectively replaces certain instructions (like add, 67 | /// sub, inc, dec, some shifts, and some multiplies) by equivalent LEA 68 | /// instructions, in order to eliminate execution delays in some processors. 69 | FunctionPass *createX86FixupLEAs(); 70 | 71 | /// Return a pass that removes redundant LEA instructions and redundant address 72 | /// recalculations. 73 | FunctionPass *createX86OptimizeLEAs(); 74 | 75 | /// Return a pass that transforms setcc + movzx pairs into xor + setcc. 76 | FunctionPass *createX86FixupSetCC(); 77 | 78 | /// Return a pass that avoids creating store forward block issues in the hardware. 79 | FunctionPass *createX86AvoidStoreForwardingBlocks(); 80 | 81 | /// Return a pass that lowers EFLAGS copy pseudo instructions. 82 | FunctionPass *createX86FlagsCopyLoweringPass(); 83 | 84 | /// Return a pass that expands WinAlloca pseudo-instructions. 85 | FunctionPass *createX86WinAllocaExpander(); 86 | 87 | /// Return a pass that optimizes the code-size of x86 call sequences. This is 88 | /// done by replacing esp-relative movs with pushes. 89 | FunctionPass *createX86CallFrameOptimization(); 90 | 91 | /// Return an IR pass that inserts EH registration stack objects and explicit 92 | /// EH state updates. This pass must run after EH preparation, which does 93 | /// Windows-specific but architecture-neutral preparation. 94 | FunctionPass *createX86WinEHStatePass(); 95 | 96 | /// Return a Machine IR pass that expands X86-specific pseudo 97 | /// instructions into a sequence of actual instructions. This pass 98 | /// must run after prologue/epilogue insertion and before lowering 99 | /// the MachineInstr to MC. 100 | FunctionPass *createX86ExpandPseudoPass(); 101 | 102 | /// This pass converts X86 cmov instructions into branch when profitable. 103 | FunctionPass *createX86CmovConverterPass(); 104 | 105 | /// Return a Machine IR pass that selectively replaces 106 | /// certain byte and word instructions by equivalent 32 bit instructions, 107 | /// in order to eliminate partial register usage, false dependences on 108 | /// the upper portions of registers, and to save code size. 109 | FunctionPass *createX86FixupBWInsts(); 110 | 111 | /// Return a Machine IR pass that reassigns instruction chains from one domain 112 | /// to another, when profitable. 113 | FunctionPass *createX86DomainReassignmentPass(); 114 | 115 | void initializeFixupBWInstPassPass(PassRegistry &); 116 | 117 | /// This pass replaces EVEX encoded of AVX-512 instructiosn by VEX 118 | /// encoding when possible in order to reduce code size. 119 | FunctionPass *createX86EvexToVexInsts(); 120 | 121 | /// This pass creates the thunks for the retpoline feature. 122 | FunctionPass *createX86RetpolineThunksPass(); 123 | 124 | //Shadow Stack store ptr in memory 125 | FunctionPass *createX86ShadowStackMem(); 126 | 127 | // Shadow stack is at constant offset from the program stack 128 | FunctionPass *createX86ShadowStackCon(); 129 | 130 | // Shadow Stack is stored in a register 131 | FunctionPass *createX86ShadowStackReg(); 132 | 133 | //Shadow Stack is stored in a segment 134 | FunctionPass *createX86ShadowStackSeg(); 135 | 136 | //This pass adds MPX protection 137 | FunctionPass *createX86ShadowStackMPX(); 138 | 139 | //This pass counts function call 140 | FunctionPass *createX86FunctionCountPass(); 141 | 142 | InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM, 143 | X86Subtarget &, 144 | X86RegisterBankInfo &); 145 | 146 | void initializeEvexToVexInstPassPass(PassRegistry &); 147 | 148 | } // End llvm namespace 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86FunctionCountPass.cpp: -------------------------------------------------------------------------------- 1 | #include "X86InstrBuilder.h" 2 | #include "X86InstrInfo.h" 3 | #include "X86MachineFunctionInfo.h" 4 | #include "X86Subtarget.h" 5 | #include "X86TargetMachine.h" 6 | #include "llvm/ADT/SmallSet.h" 7 | 8 | 9 | using namespace llvm; 10 | 11 | 12 | namespace{ 13 | class FunctionCountPass : public MachineFunctionPass{ 14 | public: 15 | static char ID; 16 | FunctionCountPass(): MachineFunctionPass(ID){} 17 | StringRef getPassName() const override { return "X86 Funciton Count Pass"; } 18 | bool runOnMachineFunction(MachineFunction &MF) override; 19 | }; 20 | } 21 | 22 | 23 | char FunctionCountPass::ID = 0; 24 | 25 | FunctionPass *llvm::createX86FunctionCountPass() { return new FunctionCountPass(); } 26 | 27 | 28 | bool FunctionCountPass::runOnMachineFunction(MachineFunction &MF) { 29 | MachineBasicBlock &MBB = MF.front(); 30 | MachineBasicBlock::iterator MBBI = MBB.begin(); 31 | const DebugLoc DL = MBBI->getDebugLoc(); 32 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 33 | BuildMI(MBB, MBBI, DL, TII->get(X86::INC64m)) 34 | .addReg(0) //base 35 | .addImm(1) //scale 36 | .addReg(0) //index 37 | .addImm(24) //disp 38 | .addReg(X86::GS); //segment 39 | 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86ShadowStackCon.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // X86ShadowStackPass.cpp 3 | // LLVM 4 | // 5 | // Created by Kelvin Zhang on 1/18/18. 6 | // 7 | #include "X86InstrBuilder.h" 8 | #include "X86InstrInfo.h" 9 | #include "X86MachineFunctionInfo.h" 10 | #include "X86Subtarget.h" 11 | #include "X86TargetMachine.h" 12 | #include "llvm/ADT/SmallSet.h" 13 | #include "llvm/Analysis/EHPersonalities.h" 14 | #include "llvm/CodeGen/MachineFrameInfo.h" 15 | #include "llvm/CodeGen/MachineFunction.h" 16 | #include "llvm/CodeGen/MachineInstrBuilder.h" 17 | #include "llvm/CodeGen/MachineModuleInfo.h" 18 | #include "llvm/CodeGen/MachineRegisterInfo.h" 19 | #include "llvm/CodeGen/WinEHFuncInfo.h" 20 | #include "llvm/IR/DataLayout.h" 21 | #include "llvm/IR/Function.h" 22 | #include "llvm/MC/MCAsmInfo.h" 23 | #include "llvm/MC/MCSymbol.h" 24 | #include "llvm/Support/Debug.h" 25 | #include "llvm/Target/TargetOptions.h" 26 | 27 | #include "ShadowStack/ShadowStackConstants.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | using namespace llvm; 35 | 36 | cl::opt 37 | parallel("x86-parallel-ss", 38 | cl::desc("Use a parallel shadow stack instead of minimal"), 39 | cl::init(false), 40 | cl::NotHidden); 41 | 42 | cl::opt 43 | epilog("x86-ss-epilog", 44 | cl::desc("Use this type of epilog"), 45 | cl::init("cmp"), 46 | cl::NotHidden); 47 | 48 | cl::opt 49 | mpk("x86-mpk", 50 | cl::desc("Use mpk to protect shadow stack"), 51 | cl::init(false), 52 | cl::NotHidden); 53 | 54 | 55 | namespace{ 56 | class X86ShadowStackCon : public MachineFunctionPass{ 57 | public: 58 | static char ID; 59 | X86ShadowStackCon() : MachineFunctionPass(ID){} 60 | StringRef getPassName() const override { return "X86 Shadow Stack Con"; } 61 | bool runOnMachineFunction(MachineFunction &MF) override; 62 | }; 63 | } 64 | char X86ShadowStackCon::ID = 0; 65 | extern void checkRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 66 | 67 | FunctionPass *llvm::createX86ShadowStackCon() { return new X86ShadowStackCon(); } 68 | 69 | 70 | void XORReg(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, unsigned Reg) 71 | { 72 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV32ri), Reg).addImm(0); 73 | } 74 | 75 | void WRPKRUI(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, int imm) 76 | { 77 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV32ri), X86::EAX).addImm(imm); 78 | XORReg(MBB, MBBI, DL, TII, X86::ECX); 79 | XORReg(MBB, MBBI, DL, TII, X86::EDX); 80 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 81 | } 82 | 83 | static void emitShadowStackPrologue(MachineFunction &MF) 84 | { 85 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 86 | 87 | const DebugLoc DL = MF.front().size() == 0 ? DebugLoc() :MF.front().front().getDebugLoc(); 88 | 89 | //put all the shadow stack code in a separate MBB 90 | MachineBasicBlock &MBB = MF.front(); 91 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 92 | if(mpk.getValue()) 93 | { 94 | //save ecx and edx 95 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RCX, RegState::Kill); 96 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RDX, RegState::Kill); 97 | 98 | //disable MPK protections 99 | WRPKRUI(MBB, MBBI, DL, TII, 0); 100 | } 101 | //get the return addr 102 | //mov RAX, [rsp] 103 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RAX); 104 | addRegOffset(getRA, X86::RSP, false, 0); 105 | 106 | //store return addr 107 | //mov [rsp+SHADOW_STACK_OFFSET], vReg1 108 | MachineInstrBuilder putRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 109 | addRegOffset(putRA, X86::RSP, false, SHADOW_STACK_OFFSET).addReg(X86::RAX, RegState::Kill); 110 | if(mpk.getValue()) 111 | { 112 | //reenable protection 113 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 114 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 115 | 116 | //restore ecx and edx 117 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RCX).addReg(X86::R10, RegState::Kill); 118 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R11, RegState::Kill); 119 | } 120 | } 121 | 122 | static void emitShadowStackEpilogue(MachineBasicBlock &MBB) 123 | { 124 | MachineBasicBlock::iterator &MBBI = --MBB.end(); 125 | 126 | const DebugLoc &DL = MBBI->getDebugLoc(); 127 | const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); 128 | 129 | const MachineInstr &back = MBB.back(); 130 | 131 | bool saveR10 = back.readsRegister(X86::R10); 132 | bool saveR11 = back.readsRegister(X86::R11); 133 | 134 | //If tail call needs R10, R11 135 | if(saveR11) 136 | { 137 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 138 | addRegOffset(saveR11, X86::RSP, false, -16).addReg(X86::R11); 139 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RAX).addReg(X86::R11); 140 | } 141 | if(saveR10) 142 | { 143 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 144 | addRegOffset(saveR10, X86::RSP, false, -24).addReg(X86::R10); 145 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R10); 146 | } 147 | 148 | //mov r11, [rsp+SHADOW_STACK_OFFSET] 149 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 150 | addRegOffset(getRA, X86::RSP, false, SHADOW_STACK_OFFSET); 151 | 152 | //check RA in r11 153 | checkRA(MBB, MBBI, TII); 154 | 155 | //restore R11, R10 if necessary 156 | if(saveR11) 157 | { 158 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 159 | addRegOffset(saveR11, X86::RSP, false, -16); 160 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RAX); 161 | } 162 | if(saveR10) 163 | { 164 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10); 165 | addRegOffset(saveR10, X86::RSP, false, -24); 166 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RDX); 167 | } 168 | } 169 | 170 | static bool isPush(unsigned opcode) 171 | { 172 | switch(opcode) 173 | { 174 | case X86::PUSH64i32: 175 | case X86::PUSHi32: 176 | case X86::PUSH64i8: 177 | case X86::PUSH32i8: 178 | case X86::PUSH64rmm: 179 | case X86::PUSH32rmm: 180 | case X86::PUSH16rmm: 181 | case X86::PUSH16r: 182 | case X86::PUSH32r: 183 | case X86::PUSH64r: 184 | return true; 185 | default: 186 | return false; 187 | } 188 | } 189 | 190 | static bool isGlobalVarAccess(const MachineInstr &MI) 191 | { 192 | for(MachineMemOperand *MMO : MI.memoperands()) 193 | { 194 | if(MMO->isStore()) 195 | { 196 | if(MMO->getValue() && isa(MMO->getValue())) 197 | { 198 | return true; 199 | } 200 | } 201 | } 202 | return false; 203 | } 204 | 205 | bool mayWriteMem(const MachineFunction &MF) 206 | { 207 | for(const MachineBasicBlock &MBB : MF) 208 | { 209 | for(const MachineInstr &MI : MBB) 210 | { 211 | //if this is a push instr, ignore it 212 | if(isPush(MI.getOpcode()))continue; 213 | if(MI.mayStore()) 214 | { 215 | if(!isGlobalVarAccess(MI))return true; 216 | } 217 | } 218 | } 219 | return false; 220 | } 221 | 222 | bool X86ShadowStackCon::runOnMachineFunction(MachineFunction &MF) { 223 | if(!mayWriteMem(MF))return false; 224 | emitShadowStackPrologue(MF); 225 | for (MachineBasicBlock &MBB : MF) 226 | { 227 | if (MBB.isReturnBlock()) 228 | { 229 | emitShadowStackEpilogue(MBB); 230 | } 231 | } 232 | return true; 233 | } 234 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86ShadowStackMPX.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // X86MPXProtect.cpp 3 | // LLVMDemangle 4 | // 5 | // Created by Kelvin Zhang on 2/14/18. 6 | // 7 | 8 | #include "X86InstrBuilder.h" 9 | #include "X86InstrInfo.h" 10 | #include "X86MachineFunctionInfo.h" 11 | #include "X86Subtarget.h" 12 | #include "X86TargetMachine.h" 13 | #include "llvm/ADT/SmallSet.h" 14 | #include "llvm/Analysis/EHPersonalities.h" 15 | #include "llvm/CodeGen/MachineFrameInfo.h" 16 | #include "llvm/CodeGen/MachineFunction.h" 17 | #include "llvm/CodeGen/MachineInstrBuilder.h" 18 | #include "llvm/CodeGen/MachineModuleInfo.h" 19 | #include "llvm/CodeGen/MachineRegisterInfo.h" 20 | #include "llvm/CodeGen/WinEHFuncInfo.h" 21 | #include "llvm/IR/DataLayout.h" 22 | #include "llvm/IR/Function.h" 23 | #include "llvm/MC/MCAsmInfo.h" 24 | #include "llvm/MC/MCSymbol.h" 25 | #include "llvm/Support/Debug.h" 26 | #include "llvm/Target/TargetOptions.h" 27 | #include "ShadowStack/ShadowStackConstants.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | using namespace llvm; 36 | 37 | namespace{ 38 | class X86ShadowStackMPX : public MachineFunctionPass{ 39 | public: 40 | static char ID; 41 | X86ShadowStackMPX() : MachineFunctionPass(ID){} 42 | StringRef getPassName() const override { return "X86 MPX"; } 43 | bool runOnMachineFunction(MachineFunction &MF) override; 44 | }; 45 | } 46 | 47 | char X86ShadowStackMPX::ID = 0; 48 | 49 | FunctionPass *llvm::createX86ShadowStackMPX() { return new X86ShadowStackMPX(); } 50 | 51 | bool X86ShadowStackMPX::runOnMachineFunction(MachineFunction &MF) 52 | { 53 | const int64_t ROTATION_OFFSET = (0xFFFFFFFFFFFFFFFFL-(size_t)SHADOW_STACK_PTR + PRACTICAL_STACK_SIZE); 54 | //#ifdef nonono 55 | /*NHB CFIXX*/ 56 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 57 | //const TargetLowering *TLI = MF.getSubtarget().getTargetLowering(); 58 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 59 | for(auto &MBB : MF){ 60 | for(auto &MI : MBB) { 61 | if(MI.mayStore()) { 62 | switch(MI.getOpcode()){ 63 | case X86::MOV8mi: 64 | case X86::MOV16mi: 65 | case X86::MOV32mi: 66 | case X86::MOV8mr: 67 | case X86::MOV16mr: 68 | case X86::MOV32mr: 69 | case X86::MOV64mr: 70 | case X86::MOV64mi32: 71 | case X86::CMP8mi8: 72 | case X86::CMP8mi: 73 | case X86::CMP16mi8: 74 | case X86::CMP32mi8: 75 | case X86::CMP32mi: 76 | case X86::CMP32mr: 77 | case X86::CMP64mi32: 78 | case X86::CMP64mi8: 79 | case X86::CMP64mr: 80 | case X86::MOVSSmr: 81 | case X86::MOVSDmr: 82 | case X86::TEST32mi: 83 | case X86::TEST16mi: 84 | case X86::TEST8mi: 85 | case X86::MOVAPDmr: 86 | case X86::INC8m: 87 | case X86::INC16m: 88 | case X86::INC32m: 89 | case X86::INC64m: 90 | case X86::DEC8m: 91 | case X86::DEC16m: 92 | case X86::DEC32m: 93 | case X86::DEC64m: 94 | //case X86::JMP16m: 95 | //case X86::JMP32m: 96 | //case X86::JMP64m: 97 | case X86::ADD64mi8: 98 | case X86::ADD64mi32: 99 | case X86::ADD64mr: 100 | case X86::ADD32mi8: 101 | case X86::ADD32mi: 102 | case X86::ADD32mr: 103 | case X86::ADD16mi8: 104 | case X86::ADD16mi: 105 | case X86::ADD16mr: 106 | case X86::ADD8mi8: 107 | case X86::ADD8mr: 108 | case X86::MOVUPSmr: 109 | case X86::MOVUPDmr: 110 | case X86::MOVAPSmr: 111 | case X86::MOVDQUmr: 112 | case X86::MOVDQAmr: 113 | case X86::MOVPQI2QImr: 114 | case X86::MOVPDI2DImr: 115 | case X86::IDIV64m: 116 | case X86::IDIV32m: 117 | case X86::IDIV16m: 118 | case X86::IDIV8m: 119 | case X86::DIV64m: 120 | case X86::DIV32m: 121 | case X86::DIV16m: 122 | case X86::DIV8m: 123 | case X86::OR8mi: 124 | case X86::OR16mi: 125 | case X86::OR32mi: 126 | case X86::OR16mi8: 127 | case X86::OR32mi8: 128 | case X86::OR64mi32: 129 | case X86::OR8mr: 130 | case X86::OR16mr: 131 | case X86::OR32mr: 132 | case X86::OR64mr: 133 | case X86::XOR8mi: 134 | case X86::XOR16mi: 135 | case X86::XOR32mi: 136 | case X86::XOR16mi8: 137 | case X86::XOR32mi8: 138 | case X86::XOR8mr: 139 | case X86::XOR16mr: 140 | case X86::XOR32mr: 141 | case X86::XOR64mr: 142 | case X86::SETBEm: 143 | case X86::SETEm: 144 | case X86::SETGm: 145 | case X86::SETGEm: 146 | case X86::SETLm: 147 | case X86::SETLEm: 148 | case X86::SETNEm: 149 | case X86::AND8mr: 150 | case X86::AND16mr: 151 | case X86::AND32mr: 152 | case X86::AND64mr: 153 | case X86::AND8mi: 154 | case X86::AND16mi: 155 | case X86::AND32mi: 156 | case X86::AND8mi8: 157 | case X86::AND16mi8: 158 | case X86::AND32mi8: 159 | case X86::AND64mi8: 160 | case X86::AND64mi32: 161 | case X86::SUB8mr: 162 | case X86::SUB16mr: 163 | case X86::SUB32mr: 164 | case X86::SUB64mr: 165 | //case X86::CALL64m: 166 | //case X86::CALL32m: 167 | case X86::ROL64mi: 168 | case X86::ROL32mi: 169 | case X86::ROL16mi: 170 | case X86::ROR64mi: 171 | case X86::ROR32mi: 172 | case X86::ROR16mi: 173 | case X86::SHR64mi: 174 | case X86::SHR64mCL: 175 | case X86::SHR32mi: 176 | case X86::SHR16mi: 177 | case X86::SHL64mi: 178 | case X86::SHL32mi: 179 | case X86::SHL16mi: 180 | case X86::SHR64m1: 181 | case X86::SHR32m1: 182 | case X86::SHR16m1: 183 | case X86::SHL64m1: 184 | case X86::SHL32m1: 185 | case X86::SHL16m1: 186 | case X86::ADC64mi8: 187 | case X86::ADC32mi8: 188 | case X86::ADC32mi: 189 | case X86::ADC16mi: 190 | case X86::ADC8mi: 191 | case X86::SBB32mi: 192 | case X86::SBB32mi8: 193 | case X86::SBB16mi: 194 | case X86::SBB16mi8: 195 | case X86::MOV8mr_NOREX: 196 | //case X86::TAILJMPm64: 197 | case X86::SHLD64mri8: 198 | case X86::SHLD32mri8: 199 | case X86::SHLD16mri8: 200 | case X86::NOT64m: 201 | case X86::NOT32m: 202 | case X86::NOT16m: 203 | case X86::NOT8m: 204 | case X86::NEG64m: 205 | case X86::NEG32m: 206 | case X86::NEG16m: 207 | case X86::NEG8m: 208 | case X86::OR64mi8: 209 | case X86::OR8mi8: 210 | case X86::MOVLPDmr: 211 | case X86::MOVLPSmr: 212 | case X86::ST_FP80m: 213 | case X86::ST_FP64m: 214 | case X86::ST_FP32m: 215 | case X86::LD_F80m: 216 | case X86::LD_F64m: 217 | case X86::LD_F32m: 218 | case X86::SAR64mi: 219 | case X86::SAR32mi: 220 | case X86::SAR32m1: 221 | case X86::SAR64mCL: 222 | case X86::SHL64mCL: 223 | case X86::SETAEm: 224 | case X86::SETBm: 225 | case X86::MOVHPDmr: 226 | case X86::SETAm: 227 | case X86::ILD_F64m: 228 | case X86::MOVSDto64mr: 229 | case X86::MOVSS2DImr: 230 | case X86::MUL_F64m: 231 | case X86::MUL_F32m: 232 | case X86::LOCK_INC64m: 233 | case X86::LOCK_INC32m: 234 | case X86::LCMPXCHG64: 235 | { 236 | const MCInstrDesc &leaOp = TII->get(X86::LEA64r); 237 | //const MCInstrDesc &shrOp = TII->get(X86::SHR64ri); 238 | const MCInstrDesc &bndcuOp = TII->get(X86::BNDCU64rr); 239 | const MCInstrDesc &movOp = TII->get(X86::MOV64ri); 240 | unsigned vReg1 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 241 | unsigned vReg2 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 242 | unsigned vReg3 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 243 | 244 | //TODO: May need to change kill flags on my new instructions 245 | MachineInstrBuilder lea = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg1); 246 | lea->addOperand(MI.getOperand(0)); 247 | lea->addOperand(MI.getOperand(1)); 248 | lea->addOperand(MI.getOperand(2)); 249 | lea->addOperand(MI.getOperand(3)); 250 | lea->addOperand(MI.getOperand(4)); 251 | 252 | MachineInstrBuilder movabs = BuildMI(MBB, MI, MI.getDebugLoc(), movOp, vReg2); 253 | movabs.addImm(ROTATION_OFFSET); 254 | 255 | MachineInstrBuilder lea2 = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg3); 256 | lea2.addReg(vReg1); 257 | lea2.addImm(1); 258 | lea2.addReg(vReg2); 259 | lea2.addImm(0); 260 | lea2.addReg(0); 261 | 262 | MachineInstrBuilder bndcu = BuildMI(MBB, MI, MI.getDebugLoc(), bndcuOp); 263 | bndcu.addReg(X86::BND0); 264 | bndcu.addReg(vReg3); //, RegState::Kill); 265 | /* 266 | bndcu.addImm(1); 267 | bndcu.addReg(0); 268 | bndcu.addImm(0xff80fd6a); 269 | bndcu.addReg(0); 270 | */ 271 | break; 272 | } 273 | case X86::MOV8rm: 274 | case X86::MOV16rm: 275 | case X86::MOV32rm: 276 | case X86::MOV64rm: 277 | case X86::CMP64rm: 278 | case X86::CMP32rm: 279 | case X86::MOVSSrm: 280 | case X86::MOVSDrm: 281 | case X86::MOVSX64rm8: 282 | case X86::MOVSX64rm16: 283 | case X86::MOVSX64rm32: 284 | case X86::MOVSX32rm8: 285 | case X86::MOVSX32rm16: 286 | case X86::MOVZX32rm8: 287 | case X86::MOVZX32rm16: 288 | case X86::CVTSI2SDrm: 289 | case X86::CVTSI2SSrm: 290 | //case X86::CVTSS2SIrm: 291 | case X86::CVTTSS2SI64rm: 292 | case X86::CVTTSS2SIrm: 293 | case X86::CVTPS2PDrm: 294 | case X86::UCOMISSrm: 295 | case X86::UCOMISDrm: 296 | case X86::MOVAPDrm: 297 | case X86::MOVAPSrm: 298 | case X86::MOVUPSrm: 299 | case X86::MOVUPDrm: 300 | case X86::MOVDQUrm: 301 | case X86::MOVDQArm: 302 | case X86::MOVQI2PQIrm: 303 | case X86::IMUL64rmi32: 304 | case X86::IMUL64rmi8: 305 | case X86::IMUL32rmi8: 306 | case X86::IMUL16rmi8: 307 | case X86::IMUL32rmi: 308 | case X86::IMUL16rmi: 309 | case X86::MOVDI2PDIrm: 310 | case X86::TEST8mr: 311 | case X86::TEST16mr: 312 | case X86::TEST32mr: 313 | case X86::TEST64mr: 314 | case X86::PSHUFDmi: 315 | case X86::CVTTSD2SIrm: 316 | case X86::CVTTSD2SI64rm: 317 | case X86::PSHUFLWmi: 318 | // case X86::MOVZQI2PQIrm: 319 | case X86::CVTPD2PSrm: 320 | case X86::MOVDI2SSrm: 321 | case X86::MOV64toSDrm: 322 | { 323 | const MCInstrDesc &leaOp = TII->get(X86::LEA64r); 324 | //const MCInstrDesc &shrOp = TII->get(X86::SHR64ri); 325 | const MCInstrDesc &bndcuOp = TII->get(X86::BNDCU64rr); 326 | const MCInstrDesc &movOp = TII->get(X86::MOV64ri); 327 | unsigned vReg1 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 328 | unsigned vReg2 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 329 | unsigned vReg3 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 330 | 331 | //TODO: May need to change kill flags on my new instructions 332 | MachineInstrBuilder lea = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg1); 333 | lea->addOperand(MI.getOperand(1)); 334 | lea->addOperand(MI.getOperand(2)); 335 | lea->addOperand(MI.getOperand(3)); 336 | lea->addOperand(MI.getOperand(4)); 337 | lea->addOperand(MI.getOperand(5)); 338 | 339 | MachineInstrBuilder movabs = BuildMI(MBB, MI, MI.getDebugLoc(), movOp, vReg2); 340 | movabs.addImm(ROTATION_OFFSET); 341 | 342 | MachineInstrBuilder lea2 = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg3); 343 | lea2.addReg(vReg1); 344 | lea2.addImm(1); 345 | lea2.addReg(vReg2); 346 | lea2.addImm(0); 347 | lea2.addReg(0); 348 | 349 | MachineInstrBuilder bndcu = BuildMI(MBB, MI, MI.getDebugLoc(), bndcuOp); 350 | bndcu.addReg(X86::BND0); 351 | bndcu.addReg(vReg3); //, RegState::Kill); 352 | /* 353 | bndcu.addImm(1); 354 | bndcu.addReg(0); 355 | bndcu.addImm(0); //xff80fd6a); 356 | bndcu.addReg(0); 357 | */ 358 | break; 359 | } 360 | case X86::DIVSSrm: 361 | case X86::DIVSDrm: 362 | case X86::SUBSSrm: 363 | case X86::SUBSDrm: 364 | case X86::SUB64rm: 365 | case X86::SUB32rm: 366 | case X86::SUB16rm: 367 | case X86::SUB8rm: 368 | case X86::MULSSrm: 369 | case X86::MULSDrm: 370 | case X86::AND64rm: 371 | case X86::AND32rm: 372 | case X86::AND16rm: 373 | case X86::AND8rm: 374 | case X86::PADDQrm: 375 | case X86::LXADD64: 376 | case X86::LXADD32: 377 | case X86::ADD64rm: 378 | case X86::ADD32rm: 379 | case X86::ADD16rm: 380 | case X86::ADD8rm: 381 | case X86::ADDSSrm: 382 | case X86::ADDSDrm: 383 | // case X86::FvXORPDrm: 384 | // case X86::FvXORPSrm: 385 | // case X86::FvANDPSrm: 386 | case X86::OR64rm: 387 | case X86::OR32rm: 388 | case X86::OR16rm: 389 | case X86::OR8rm: 390 | case X86::PANDrm: 391 | case X86::PANDNrm: 392 | case X86::PXORrm: 393 | case X86::PORrm: 394 | case X86::MINSSrm: 395 | case X86::MINSDrm: 396 | case X86::MAXSSrm: 397 | case X86::MAXSDrm: 398 | case X86::IMUL64rm: 399 | case X86::IMUL32rm: 400 | case X86::IMUL16rm: 401 | case X86::UNPCKLPDrm: 402 | case X86::CMOVS64rm: 403 | case X86::CMOVS32rm: 404 | case X86::CMOVS16rm: 405 | case X86::CMOVE64rm: 406 | case X86::CMOVE32rm: 407 | case X86::CMOVE16rm: 408 | case X86::CMOVNE64rm: 409 | case X86::CMOVNE32rm: 410 | case X86::CMOVNE16rm: 411 | case X86::CMOVGE64rm: 412 | case X86::CMOVGE32rm: 413 | case X86::CMOVGE16rm: 414 | case X86::CMOVG64rm: 415 | case X86::CMOVG32rm: 416 | case X86::CMOVG16rm: 417 | case X86::CMOVLE64rm: 418 | case X86::CMOVLE32rm: 419 | case X86::CMOVLE16rm: 420 | case X86::CMOVL64rm: 421 | case X86::CMOVL32rm: 422 | case X86::CMOVL16rm: 423 | case X86::CMOVB64rm: 424 | case X86::CMOVB32rm: 425 | case X86::CMOVB16rm: 426 | case X86::CMOVBE64rm: 427 | case X86::CMOVBE32rm: 428 | case X86::CMOVBE16rm: 429 | case X86::XOR64rm: 430 | case X86::XOR32rm: 431 | case X86::XOR16rm: 432 | case X86::XOR8rm: 433 | case X86::PUNPCKLQDQrm: 434 | case X86::PINSRWrm: 435 | case X86::ORPSrm: 436 | case X86::PCMPEQDrm: 437 | case X86::PCMPEQQrm: 438 | case X86::PUNPCKLDQrm: 439 | case X86::SUBPDrm: 440 | case X86::CMOVAE64rm: 441 | case X86::MOVHPDrm: 442 | case X86::CMOVNS32rm: 443 | case X86::CMPSDrm: 444 | case X86::ANDPSrm: 445 | case X86::ANDPDrm: 446 | case X86::PMULUDQrm: 447 | // case X86::FvANDPDrm: 448 | case X86::CMOVA64rm: 449 | case X86::CMOVA32rm: 450 | case X86::CMOVA16rm: 451 | case X86::MULPDrm: 452 | case X86::ADDPDrm: 453 | case X86::PADDDrm: 454 | case X86::CMPSSrm: 455 | case X86::SHUFPDrmi: 456 | case X86::DIVPDrm: 457 | case X86::ADDPSrm: 458 | case X86::ANDNPDrm: 459 | case X86::MOVLPDrm: 460 | case X86::UNPCKLPSrm: 461 | case X86::UNPCKHPDrm: 462 | case X86::XORPDrm: 463 | case X86::CMPPDrmi: 464 | case X86::MULPSrm: 465 | case X86::XCHG64rm: 466 | { 467 | const MCInstrDesc &leaOp = TII->get(X86::LEA64r); 468 | //const MCInstrDesc &shrOp = TII->get(X86::SHR64ri); 469 | const MCInstrDesc &bndcuOp = TII->get(X86::BNDCU64rr); 470 | const MCInstrDesc &movOp = TII->get(X86::MOV64ri); 471 | unsigned vReg1 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 472 | unsigned vReg2 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 473 | unsigned vReg3 = MF.getRegInfo().createVirtualRegister(TII->getRegClass(bndcuOp, 1, TRI, MF)); 474 | 475 | //TODO: May need to change kill flags on my new instructions 476 | MachineInstrBuilder lea = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg1); 477 | lea->addOperand(MI.getOperand(2)); 478 | lea->addOperand(MI.getOperand(3)); 479 | lea->addOperand(MI.getOperand(4)); 480 | lea->addOperand(MI.getOperand(5)); 481 | lea->addOperand(MI.getOperand(6)); 482 | 483 | MachineInstrBuilder movabs = BuildMI(MBB, MI, MI.getDebugLoc(), movOp, vReg2); 484 | movabs.addImm(ROTATION_OFFSET); 485 | 486 | MachineInstrBuilder lea2 = BuildMI(MBB, MI, MI.getDebugLoc(), leaOp, vReg3); 487 | lea2.addReg(vReg1); 488 | lea2.addImm(1); 489 | lea2.addReg(vReg2); 490 | lea2.addImm(0); 491 | lea2.addReg(0); 492 | 493 | MachineInstrBuilder bndcu = BuildMI(MBB, MI, MI.getDebugLoc(), bndcuOp); 494 | bndcu.addReg(X86::BND0); 495 | bndcu.addReg(vReg3); //, RegState::Kill); 496 | /* 497 | bndcu.addImm(1); 498 | bndcu.addReg(0); 499 | bndcu.addImm(0); //xff80fd6a); 500 | bndcu.addReg(0); 501 | */ 502 | break; 503 | } 504 | 505 | default: 506 | break; 507 | } 508 | } 509 | } 510 | } 511 | //#endif 512 | return true; 513 | } 514 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86ShadowStackMem.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // X86ShadowStackPass.cpp 3 | // LLVM 4 | // 5 | // Created by Kelvin Zhang on 1/18/18. 6 | // 7 | 8 | #include "X86InstrBuilder.h" 9 | #include "X86InstrInfo.h" 10 | #include "X86MachineFunctionInfo.h" 11 | #include "X86Subtarget.h" 12 | #include "X86TargetMachine.h" 13 | #include "llvm/ADT/SmallSet.h" 14 | #include "llvm/Analysis/EHPersonalities.h" 15 | #include "llvm/CodeGen/MachineFrameInfo.h" 16 | #include "llvm/CodeGen/MachineFunction.h" 17 | #include "llvm/CodeGen/MachineInstrBuilder.h" 18 | #include "llvm/CodeGen/MachineModuleInfo.h" 19 | #include "llvm/CodeGen/MachineRegisterInfo.h" 20 | #include "llvm/CodeGen/WinEHFuncInfo.h" 21 | #include "llvm/IR/DataLayout.h" 22 | #include "llvm/IR/Function.h" 23 | #include "llvm/MC/MCAsmInfo.h" 24 | #include "llvm/MC/MCSymbol.h" 25 | #include "llvm/Support/Debug.h" 26 | #include "llvm/Target/TargetOptions.h" 27 | #include "ShadowStack/ShadowStackConstants.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | using namespace llvm; 35 | 36 | extern cl::opt parallel; 37 | 38 | extern cl::opt mpk; 39 | 40 | 41 | namespace{ 42 | class X86ShadowStackMem : public MachineFunctionPass{ 43 | public: 44 | static char ID; 45 | X86ShadowStackMem() : MachineFunctionPass(ID){} 46 | StringRef getPassName() const override { 47 | return "X86 Shadow Stack Memory Scheme"; } 48 | bool runOnMachineFunction(MachineFunction &MF) override; 49 | }; 50 | } 51 | char X86ShadowStackMem::ID = 0; 52 | 53 | FunctionPass *llvm::createX86ShadowStackMem() { return new X86ShadowStackMem(); } 54 | 55 | extern bool mayWriteMem(const MachineFunction &MF); 56 | extern void WRPKRUI(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, int imm); 57 | extern void XORReg(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, unsigned Reg); 58 | extern void checkRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 59 | extern void checkRALBP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 60 | extern void checkRAJMP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 61 | extern void checkRASilence(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 62 | 63 | 64 | static void emitShadowStackPrologue(MachineFunction &MF) 65 | { 66 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 67 | 68 | const DebugLoc DL = MF.front().size() == 0 ? DebugLoc() :MF.front().front().getDebugLoc(); 69 | 70 | //put all the shadow stack code in a separate MBB 71 | MachineBasicBlock &MBB = MF.front(); 72 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 73 | //save ecx and edx 74 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RCX, RegState::Kill); 75 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RDX, RegState::Kill); 76 | if(mpk.getValue()) 77 | { 78 | //disable MPK protections 79 | WRPKRUI(MBB, MBBI, DL, TII, 0); 80 | } 81 | //get the return addr 82 | //mov RAX, [rsp] 83 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RAX); 84 | addRegOffset(getRA, X86::RSP, false, 0); 85 | 86 | //movabs rdx, SHADOW_STACK_PTR 87 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RDX).addImm((int64_t)SHADOW_STACK_PTR); 88 | //mov RCX, [RDX]; 89 | MachineInstrBuilder getPtr = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RCX); 90 | addDirectMem(getPtr, X86::RDX); 91 | 92 | 93 | //mov [RCX], RAX 94 | MachineInstrBuilder putRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 95 | addRegOffset(putRA, X86::RCX, false, 0); 96 | putRA.addReg(X86::RAX); 97 | //mov [RCX+8], RSP 98 | MachineInstrBuilder putRSP = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 99 | addRegOffset(putRSP, X86::RCX, false, 8).addReg(X86::RSP); 100 | 101 | 102 | //add [RDX], 8 103 | MachineInstrBuilder addPtr = BuildMI(MBB, MBBI, DL, TII->get(X86::ADD64mi8)); 104 | addDirectMem(addPtr, X86::RDX); 105 | addPtr.addImm(16); 106 | 107 | if(mpk.getValue()) 108 | { 109 | XORReg(MBB, MBBI, DL, TII, X86::RCX); 110 | XORReg(MBB, MBBI, DL, TII, X86::RDX); 111 | //reenable protection 112 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 113 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 114 | } 115 | //restore ecx and edx 116 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RCX).addReg(X86::R10, RegState::Kill); 117 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R11, RegState::Kill); 118 | } 119 | 120 | static void emitShadowStackEpilogue(MachineBasicBlock &MBB) 121 | { 122 | MachineBasicBlock::iterator &MBBI = --MBB.end(); 123 | 124 | const DebugLoc &DL = MBBI->getDebugLoc(); 125 | const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); 126 | 127 | const MachineInstr &back = MBB.back(); 128 | //If tail call needs to use R10, R11 129 | if(back.readsRegister(X86::R11)) 130 | { 131 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 132 | addRegOffset(saveR11, X86::RSP, false, -16).addReg(X86::R11); 133 | } 134 | if(back.readsRegister(X86::R10)) 135 | { 136 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 137 | addRegOffset(saveR10, X86::RSP, false, -24).addReg(X86::R10); 138 | } 139 | 140 | //save ret value in rax 141 | //mov r10, rax 142 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RAX); 143 | //save RCX, RDX 144 | BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH64r)).addReg(X86::RDX); 145 | if(mpk.getValue()) 146 | { 147 | BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH64r)).addReg(X86::RCX); 148 | //disable protection 149 | WRPKRUI(MBB, MBBI, DL, TII, 0); 150 | } 151 | //mov rdx, SHADOW_STACK_PTR 152 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RDX).addImm((int64_t)SHADOW_STACK_PTR); 153 | //sub [rdx], 8 154 | MachineInstrBuilder subPtr = BuildMI(MBB, MBBI, DL, TII->get(X86::SUB64mi8)); 155 | addDirectMem(subPtr, X86::RDX); 156 | subPtr.addImm(16); 157 | 158 | //r11 now points to top of shadow stack 159 | //mov r11, [rdx] 160 | MachineInstrBuilder getPtr = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 161 | addDirectMem(getPtr, X86::RDX); 162 | //R11 now contains RA 163 | //mov r11, [r11] 164 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 165 | addDirectMem(getRA, X86::R11); 166 | if(mpk.getValue()) 167 | { 168 | XORReg(MBB, MBBI, DL, TII, X86::RDX); 169 | //renable protection 170 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 171 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 172 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::RCX); 173 | } 174 | //restore RCX, RDX 175 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::RDX); 176 | 177 | 178 | //restore rax 179 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RAX).addReg(X86::R10); 180 | 181 | //check RA in r11 182 | checkRA(MBB, MBBI, TII); 183 | 184 | //restore R10, R11 if necessary 185 | if(back.readsRegister(X86::R11)) 186 | { 187 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 188 | addRegOffset(saveR11, X86::RSP, false, -16); 189 | } 190 | if(back.readsRegister(X86::R10)) 191 | { 192 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10); 193 | addRegOffset(saveR10, X86::RSP, false, -24); 194 | } 195 | } 196 | 197 | 198 | bool X86ShadowStackMem::runOnMachineFunction(MachineFunction &MF) { 199 | if(!mayWriteMem(MF))return false; 200 | emitShadowStackPrologue(MF); 201 | for (MachineBasicBlock &MBB : MF) 202 | { 203 | if (MBB.isReturnBlock()) 204 | { 205 | emitShadowStackEpilogue(MBB); 206 | } 207 | } 208 | return true; 209 | } 210 | void checkRALBP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII) 211 | { 212 | DebugLoc DL = MBBI->getDebugLoc(); 213 | if(!MBB.back().isCall()) 214 | { 215 | //pop r10 216 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::R10); 217 | }else 218 | { 219 | //mov r10, [rsp] 220 | addDirectMem( 221 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10) 222 | , X86::RSP); 223 | } 224 | 225 | //xor r11, r10 226 | BuildMI(MBB, MBBI, DL, TII->get(X86::XOR64rr), X86::R11) 227 | .addReg(X86::R11) 228 | .addReg(X86::R10); 229 | 230 | //popcnt r11, r11 231 | BuildMI(MBB, MBBI, DL, TII->get(X86::POPCNT64rr), X86::R11) 232 | .addReg(X86::R11); 233 | 234 | //mov gs:[r11], 0 235 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV8rm), X86::R11B) 236 | .addReg(0) //base 237 | .addImm(1) //scale 238 | .addReg(X86::R11) //index 239 | .addImm((int64_t)SHADOW_STACK_SENTINEL+4095) //disp 240 | .addReg(0); //segment 241 | 242 | 243 | if(!MBB.back().isCall()) 244 | { 245 | BuildMI(MBB, MBBI, DL, TII->get(X86::JMP64r), X86::R10); 246 | //MBB.back().eraseFromParent(); 247 | } 248 | } 249 | 250 | void checkRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII) 251 | { 252 | DebugLoc DL = MBBI->getDebugLoc(); 253 | //mov r10, rsp 254 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RSP); 255 | 256 | //xor r11, [rsp] 257 | MachineInstrBuilder cmp = BuildMI(MBB, MBBI, DL, TII->get(X86::XOR64rm), X86::R11).addReg(X86::R11); 258 | addDirectMem(cmp, X86::RSP); 259 | 260 | //mov rsp, 0 261 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RSP) 262 | .addImm(0); 263 | //cmove rsp, r10 264 | BuildMI(MBB, MBBI, DL, TII->get(X86::CMOVE64rr), X86::RSP) 265 | .addReg(X86::RSP) 266 | .addReg(X86::R10); 267 | } 268 | 269 | static void checkRANew(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII) 270 | { 271 | DebugLoc DL = MBBI->getDebugLoc(); 272 | addDirectMem( 273 | BuildMI(MBB, MBBI, DL, TII->get(X86::CMP64rm), X86::R11) 274 | , X86::RSP); 275 | BuildMI(MBB, MBBI, DL, TII->get(X86::CMOVNE64rm), X86::R11) 276 | .addReg(X86::R11) 277 | .addReg(0) //base 278 | .addImm(1) //scale 279 | .addReg(0) //index 280 | .addImm(0) //disp 281 | .addReg(0); //segment 282 | } 283 | void checkRAJMP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII) 284 | { 285 | DebugLoc DL = MBBI->getDebugLoc(); 286 | if(!MBB.back().isCall()) 287 | { 288 | //pop r10 289 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::R10); 290 | }else 291 | { 292 | //mov r10, [rsp] 293 | addDirectMem( 294 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10) 295 | , X86::RSP); 296 | } 297 | 298 | //xor r11, r10 299 | BuildMI(MBB, MBBI, DL, TII->get(X86::XOR64rr), X86::R11) 300 | .addReg(X86::R11) 301 | .addReg(X86::R10); 302 | 303 | //popcnt r11, r11 304 | BuildMI(MBB, MBBI, DL, TII->get(X86::POPCNT64rr), X86::R11).addReg(X86::R11); 305 | BuildMI(MBB, MBBI, DL, TII->get(X86::SHL64ri), X86::R11) 306 | .addReg(X86::R11) 307 | .addImm(48); 308 | 309 | //or r11, r10 310 | BuildMI(MBB, MBBI, DL, TII->get(X86::OR64rr), X86::R11) 311 | .addReg(X86::R11) 312 | .addReg(X86::R10); 313 | if(!MBB.back().isCall()) 314 | { 315 | //jmp r11 316 | BuildMI(MBB, MBBI, DL, TII->get(X86::JMP64r), X86::R11); 317 | //MBB.back().eraseFromParent(); 318 | }else 319 | { 320 | //no return for tail call, instead just do a read 321 | //mov r11b, [r11] 322 | addDirectMem( 323 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV8rm), X86::R11B) 324 | , X86::R11); 325 | } 326 | } 327 | 328 | void checkRASilence(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII) 329 | { 330 | DebugLoc DL = MBBI->getDebugLoc(); 331 | if(!MBB.back().isCall()) 332 | { 333 | BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), X86::RSP) 334 | .addReg(X86::RSP) //base 335 | .addImm(1) //scale 336 | .addReg(0) //index 337 | .addImm(8) //disp 338 | .addReg(0); //segment 339 | //jmp r11 340 | BuildMI(MBB, MBBI, DL, TII->get(X86::JMP64r), X86::R11); 341 | //MBB.back().eraseFromParent(); 342 | }else 343 | { 344 | MachineInstrBuilder writeRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 345 | addDirectMem(writeRA, X86::RSP); 346 | writeRA.addReg(X86::R11); 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86ShadowStackReg.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // X86ShadowStackReg.cpp 3 | // LLVMX86CodeGen 4 | // 5 | // Created by Kelvin Zhang on 2/8/18. 6 | // 7 | #include "X86InstrBuilder.h" 8 | #include "X86InstrInfo.h" 9 | #include "X86MachineFunctionInfo.h" 10 | #include "X86Subtarget.h" 11 | #include "X86TargetMachine.h" 12 | #include "llvm/ADT/SmallSet.h" 13 | #include "llvm/Analysis/EHPersonalities.h" 14 | #include "llvm/CodeGen/MachineFrameInfo.h" 15 | #include "llvm/CodeGen/MachineFunction.h" 16 | #include "llvm/CodeGen/MachineInstrBuilder.h" 17 | #include "llvm/CodeGen/MachineModuleInfo.h" 18 | #include "llvm/CodeGen/MachineRegisterInfo.h" 19 | #include "llvm/CodeGen/WinEHFuncInfo.h" 20 | #include "llvm/IR/DataLayout.h" 21 | #include "llvm/IR/Function.h" 22 | #include "llvm/MC/MCAsmInfo.h" 23 | #include "llvm/MC/MCSymbol.h" 24 | #include "llvm/Support/Debug.h" 25 | #include "llvm/Target/TargetOptions.h" 26 | #include "ShadowStack/ShadowStackFeatures.h" 27 | #include "ShadowStack/ShadowStackConstants.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | using namespace llvm; 36 | extern cl::opt parallel; 37 | extern cl::opt epilog; 38 | 39 | namespace{ 40 | class X86ShadowStackReg : public MachineFunctionPass{ 41 | public: 42 | static char ID; 43 | X86ShadowStackReg() : MachineFunctionPass(ID){} 44 | StringRef getPassName() const override { return "X86 Shadow Stack Register Scheme"; } 45 | bool runOnMachineFunction(MachineFunction &MF) override; 46 | }; 47 | } 48 | 49 | char X86ShadowStackReg::ID = 0; 50 | 51 | FunctionPass *llvm::createX86ShadowStackReg() { return new X86ShadowStackReg(); } 52 | 53 | extern bool mayWriteMem(const MachineFunction &MF); 54 | extern void WRPKRUI(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, int imm); 55 | extern void checkRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 56 | extern void checkRALBP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 57 | extern void checkRAJMP(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 58 | extern void checkRASilence(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 59 | 60 | static void emitMinimalRegisterProlog(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc DL, const TargetInstrInfo *TII) 61 | { 62 | //get the return addr 63 | //mov RAX, [rsp] 64 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RAX); 65 | addDirectMem(getRA, X86::RSP); 66 | 67 | //store return addr 68 | //mov [r15], RAX 69 | MachineInstrBuilder putRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 70 | addDirectMem(putRA, X86::R15); 71 | putRA.addReg(X86::RAX); 72 | 73 | //mov [r15+8], rsp 74 | MachineInstrBuilder putRSP = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 75 | addRegOffset(putRSP, X86::R15, false, 8); 76 | putRSP.addReg(X86::RSP); 77 | 78 | //lea r15, [r15 + 16] 79 | BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), X86::R15) 80 | .addReg(X86::R15) //base 81 | .addImm(1) //scale 82 | .addReg(0) //index 83 | .addImm(16) //disp 84 | .addReg(0); //segment 85 | } 86 | 87 | static void emitParallelRegisterProlog(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc DL, const TargetInstrInfo *TII) 88 | { 89 | 90 | //get the return addr 91 | //mov RAX, [rsp] 92 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RAX); 93 | addDirectMem(getRA, X86::RSP); 94 | 95 | //store return addr 96 | //mov [rsp+r15], RAX 97 | MachineInstrBuilder putRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 98 | addRegReg(putRA, X86::RSP, false, X86::R15, false); 99 | putRA.addReg(X86::RAX); 100 | } 101 | 102 | static void emitRegisterProlog(MachineFunction &MF) 103 | { 104 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 105 | const DebugLoc DL = MF.front().size() == 0 ? DebugLoc() :MF.front().front().getDebugLoc(); 106 | MachineBasicBlock &MBB = MF.front(); 107 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 108 | 109 | #ifdef SHADOW_STACK_MPK 110 | //save ecx and edx 111 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RCX, RegState::Kill); 112 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RDX, RegState::Kill); 113 | 114 | //disable MPK protections 115 | WRPKRUI(MBB, MBBI, DL, TII, 0); 116 | #endif 117 | 118 | #ifndef SHADOW_STACK_PARR 119 | emitMinimalRegisterProlog(MBB, MBBI, DL, TII); 120 | #else 121 | emitParallelRegisterProlog(MBB, MBBI, DL, TII); 122 | #endif 123 | 124 | #ifdef SHADOW_STACK_MPK 125 | //reenable protection 126 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 127 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 128 | 129 | //restore ecx and edx 130 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RCX).addReg(X86::R10, RegState::Kill); 131 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R11, RegState::Kill); 132 | #endif 133 | } 134 | 135 | //read shadow RA into R11 136 | static void emitParallelRegisterEpilog(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc DL, const TargetInstrInfo *TII) 137 | { 138 | //mov r11, [rsp+r15] 139 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 140 | addRegReg(getRA, X86::RSP, false, X86::R15, false); 141 | } 142 | 143 | //read shadow RA into r11 144 | static void emitMinimalRegisterEpilog(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc DL, const TargetInstrInfo *TII) 145 | { 146 | //mov r11, [r15-8] 147 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 148 | addRegOffset(getRA, X86::R15, false, -16); 149 | //lea r15, [r15-16] 150 | BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), X86::R15) 151 | .addReg(X86::R15) //base 152 | .addImm(1) //scale 153 | .addReg(0) //index 154 | .addImm(-16) //disp 155 | .addReg(0); //segment 156 | } 157 | static void emitRegisterEpilog(MachineBasicBlock &MBB) 158 | { 159 | MachineBasicBlock::iterator &MBBI = --MBB.end(); 160 | 161 | const DebugLoc &DL = MBBI->getDebugLoc(); 162 | const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); 163 | const MachineInstr &back = MBB.back(); 164 | 165 | bool saveR10 = back.readsRegister(X86::R10); 166 | bool saveR11 = back.readsRegister(X86::R11); 167 | 168 | //If tail call needs R10, R11 169 | if(saveR11) 170 | { 171 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 172 | addRegOffset(saveR11, X86::RSP, false, -16).addReg(X86::R11); 173 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RAX).addReg(X86::R11); 174 | } 175 | if(saveR10) 176 | { 177 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 178 | addRegOffset(saveR10, X86::RSP, false, -24).addReg(X86::R10); 179 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R10); 180 | } 181 | #ifndef SHADOW_STACK_PARR 182 | emitMinimalRegisterEpilog(MBB, MBBI, DL, TII); 183 | #else 184 | emitParallelRegisterEpilog(MBB, MBBI, DL, TII); 185 | #endif 186 | 187 | //checkRAJMP(MBB, MBBI, TII); 188 | checkRALBP(MBB, MBBI, TII); 189 | //checkRA(MBB, MBBI, TII); 190 | 191 | //Restore R10, R11 192 | if(saveR11) 193 | { 194 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 195 | addRegOffset(saveR11, X86::RSP, false, -16); 196 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RAX); 197 | } 198 | if(saveR10) 199 | { 200 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10); 201 | addRegOffset(saveR10, X86::RSP, false, -24); 202 | //BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RDX); 203 | } 204 | } 205 | 206 | static bool isGlobalConstructor(const MachineFunction &MF) 207 | { 208 | const Module *MOD = MF.getFunction().getParent(); 209 | GlobalVariable *ctors = MOD->getGlobalVariable("llvm.global_ctors"); 210 | if(ctors == NULL)return false; 211 | ConstantArray *CA = dyn_cast(ctors->getInitializer()); 212 | if(CA) 213 | { 214 | for(Use &OP : CA->operands()) 215 | { 216 | if(isa(OP))continue; 217 | ConstantStruct *CS = cast(OP); 218 | if(Function *F = dyn_cast(CS->getOperand(1))) 219 | { 220 | if(F->getName() == MF.getFunction().getName())return true; 221 | } 222 | } 223 | } 224 | ctors = MOD->getGlobalVariable("llvm.global_dtors"); 225 | if(ctors == NULL)return false; 226 | CA = dyn_cast(ctors->getInitializer()); 227 | if(CA) 228 | { 229 | for(Use &OP : CA->operands()) 230 | { 231 | if(isa(OP))continue; 232 | ConstantStruct *CS = cast(OP); 233 | if(Function *F = dyn_cast(CS->getOperand(1))) 234 | { 235 | if(F->getName() == MF.getFunction().getName())return true; 236 | } 237 | } 238 | } 239 | return false; 240 | } 241 | 242 | static void loadR15(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, 243 | const DebugLoc &DL, const TargetInstrInfo *TII) 244 | { 245 | #ifndef SHADOW_STACK_PARR 246 | //read gs:[16], contains top of shadow stack 247 | //mov r15, gs:[0] 248 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R15) 249 | .addReg(0) //base 250 | .addImm(1) //scale 251 | .addReg(0) //index 252 | .addImm(16) //disp 253 | .addReg(X86::GS); //segment 254 | #else 255 | //read gs:[0], contains offset of shadow stack 256 | //mov r15, gs:[0] 257 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R15) 258 | .addReg(0) //base 259 | .addImm(1) //scale 260 | .addReg(0) //index 261 | .addImm(0) //disp 262 | .addReg(X86::GS); //segment 263 | #endif 264 | } 265 | 266 | bool X86ShadowStackReg::runOnMachineFunction(MachineFunction &MF) 267 | { 268 | const bool unsafe = mayWriteMem(MF); 269 | if (unsafe) 270 | emitRegisterProlog(MF); 271 | 272 | if(isGlobalConstructor(MF)) 273 | { 274 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 275 | const DebugLoc DL = MF.front().front().getDebugLoc(); 276 | MachineBasicBlock &MBB = MF.front(); 277 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 278 | loadR15(MBB, MBBI, DL, TII); 279 | return true; 280 | } 281 | 282 | if(MF.getFunction().getName() == "main") 283 | { 284 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 285 | const DebugLoc DL = MF.front().front().getDebugLoc(); 286 | MachineBasicBlock &MBB = MF.front(); 287 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 288 | loadR15(MBB, MBBI, DL, TII); 289 | } 290 | 291 | if(!unsafe)return true; 292 | 293 | for (MachineBasicBlock &MBB : MF) 294 | { 295 | if (MBB.isReturnBlock()) 296 | { 297 | emitRegisterEpilog(MBB); 298 | } 299 | } 300 | return true; 301 | } 302 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86ShadowStackSeg.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // X86ShadowStackSeg.cpp 3 | // LLVMX86CodeGen 4 | // 5 | // Created by Kelvin Zhang on 2/17/18. 6 | // 7 | #include "X86InstrBuilder.h" 8 | #include "X86InstrInfo.h" 9 | #include "X86MachineFunctionInfo.h" 10 | #include "X86Subtarget.h" 11 | #include "X86TargetMachine.h" 12 | #include "llvm/ADT/SmallSet.h" 13 | #include "llvm/Analysis/EHPersonalities.h" 14 | #include "llvm/CodeGen/MachineFrameInfo.h" 15 | #include "llvm/CodeGen/MachineFunction.h" 16 | #include "llvm/CodeGen/MachineInstrBuilder.h" 17 | #include "llvm/CodeGen/MachineModuleInfo.h" 18 | #include "llvm/CodeGen/MachineRegisterInfo.h" 19 | #include "llvm/CodeGen/WinEHFuncInfo.h" 20 | #include "llvm/IR/DataLayout.h" 21 | #include "llvm/IR/Function.h" 22 | #include "llvm/MC/MCAsmInfo.h" 23 | #include "llvm/MC/MCSymbol.h" 24 | #include "llvm/Support/Debug.h" 25 | #include "llvm/Target/TargetOptions.h" 26 | #include "ShadowStack/ShadowStackConstants.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | using namespace llvm; 35 | extern cl::opt mpk; 36 | 37 | namespace{ 38 | class X86ShadowStackSeg : public MachineFunctionPass{ 39 | public: 40 | static char ID; 41 | X86ShadowStackSeg() : MachineFunctionPass(ID){} 42 | StringRef getPassName() const override { 43 | return "X86 Shadow Stack Segment Scheme"; } 44 | bool runOnMachineFunction(MachineFunction &MF) override; 45 | }; 46 | } 47 | 48 | char X86ShadowStackSeg::ID = 0; 49 | 50 | FunctionPass *llvm::createX86ShadowStackSeg() { return new X86ShadowStackSeg(); } 51 | 52 | extern bool mayWriteMem(const MachineFunction &MF); 53 | extern void WRPKRUI(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, int imm); 54 | extern void XORReg(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, unsigned Reg); 55 | extern void checkRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo *TII); 56 | 57 | static void emitSegmentProlog(MachineFunction &MF) 58 | { 59 | const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 60 | const DebugLoc DL = MF.front().size() == 0 ? DebugLoc() :MF.front().front().getDebugLoc(); 61 | MachineBasicBlock &MBB = MF.front(); 62 | const MachineBasicBlock::iterator &MBBI = MBB.begin(); 63 | 64 | unsigned raReg = X86::R10; 65 | if(mpk.getValue()) 66 | { 67 | raReg = X86::RCX; 68 | //save ecx and edx 69 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(X86::RCX, RegState::Kill); 70 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R11).addReg(X86::RDX, RegState::Kill); 71 | 72 | //disable MPK protections 73 | WRPKRUI(MBB, MBBI, DL, TII, 0); 74 | } 75 | //get the return addr 76 | //mov RAX, [rsp] 77 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::RAX); 78 | addDirectMem(getRA, X86::RSP); 79 | 80 | //mov raReg, fs[0] 81 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), raReg) 82 | .addReg(0) //base 83 | .addImm(1) //scale 84 | .addReg(0) //index 85 | .addImm(0) //disp 86 | .addReg(X86::GS); //segment 87 | 88 | //mov [raReg], rax 89 | MachineInstrBuilder putRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 90 | addDirectMem(putRA, raReg).addReg(X86::RAX); 91 | 92 | //mov [raReg+8], rax 93 | MachineInstrBuilder putSP = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 94 | addRegOffset(putSP, raReg, false, 8).addReg(X86::RSP); 95 | 96 | //add raReg, 16 97 | BuildMI(MBB, MBBI, DL, TII->get(X86::ADD64ri8), raReg) 98 | .addReg(raReg) 99 | .addImm(MF.getDataLayout().getPointerSize() * 2); 100 | 101 | //update shadow stack pointer 102 | //mov fs:[0], raReg 103 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)) 104 | .addReg(0) //base 105 | .addImm(1) //scale 106 | .addReg(0) //index 107 | .addImm(0) //disp 108 | .addReg(X86::GS) //segment 109 | .addReg(raReg); //raReg... 110 | 111 | if(mpk.getValue()) 112 | { 113 | XORReg(MBB, MBBI, DL, TII, X86::ECX); 114 | //reenable protection 115 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 116 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 117 | 118 | //restore ecx and edx 119 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RCX).addReg(X86::R10, RegState::Kill); 120 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::RDX).addReg(X86::R11, RegState::Kill); 121 | } 122 | } 123 | 124 | 125 | 126 | static void emitSegmentEpilog(MachineBasicBlock &MBB) 127 | { 128 | MachineBasicBlock::iterator &MBBI = --MBB.end(); 129 | 130 | const DebugLoc &DL = MBBI->getDebugLoc(); 131 | const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); 132 | const int PtrSize = MBB.getParent()->getDataLayout().getPointerSize(); 133 | const MachineInstr &back = MBB.back(); 134 | const bool isTailCall = MBB.back().isCall(); 135 | 136 | //If tail call 137 | //Save RCX RDX, they might be used as parameters 138 | //If return site 139 | //Save RAX RDX, they might be used as return value 140 | unsigned Reg1 = isTailCall ? X86::RCX : X86::RAX; 141 | 142 | //If Tail call needs R11,R10 143 | if(back.readsRegister(X86::R11)) 144 | { 145 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 146 | addRegOffset(saveR11, X86::RSP, false, -16).addReg(X86::R11); 147 | } 148 | if(back.readsRegister(X86::R10)) 149 | { 150 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)); 151 | addRegOffset(saveR10, X86::RSP, false, -24).addReg(X86::R10); 152 | } 153 | 154 | //just pop the shadow stack. 155 | if(mpk.getValue()) 156 | { 157 | if(MBB.back().readsRegister(X86::RAX)) 158 | { 159 | BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH64r), X86::RAX); 160 | } 161 | //If tail call 162 | //Save RCX RDX, they might be used as parameters 163 | //If return site 164 | //Save RAX RDX, they might be used as return value 165 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), X86::R10).addReg(Reg1); 166 | BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH64r), X86::RDX); 167 | //disable MPK protections 168 | WRPKRUI(MBB, MBBI, DL, TII, 0); 169 | } 170 | //mov r11, gs:[0] 171 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11) 172 | .addReg(0) //base reg 173 | .addImm(1) //scale 174 | .addReg(0) //index 175 | .addImm(0) //disp 176 | .addReg(X86::GS); //segment 177 | 178 | //sub R11, 8 179 | BuildMI(MBB, MBBI, DL, TII->get(X86::SUB64ri8), X86::R11) 180 | .addReg(X86::R11) 181 | .addImm(PtrSize*2); 182 | 183 | //mov gs:[0], R11 184 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)) 185 | .addReg(0) //base reg 186 | .addImm(1) //scale 187 | .addReg(0) //index 188 | .addImm(0) //disp 189 | .addReg(X86::GS) //segment 190 | .addReg(X86::R11); 191 | 192 | //mov R11, [R11] 193 | MachineInstrBuilder getRA = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 194 | addDirectMem(getRA, X86::R11); 195 | 196 | if(mpk.getValue()) 197 | { 198 | //reenable protection 199 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(WRITE_PROTECTION); 200 | BuildMI(MBB, MBBI, DL, TII->get(X86::WRPKRUr)); 201 | 202 | //restore RCX and RDX 203 | BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rr), Reg1).addReg(X86::R10, RegState::Kill); 204 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::RDX); 205 | if(MBB.back().readsRegister(X86::RAX)) 206 | { 207 | BuildMI(MBB, MBBI, DL, TII->get(X86::POP64r), X86::RAX); 208 | } 209 | } 210 | 211 | checkRA(MBB, MBBI, TII); 212 | //Restore R10, R11 if necessary 213 | if(back.readsRegister(X86::R11)) 214 | { 215 | MachineInstrBuilder saveR11 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R11); 216 | addRegOffset(saveR11, X86::RSP, false, -16); 217 | } 218 | if(back.readsRegister(X86::R10)) 219 | { 220 | MachineInstrBuilder saveR10 = BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm), X86::R10); 221 | addRegOffset(saveR10, X86::RSP, false, -24); 222 | } 223 | } 224 | 225 | bool X86ShadowStackSeg::runOnMachineFunction(MachineFunction &MF) 226 | { 227 | if(!mayWriteMem(MF))return false; 228 | emitSegmentProlog(MF); 229 | for (MachineBasicBlock &MBB : MF) 230 | { 231 | if (MBB.isReturnBlock()) 232 | { 233 | emitSegmentEpilog(MBB); 234 | } 235 | } 236 | return true; 237 | } 238 | -------------------------------------------------------------------------------- /Compiler-Impl/src/X86TargetMachine.cpp: -------------------------------------------------------------------------------- 1 | //===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the X86 specific subclass of TargetMachine. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "X86TargetMachine.h" 15 | #include "MCTargetDesc/X86MCTargetDesc.h" 16 | #include "X86.h" 17 | #include "X86CallLowering.h" 18 | #include "X86LegalizerInfo.h" 19 | #include "X86MacroFusion.h" 20 | #include "X86Subtarget.h" 21 | #include "X86TargetObjectFile.h" 22 | #include "X86TargetTransformInfo.h" 23 | #include "llvm/ADT/Optional.h" 24 | #include "llvm/ADT/STLExtras.h" 25 | #include "llvm/ADT/SmallString.h" 26 | #include "llvm/ADT/StringRef.h" 27 | #include "llvm/ADT/Triple.h" 28 | #include "llvm/Analysis/TargetTransformInfo.h" 29 | #include "llvm/CodeGen/ExecutionDomainFix.h" 30 | #include "llvm/CodeGen/GlobalISel/CallLowering.h" 31 | #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 32 | #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 33 | #include "llvm/CodeGen/GlobalISel/Legalizer.h" 34 | #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 35 | #include "llvm/CodeGen/MachineScheduler.h" 36 | #include "llvm/CodeGen/Passes.h" 37 | #include "llvm/CodeGen/TargetPassConfig.h" 38 | #include "llvm/IR/Attributes.h" 39 | #include "llvm/IR/DataLayout.h" 40 | #include "llvm/IR/Function.h" 41 | #include "llvm/Pass.h" 42 | #include "llvm/Support/CodeGen.h" 43 | #include "llvm/Support/CommandLine.h" 44 | #include "llvm/Support/ErrorHandling.h" 45 | #include "llvm/Support/TargetRegistry.h" 46 | #include "llvm/Target/TargetLoweringObjectFile.h" 47 | #include "llvm/Target/TargetOptions.h" 48 | #include 49 | #include 50 | #include 51 | 52 | using namespace llvm; 53 | 54 | static cl::opt EnableMachineCombinerPass("x86-machine-combiner", 55 | cl::desc("Enable the machine combiner pass"), 56 | cl::init(true), cl::Hidden); 57 | 58 | namespace llvm { 59 | 60 | void initializeWinEHStatePassPass(PassRegistry &); 61 | void initializeFixupLEAPassPass(PassRegistry &); 62 | void initializeShadowCallStackPass(PassRegistry &); 63 | void initializeX86CallFrameOptimizationPass(PassRegistry &); 64 | void initializeX86CmovConverterPassPass(PassRegistry &); 65 | void initializeX86ExecutionDomainFixPass(PassRegistry &); 66 | void initializeX86DomainReassignmentPass(PassRegistry &); 67 | void initializeX86AvoidSFBPassPass(PassRegistry &); 68 | void initializeX86FlagsCopyLoweringPassPass(PassRegistry &); 69 | 70 | } // end namespace llvm 71 | 72 | extern "C" void LLVMInitializeX86Target() { 73 | // Register the target. 74 | RegisterTargetMachine X(getTheX86_32Target()); 75 | RegisterTargetMachine Y(getTheX86_64Target()); 76 | 77 | PassRegistry &PR = *PassRegistry::getPassRegistry(); 78 | initializeGlobalISel(PR); 79 | initializeWinEHStatePassPass(PR); 80 | initializeFixupBWInstPassPass(PR); 81 | initializeEvexToVexInstPassPass(PR); 82 | initializeFixupLEAPassPass(PR); 83 | initializeShadowCallStackPass(PR); 84 | initializeX86CallFrameOptimizationPass(PR); 85 | initializeX86CmovConverterPassPass(PR); 86 | initializeX86ExecutionDomainFixPass(PR); 87 | initializeX86DomainReassignmentPass(PR); 88 | initializeX86AvoidSFBPassPass(PR); 89 | initializeX86FlagsCopyLoweringPassPass(PR); 90 | } 91 | 92 | static std::unique_ptr createTLOF(const Triple &TT) { 93 | if (TT.isOSBinFormatMachO()) { 94 | if (TT.getArch() == Triple::x86_64) 95 | return llvm::make_unique(); 96 | return llvm::make_unique(); 97 | } 98 | 99 | if (TT.isOSFreeBSD()) 100 | return llvm::make_unique(); 101 | if (TT.isOSLinux() || TT.isOSNaCl() || TT.isOSIAMCU()) 102 | return llvm::make_unique(); 103 | if (TT.isOSSolaris()) 104 | return llvm::make_unique(); 105 | if (TT.isOSFuchsia()) 106 | return llvm::make_unique(); 107 | if (TT.isOSBinFormatELF()) 108 | return llvm::make_unique(); 109 | if (TT.isKnownWindowsMSVCEnvironment() || TT.isWindowsCoreCLREnvironment()) 110 | return llvm::make_unique(); 111 | if (TT.isOSBinFormatCOFF()) 112 | return llvm::make_unique(); 113 | llvm_unreachable("unknown subtarget type"); 114 | } 115 | 116 | static std::string computeDataLayout(const Triple &TT) { 117 | // X86 is little endian 118 | std::string Ret = "e"; 119 | 120 | Ret += DataLayout::getManglingComponent(TT); 121 | // X86 and x32 have 32 bit pointers. 122 | if ((TT.isArch64Bit() && 123 | (TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) || 124 | !TT.isArch64Bit()) 125 | Ret += "-p:32:32"; 126 | 127 | // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32. 128 | if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl()) 129 | Ret += "-i64:64"; 130 | else if (TT.isOSIAMCU()) 131 | Ret += "-i64:32-f64:32"; 132 | else 133 | Ret += "-f64:32:64"; 134 | 135 | // Some ABIs align long double to 128 bits, others to 32. 136 | if (TT.isOSNaCl() || TT.isOSIAMCU()) 137 | ; // No f80 138 | else if (TT.isArch64Bit() || TT.isOSDarwin()) 139 | Ret += "-f80:128"; 140 | else 141 | Ret += "-f80:32"; 142 | 143 | if (TT.isOSIAMCU()) 144 | Ret += "-f128:32"; 145 | 146 | // The registers can hold 8, 16, 32 or, in x86-64, 64 bits. 147 | if (TT.isArch64Bit()) 148 | Ret += "-n8:16:32:64"; 149 | else 150 | Ret += "-n8:16:32"; 151 | 152 | // The stack is aligned to 32 bits on some ABIs and 128 bits on others. 153 | if ((!TT.isArch64Bit() && TT.isOSWindows()) || TT.isOSIAMCU()) 154 | Ret += "-a:0:32-S32"; 155 | else 156 | Ret += "-S128"; 157 | 158 | return Ret; 159 | } 160 | 161 | static Reloc::Model getEffectiveRelocModel(const Triple &TT, 162 | Optional RM) { 163 | bool is64Bit = TT.getArch() == Triple::x86_64; 164 | if (!RM.hasValue()) { 165 | // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode. 166 | // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we 167 | // use static relocation model by default. 168 | if (TT.isOSDarwin()) { 169 | if (is64Bit) 170 | return Reloc::PIC_; 171 | return Reloc::DynamicNoPIC; 172 | } 173 | if (TT.isOSWindows() && is64Bit) 174 | return Reloc::PIC_; 175 | return Reloc::Static; 176 | } 177 | 178 | // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC 179 | // is defined as a model for code which may be used in static or dynamic 180 | // executables but not necessarily a shared library. On X86-32 we just 181 | // compile in -static mode, in x86-64 we use PIC. 182 | if (*RM == Reloc::DynamicNoPIC) { 183 | if (is64Bit) 184 | return Reloc::PIC_; 185 | if (!TT.isOSDarwin()) 186 | return Reloc::Static; 187 | } 188 | 189 | // If we are on Darwin, disallow static relocation model in X86-64 mode, since 190 | // the Mach-O file format doesn't support it. 191 | if (*RM == Reloc::Static && TT.isOSDarwin() && is64Bit) 192 | return Reloc::PIC_; 193 | 194 | return *RM; 195 | } 196 | 197 | static CodeModel::Model getEffectiveCodeModel(Optional CM, 198 | bool JIT, bool Is64Bit) { 199 | if (CM) 200 | return *CM; 201 | if (JIT) 202 | return Is64Bit ? CodeModel::Large : CodeModel::Small; 203 | return CodeModel::Small; 204 | } 205 | 206 | /// Create an X86 target. 207 | /// 208 | X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, 209 | StringRef CPU, StringRef FS, 210 | const TargetOptions &Options, 211 | Optional RM, 212 | Optional CM, 213 | CodeGenOpt::Level OL, bool JIT) 214 | : LLVMTargetMachine( 215 | T, computeDataLayout(TT), TT, CPU, FS, Options, 216 | getEffectiveRelocModel(TT, RM), 217 | getEffectiveCodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL), 218 | TLOF(createTLOF(getTargetTriple())) { 219 | // Windows stack unwinder gets confused when execution flow "falls through" 220 | // after a call to 'noreturn' function. 221 | // To prevent that, we emit a trap for 'unreachable' IR instructions. 222 | // (which on X86, happens to be the 'ud2' instruction) 223 | // On PS4, the "return address" of a 'noreturn' call must still be within 224 | // the calling function, and TrapUnreachable is an easy way to get that. 225 | // The check here for 64-bit windows is a bit icky, but as we're unlikely 226 | // to ever want to mix 32 and 64-bit windows code in a single module 227 | // this should be fine. 228 | if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() || 229 | TT.isOSBinFormatMachO()) 230 | this->Options.TrapUnreachable = true; 231 | 232 | initAsmInfo(); 233 | } 234 | 235 | X86TargetMachine::~X86TargetMachine() = default; 236 | 237 | const X86Subtarget * 238 | X86TargetMachine::getSubtargetImpl(const Function &F) const { 239 | Attribute CPUAttr = F.getFnAttribute("target-cpu"); 240 | Attribute FSAttr = F.getFnAttribute("target-features"); 241 | 242 | StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) 243 | ? CPUAttr.getValueAsString() 244 | : (StringRef)TargetCPU; 245 | StringRef FS = !FSAttr.hasAttribute(Attribute::None) 246 | ? FSAttr.getValueAsString() 247 | : (StringRef)TargetFS; 248 | 249 | SmallString<512> Key; 250 | Key.reserve(CPU.size() + FS.size()); 251 | Key += CPU; 252 | Key += FS; 253 | 254 | // FIXME: This is related to the code below to reset the target options, 255 | // we need to know whether or not the soft float flag is set on the 256 | // function before we can generate a subtarget. We also need to use 257 | // it as a key for the subtarget since that can be the only difference 258 | // between two functions. 259 | bool SoftFloat = 260 | F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 261 | // If the soft float attribute is set on the function turn on the soft float 262 | // subtarget feature. 263 | if (SoftFloat) 264 | Key += FS.empty() ? "+soft-float" : ",+soft-float"; 265 | 266 | // Keep track of the key width after all features are added so we can extract 267 | // the feature string out later. 268 | unsigned CPUFSWidth = Key.size(); 269 | 270 | // Extract prefer-vector-width attribute. 271 | unsigned PreferVectorWidthOverride = 0; 272 | if (F.hasFnAttribute("prefer-vector-width")) { 273 | StringRef Val = F.getFnAttribute("prefer-vector-width").getValueAsString(); 274 | unsigned Width; 275 | if (!Val.getAsInteger(0, Width)) { 276 | Key += ",prefer-vector-width="; 277 | Key += Val; 278 | PreferVectorWidthOverride = Width; 279 | } 280 | } 281 | 282 | // Extract required-vector-width attribute. 283 | unsigned RequiredVectorWidth = UINT32_MAX; 284 | if (F.hasFnAttribute("required-vector-width")) { 285 | StringRef Val = F.getFnAttribute("required-vector-width").getValueAsString(); 286 | unsigned Width; 287 | if (!Val.getAsInteger(0, Width)) { 288 | Key += ",required-vector-width="; 289 | Key += Val; 290 | RequiredVectorWidth = Width; 291 | } 292 | } 293 | 294 | // Extracted here so that we make sure there is backing for the StringRef. If 295 | // we assigned earlier, its possible the SmallString reallocated leaving a 296 | // dangling StringRef. 297 | FS = Key.slice(CPU.size(), CPUFSWidth); 298 | 299 | auto &I = SubtargetMap[Key]; 300 | if (!I) { 301 | // This needs to be done before we create a new subtarget since any 302 | // creation will depend on the TM and the code generation flags on the 303 | // function that reside in TargetOptions. 304 | resetTargetOptions(F); 305 | I = llvm::make_unique(TargetTriple, CPU, FS, *this, 306 | Options.StackAlignmentOverride, 307 | PreferVectorWidthOverride, 308 | RequiredVectorWidth); 309 | } 310 | return I.get(); 311 | } 312 | 313 | //===----------------------------------------------------------------------===// 314 | // Command line options for x86 315 | //===----------------------------------------------------------------------===// 316 | static cl::opt 317 | UseVZeroUpper("x86-use-vzeroupper", cl::Hidden, 318 | cl::desc("Minimize AVX to SSE transition penalty"), 319 | cl::init(true)); 320 | 321 | //===----------------------------------------------------------------------===// 322 | // X86 TTI query. 323 | //===----------------------------------------------------------------------===// 324 | 325 | TargetTransformInfo 326 | X86TargetMachine::getTargetTransformInfo(const Function &F) { 327 | return TargetTransformInfo(X86TTIImpl(this, F)); 328 | } 329 | 330 | //===----------------------------------------------------------------------===// 331 | // Pass Pipeline Configuration 332 | //===----------------------------------------------------------------------===// 333 | 334 | namespace { 335 | 336 | /// X86 Code Generator Pass Configuration Options. 337 | class X86PassConfig : public TargetPassConfig { 338 | public: 339 | X86PassConfig(X86TargetMachine &TM, PassManagerBase &PM) 340 | : TargetPassConfig(TM, PM) {} 341 | 342 | X86TargetMachine &getX86TargetMachine() const { 343 | return getTM(); 344 | } 345 | 346 | ScheduleDAGInstrs * 347 | createMachineScheduler(MachineSchedContext *C) const override { 348 | ScheduleDAGMILive *DAG = createGenericSchedLive(C); 349 | DAG->addMutation(createX86MacroFusionDAGMutation()); 350 | return DAG; 351 | } 352 | 353 | void addIRPasses() override; 354 | bool addInstSelector() override; 355 | bool addIRTranslator() override; 356 | bool addLegalizeMachineIR() override; 357 | bool addRegBankSelect() override; 358 | bool addGlobalInstructionSelect() override; 359 | bool addILPOpts() override; 360 | bool addPreISel() override; 361 | void addMachineSSAOptimization() override; 362 | void addPreRegAlloc() override; 363 | void addPostRegAlloc() override; 364 | void addPreEmitPass() override; 365 | void addPreEmitPass2() override; 366 | void addPreSched2() override; 367 | }; 368 | 369 | class X86ExecutionDomainFix : public ExecutionDomainFix { 370 | public: 371 | static char ID; 372 | X86ExecutionDomainFix() : ExecutionDomainFix(ID, X86::VR128XRegClass) {} 373 | StringRef getPassName() const override { 374 | return "X86 Execution Dependency Fix"; 375 | } 376 | }; 377 | char X86ExecutionDomainFix::ID; 378 | 379 | } // end anonymous namespace 380 | 381 | INITIALIZE_PASS_BEGIN(X86ExecutionDomainFix, "x86-execution-domain-fix", 382 | "X86 Execution Domain Fix", false, false) 383 | INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis) 384 | INITIALIZE_PASS_END(X86ExecutionDomainFix, "x86-execution-domain-fix", 385 | "X86 Execution Domain Fix", false, false) 386 | 387 | TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) { 388 | return new X86PassConfig(*this, PM); 389 | } 390 | 391 | void X86PassConfig::addIRPasses() { 392 | addPass(createAtomicExpandPass()); 393 | 394 | TargetPassConfig::addIRPasses(); 395 | 396 | if (TM->getOptLevel() != CodeGenOpt::None) 397 | addPass(createInterleavedAccessPass()); 398 | 399 | // Add passes that handle indirect branch removal and insertion of a retpoline 400 | // thunk. These will be a no-op unless a function subtarget has the retpoline 401 | // feature enabled. 402 | addPass(createIndirectBrExpandPass()); 403 | } 404 | 405 | bool X86PassConfig::addInstSelector() { 406 | // Install an instruction selector. 407 | addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel())); 408 | 409 | // For ELF, cleanup any local-dynamic TLS accesses. 410 | if (TM->getTargetTriple().isOSBinFormatELF() && 411 | getOptLevel() != CodeGenOpt::None) 412 | addPass(createCleanupLocalDynamicTLSPass()); 413 | 414 | addPass(createX86GlobalBaseRegPass()); 415 | return false; 416 | } 417 | 418 | bool X86PassConfig::addIRTranslator() { 419 | addPass(new IRTranslator()); 420 | return false; 421 | } 422 | 423 | bool X86PassConfig::addLegalizeMachineIR() { 424 | addPass(new Legalizer()); 425 | return false; 426 | } 427 | 428 | bool X86PassConfig::addRegBankSelect() { 429 | addPass(new RegBankSelect()); 430 | return false; 431 | } 432 | 433 | bool X86PassConfig::addGlobalInstructionSelect() { 434 | addPass(new InstructionSelect()); 435 | return false; 436 | } 437 | 438 | bool X86PassConfig::addILPOpts() { 439 | addPass(&EarlyIfConverterID); 440 | if (EnableMachineCombinerPass) 441 | addPass(&MachineCombinerID); 442 | addPass(createX86CmovConverterPass()); 443 | return true; 444 | } 445 | 446 | bool X86PassConfig::addPreISel() { 447 | // Only add this pass for 32-bit x86 Windows. 448 | const Triple &TT = TM->getTargetTriple(); 449 | if (TT.isOSWindows() && TT.getArch() == Triple::x86) 450 | addPass(createX86WinEHStatePass()); 451 | return true; 452 | } 453 | 454 | 455 | void X86PassConfig::addPreRegAlloc() { 456 | if (getOptLevel() != CodeGenOpt::None) { 457 | addPass(&LiveRangeShrinkID); 458 | addPass(createX86FixupSetCC()); 459 | addPass(createX86OptimizeLEAs()); 460 | addPass(createX86CallFrameOptimization()); 461 | addPass(createX86AvoidStoreForwardingBlocks()); 462 | } 463 | 464 | addPass(createX86FlagsCopyLoweringPass()); 465 | addPass(createX86WinAllocaExpander()); 466 | #ifdef SHADOW_STACK_MPX 467 | addPass(createX86ShadowStackMPX()); 468 | #endif 469 | } 470 | void X86PassConfig::addMachineSSAOptimization() { 471 | addPass(createX86DomainReassignmentPass()); 472 | TargetPassConfig::addMachineSSAOptimization(); 473 | } 474 | 475 | void X86PassConfig::addPostRegAlloc() { 476 | addPass(createX86FloatingPointStackifierPass()); 477 | } 478 | 479 | void X86PassConfig::addPreSched2() { addPass(createX86ExpandPseudoPass()); } 480 | 481 | 482 | void X86PassConfig::addPreEmitPass() { 483 | if (getOptLevel() != CodeGenOpt::None) { 484 | addPass(new X86ExecutionDomainFix()); 485 | addPass(createBreakFalseDeps()); 486 | } 487 | 488 | addPass(createShadowCallStackPass()); 489 | addPass(createX86IndirectBranchTrackingPass()); 490 | 491 | if (UseVZeroUpper) 492 | addPass(createX86IssueVZeroUpperPass()); 493 | 494 | if (getOptLevel() != CodeGenOpt::None) { 495 | addPass(createX86FixupBWInsts()); 496 | addPass(createX86PadShortFunctions()); 497 | addPass(createX86FixupLEAs()); 498 | addPass(createX86EvexToVexInsts()); 499 | } 500 | #ifdef COUNT_FUNCTION_CALLS 501 | addPass(createX86FunctionCountPass()); 502 | #endif 503 | #ifdef SHADOW_STACK_REG 504 | addPass(createX86ShadowStackReg()); 505 | #endif 506 | 507 | #ifdef SHADOW_STACK_MEM_SCHEME 508 | addPass(createX86ShadowStackMem()); 509 | #endif 510 | 511 | #ifdef SHADOW_STACK_SEG 512 | addPass(createX86ShadowStackSeg()); 513 | #endif 514 | 515 | #ifdef SHADOW_STACK_CON 516 | addPass(createX86ShadowStackCon()); 517 | #endif 518 | } 519 | 520 | void X86PassConfig::addPreEmitPass2() { 521 | addPass(createX86RetpolineThunksPass()); 522 | } 523 | -------------------------------------------------------------------------------- /Compiler-Impl/src/crash_clang.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | 4 | #define GS_RELATIVE __attribute__((address_space(256))) 5 | static char read_gs(char GS_RELATIVE *ptr) 6 | { 7 | return *ptr; 8 | } 9 | 10 | int main(int argc, const char *argv[]) 11 | { 12 | 13 | char *rsp = "Y"; 14 | char byte = read_gs((char GS_RELATIVE *)rsp); 15 | printf("%d\n", byte); 16 | printf("%d\n", *rsp); 17 | printf("Might worked\n"); 18 | } 19 | -------------------------------------------------------------------------------- /Compiler-Impl/src/crt-lib-CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # First, add the subdirectories which contain feature-based runtime libraries 2 | # and several convenience helper libraries. 3 | 4 | include(AddCompilerRT) 5 | include(SanitizerUtils) 6 | 7 | # Hoist the building of sanitizer_common on whether we're building either the 8 | # sanitizers or xray (or both). 9 | # 10 | #TODO: Refactor sanitizer_common into smaller pieces (e.g. flag parsing, utils). 11 | if (COMPILER_RT_HAS_SANITIZER_COMMON AND 12 | (COMPILER_RT_BUILD_SANITIZERS OR COMPILER_RT_BUILD_XRAY)) 13 | add_subdirectory(sanitizer_common) 14 | endif() 15 | 16 | if(COMPILER_RT_BUILD_BUILTINS) 17 | add_subdirectory(builtins) 18 | endif() 19 | 20 | function(compiler_rt_build_runtime runtime) 21 | string(TOUPPER ${runtime} runtime_uppercase) 22 | if(COMPILER_RT_HAS_${runtime_uppercase}) 23 | add_subdirectory(${runtime}) 24 | if(${runtime} STREQUAL tsan) 25 | add_subdirectory(tsan/dd) 26 | endif() 27 | endif() 28 | endfunction() 29 | 30 | if(COMPILER_RT_BUILD_SANITIZERS) 31 | compiler_rt_build_runtime(interception) 32 | 33 | if(COMPILER_RT_HAS_SANITIZER_COMMON) 34 | add_subdirectory(stats) 35 | add_subdirectory(lsan) 36 | add_subdirectory(ubsan) 37 | endif() 38 | 39 | foreach(sanitizer ${COMPILER_RT_SANITIZERS_TO_BUILD}) 40 | compiler_rt_build_runtime(${sanitizer}) 41 | endforeach() 42 | endif() 43 | 44 | if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) 45 | compiler_rt_build_runtime(profile) 46 | endif() 47 | 48 | if(COMPILER_RT_BUILD_XRAY) 49 | compiler_rt_build_runtime(xray) 50 | endif() 51 | 52 | if(COMPILER_RT_BUILD_LIBFUZZER) 53 | compiler_rt_build_runtime(fuzzer) 54 | endif() 55 | 56 | add_subdirectory(shadowstack) 57 | -------------------------------------------------------------------------------- /Compiler-Impl/src/exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void throw_exception() 5 | { 6 | throw "A testing exception..."; 7 | } 8 | 9 | void bar() 10 | { 11 | throw_exception(); 12 | } 13 | 14 | void foo() 15 | { 16 | bar(); 17 | } 18 | 19 | int main(int argc, const char *argv[]) 20 | { 21 | std::cout << "====TEST EXCEPTIONS====" << std::endl; 22 | try{ 23 | foo(); 24 | }catch(const char *msg) 25 | { 26 | std::cout << "OK!" << std::endl; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Compiler-Impl/src/fib.c: -------------------------------------------------------------------------------- 1 | int fib(int n) 2 | { 3 | if(n <= 0)return 0; 4 | if(n <= 2)return 1; 5 | return fib(n-1) + fib(n-2); 6 | } 7 | -------------------------------------------------------------------------------- /Compiler-Impl/src/fib_driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int fib(int); 5 | extern int fib_mpk(int); 6 | 7 | 8 | int main(int argc, const char *argv[]) 9 | { 10 | unsigned long long start = 0, end = 0; 11 | 12 | for(int i = 10; i < 50; i ++) 13 | { 14 | start = __rdtsc(); 15 | fib(i); 16 | end = __rdtsc(); 17 | unsigned long long base = (end - start); 18 | 19 | start = __rdtsc(); 20 | fib_mpk(i); 21 | end = __rdtsc(); 22 | unsigned long long mpk = (end - start); 23 | printf("i = %d, Overhead: %.2f%%\n", i, (((double)mpk/base)-1)*100); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /Compiler-Impl/src/fib_mpk.c: -------------------------------------------------------------------------------- 1 | int fib_mpk(int n) 2 | { 3 | if(n <= 0)return 0; 4 | if(n <= 2)return 1; 5 | return fib_mpk(n-1) + fib_mpk(n-2); 6 | } 7 | -------------------------------------------------------------------------------- /Compiler-Impl/src/longjmp.s: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 2 | #include 3 | 4 | .global __longjmp 5 | .global _longjmp 6 | .global longjmp 7 | .global __libc_siglongjmp 8 | .type __longjmp,@function 9 | .type _longjmp,@function 10 | .type longjmp,@function 11 | .type __libc_siglongjmp,@function 12 | .global __siglongjmp 13 | .global _siglongjmp 14 | .global siglongjmp 15 | .type __siglongjmp,@function 16 | .type _siglongjmp,@function 17 | .type siglongjmp,@function 18 | .intel_syntax noprefix 19 | 20 | __longjmp: 21 | _longjmp: 22 | longjmp: 23 | __libc_siglongjmp: 24 | __siglongjmp: 25 | _siglongjmp: 26 | siglongjmp: 27 | #xor eax, eax 28 | #xor ecx, ecx 29 | #xor edx, edx 30 | #wrpkru 31 | 32 | mov r15, gs:[8] 33 | #mov rax, [rdx] 34 | lea r15, [r15+0x10] 35 | 36 | //get recoreded RSP with RA 37 | mov rcx, [rdi+48] 38 | 2: 39 | cmp qword ptr[r15], 0 40 | je 3f 41 | cmp rcx, [r15+8] 42 | jge 4f 43 | add r15, 16 44 | jmp 2b 45 | 3: 46 | int 3 47 | 4: 48 | #mov gs:[0], r15 49 | mov rax, rsi /* val will be longjmp return */ 50 | test rax,rax 51 | jnz 1f 52 | inc rax /* if val==0, val=1 per longjmp semantics */ 53 | 1: 54 | /* rdi is the jmp_buf, restore regs from it */ 55 | mov rbx, [rdi] 56 | mov rbp, [rdi+8] 57 | mov r12, [rdi+16] 58 | mov r13, [rdi+24] 59 | mov r14, [rdi+32] 60 | mov r15, [rdi+40] 61 | /* this ends up being the stack pointer */ 62 | mov rdx, [rdi+48] 63 | mov rsp, rdx 64 | /* this is the instruction pointer */ 65 | mov rdx, [rdi+56] 66 | /* goto saved address without altering rsp */ 67 | jmp rdx 68 | -------------------------------------------------------------------------------- /Compiler-Impl/src/main.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int global = 0; 9 | extern int getpid(); 10 | extern int printf(const char*, ...); 11 | 12 | int test_branch(int a, int b) 13 | { 14 | global ++; 15 | if(a == b)return 0; 16 | else if(a < b)return -1; 17 | else return 1; 18 | } 19 | 20 | __attribute__((noinline)) 21 | int tail_func(int a, int b, int c, int d) 22 | { 23 | char arr[20]; 24 | arr[0] = 0; 25 | return a + getpid() + b - getpid() + c + d - getpid(); 26 | } 27 | 28 | int test_tail(int a, int b, int c, int d) 29 | { 30 | char arr[20]; 31 | arr[0] = a+b-c+c-b; 32 | a += getpid(); 33 | return tail_func(arr[0], b, c, d); 34 | } 35 | 36 | __attribute__((noinline)) 37 | int sum_tail(int n, int p) 38 | { 39 | if(n <= 0)return p; 40 | return sum_tail(n-1, p+n); 41 | } 42 | 43 | 44 | void test_params(int a, int b, int c, int d) 45 | { 46 | char arr[20]; 47 | arr[0] = 0; 48 | assert(a == 1); 49 | assert(b == 2); 50 | assert(c == 3); 51 | assert(d == 4); 52 | } 53 | 54 | void *small_return() 55 | { 56 | char arr[20]; 57 | arr[0] = 0; 58 | return small_return; 59 | } 60 | 61 | typedef struct{ 62 | void *low; 63 | void *high; 64 | }BIG_STRUCT; 65 | 66 | __int128_t big_return() 67 | { 68 | char arr[20]; 69 | arr[0] = 0; 70 | __int128_t ret = 0xECE; 71 | ret = ret << 64 | 0xE2EE; 72 | return ret; 73 | } 74 | 75 | void test_return() 76 | { 77 | assert(small_return() == small_return); 78 | __int128_t big = big_return(); 79 | assert((big << 64 >> 64) == 0xE2EE); 80 | assert((big>>64) == 0xECE); 81 | } 82 | 83 | void b(jmp_buf env) 84 | { 85 | longjmp(env, 0); 86 | } 87 | 88 | void a(jmp_buf env) 89 | { 90 | b(env); 91 | } 92 | 93 | void test_setjmp() 94 | { 95 | jmp_buf env; 96 | int ret = setjmp(env); 97 | if(ret)return; 98 | a(env); 99 | return; 100 | } 101 | 102 | void test_setjmp_return() 103 | { 104 | jmp_buf env; 105 | setjmp(env); 106 | return; 107 | } 108 | void *test(void *arg) 109 | { 110 | printf("====TEST TAIL CALL====\n"); 111 | sum_tail(10, 20); 112 | test_tail(1, 2, 3, 4); 113 | printf("OK\n"); 114 | 115 | printf("====TEST PARAMS====\n"); 116 | test_params(1, 2, 3, 4); 117 | printf("OK\n"); 118 | 119 | printf("====TEST RETURN====\n"); 120 | test_return(); 121 | printf("OK\n"); 122 | 123 | printf("====TEST SETJMP===\n"); 124 | test_setjmp(); 125 | printf("OK!\n"); 126 | 127 | 128 | printf("====TEST SETJMP NO LONGJMP===\n"); 129 | test_setjmp_return(); 130 | printf("OK!\n"); 131 | return 0; 132 | } 133 | //for testing compilers 134 | int main(int argc, const char *argv[]) 135 | { 136 | if(argc == 2) 137 | { 138 | pthread_t thread; 139 | pthread_create(&thread, NULL, test, (void*)1); 140 | pthread_join(thread, NULL); 141 | return 0; 142 | } 143 | test(NULL); 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /Compiler-Impl/src/mpk.h: -------------------------------------------------------------------------------- 1 | #ifndef __MPK 2 | #define __MPK 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //these constatns are not defined in sys/mman.h, hardcode them 9 | //PKRU[2i] is the access-disable bit for protection key i (ADi); 10 | //PKRU[2i+1] is the write-disable bit 11 | //for protection key i (WDi) 12 | //checked on intel's manual, section 4.6.2, protection keys 13 | #define PKEY_DISABLE_ACCESS 0x1 14 | #define PKEY_DISABLE_WRITE 0x2 15 | 16 | #define errExit(msg) do { perror(msg); exit(errno); \ 17 | } while (0) 18 | 19 | __attribute__((always_inline)) 20 | static inline int 21 | wrpkru(unsigned int pkru) 22 | { 23 | unsigned int eax = pkru; 24 | unsigned int ecx = 0; 25 | unsigned int edx = 0; 26 | 27 | asm volatile(".byte 0x0f,0x01,0xef\n\t" 28 | : : "a" (eax), "c" (ecx), "d" (edx)); 29 | return 0; 30 | } 31 | 32 | __attribute__((always_inline)) 33 | static inline int 34 | pkey_set(int pkey, unsigned long rights, unsigned long flags) 35 | { 36 | unsigned int pkru = (rights << (pkey << 1)); 37 | return wrpkru(pkru); 38 | } 39 | 40 | __attribute__((always_inline)) 41 | static inline int 42 | pkey_mprotect(void *ptr, size_t size, unsigned long orig_prot, 43 | unsigned long pkey) 44 | { 45 | return syscall(SYS_pkey_mprotect, ptr, size, orig_prot, pkey); 46 | } 47 | 48 | __attribute__((always_inline)) 49 | static inline int 50 | pkey_alloc(void) 51 | { 52 | return syscall(SYS_pkey_alloc, 0, 0); 53 | } 54 | 55 | __attribute__((always_inline)) 56 | static inline int 57 | pkey_free(unsigned long pkey) 58 | { 59 | return syscall(SYS_pkey_free, pkey); 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /Compiler-Impl/src/mpk_example.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | #include "mpk.h" 7 | 8 | 9 | int 10 | main(void) 11 | { 12 | int status; 13 | int pkey; 14 | int *buffer; 15 | 16 | /* 17 | *Allocate one page of memory 18 | */ 19 | buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, 20 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 21 | if (buffer == MAP_FAILED) 22 | errExit("mmap"); 23 | printf("Buffer Location: %p\n", buffer); 24 | /* 25 | * Put some random data into the page (still OK to touch) 26 | */ 27 | *buffer = __LINE__; 28 | printf("buffer contains: %d\n", *buffer); 29 | 30 | /* 31 | * Allocate a protection key: 32 | */ 33 | pkey = pkey_alloc(); 34 | if (pkey == -1) 35 | errExit("pkey_alloc"); 36 | 37 | /* 38 | * Disable access to any memory with "pkey" set, 39 | * even though there is none right now 40 | */ 41 | status = pkey_set(pkey, PKEY_DISABLE_ACCESS, 0); 42 | if (status) 43 | errExit("pkey_set"); 44 | 45 | char *ptr = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, 46 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 47 | if(ptr == MAP_FAILED) 48 | perror("mmap()"); 49 | /* 50 | * Set the protection key on "buffer". 51 | * Note that it is still read/write as far as mprotect() is 52 | * concerned and the previous pkey_set() overrides it. 53 | */ 54 | status = pkey_mprotect(buffer, getpagesize(), 55 | PROT_READ | PROT_WRITE, pkey); 56 | if (status == -1) 57 | errExit("pkey_mprotect"); 58 | 59 | status = pkey_mprotect(ptr, getpagesize(), 60 | PROT_READ | PROT_WRITE, pkey); 61 | if (status == -1) 62 | errExit("pkey_mprotect"); 63 | printf("about to read buffer again...\n"); 64 | 65 | /* 66 | * This will crash, because we have disallowed access 67 | */ 68 | printf("buffer contains: %d\n", *buffer); 69 | printf("buffer contains: %d\n", *ptr); 70 | 71 | status = pkey_free(pkey); 72 | if (status == -1) 73 | errExit("pkey_free"); 74 | 75 | exit(EXIT_SUCCESS); 76 | } 77 | -------------------------------------------------------------------------------- /Compiler-Impl/src/no_exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void throw_exception() 5 | { 6 | //throw "A testing exception..."; 7 | } 8 | 9 | void bar() 10 | { 11 | throw_exception(); 12 | } 13 | 14 | void foo() 15 | { 16 | bar(); 17 | } 18 | 19 | int main(int argc, const char *argv[]) 20 | { 21 | std::cout << "====TEST EXCEPTIONS====" << std::endl; 22 | try{ 23 | foo(); 24 | }catch(const char *msg) 25 | { 26 | std::cout << "OK!" << std::endl; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Compiler-Impl/src/pthread_create.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "ShadowStackConstants.h" 3 | #include "ShadowStackFeatures.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "mpk.h" 15 | int arch_prctl(int code, unsigned long addr); 16 | 17 | typedef int (*pthread_create_f)(pthread_t *thread, const pthread_attr_t *attr, 18 | void *(*start_routine) (void *), void *arg); 19 | 20 | typedef struct{ 21 | void*(*start_routine)(void*); 22 | void *arg; 23 | }FunctionCall; 24 | 25 | static pthread_create_f real_pthread_create = NULL; 26 | __attribute__((__noreturn__)) static void (*real_pthread_exit)(void *retval) = NULL; 27 | 28 | void pthread_exit(void *retval) 29 | { 30 | if(real_pthread_exit == NULL)real_pthread_exit = dlsym(RTLD_NEXT, "pthread_exit"); 31 | pthread_attr_t attr; 32 | pthread_getattr_np(pthread_self(), &attr); 33 | void *stack_base; 34 | size_t stack_size; 35 | int status = 0; 36 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 37 | if(status) 38 | errExit("get stack size"); 39 | 40 | //retrieve shadow stack location 41 | asm volatile("movq %gs:8, %rax"); 42 | asm volatile("movq %%rax, %0":"=rim"(stack_base)); 43 | status = munmap(stack_base, stack_size); 44 | if(status == -1) 45 | errExit("munmap shadowstack"); 46 | void *clave; 47 | asm volatile("movq %gs:32, %rax"); 48 | asm volatile("movq %%rax, %0":"=rim"(clave)); 49 | munmap(clave, getpagesize()); 50 | real_pthread_exit(retval); 51 | } 52 | 53 | static void *getpage(void *ptr, size_t page_size) 54 | { 55 | return mmap(ptr, 56 | page_size, 57 | PROT_READ | PROT_WRITE, 58 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 59 | } 60 | 61 | 62 | 63 | static void init_shadow_stack(pthread_t thread) 64 | { 65 | //get the start of stack memory and stack size 66 | pthread_attr_t attr; 67 | pthread_attr_init(&attr); 68 | pthread_getattr_np(thread, &attr); 69 | void *stack_base; 70 | size_t stack_size; 71 | int status = 0; 72 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 73 | if(status) 74 | errExit("get stack size"); 75 | 76 | #ifdef SHADOW_STACK_MEM_SCHEME 77 | void **shadow_base = getpage(SHADOW_STACK_PTR, stack_size); 78 | if(shadow_base != SHADOW_STACK_PTR) 79 | errExit("Failed to mmap() at hardcoded location"); 80 | *shadow_base = (shadow_base+1); 81 | #else 82 | 83 | //allocate the shadowstack at constant offset 84 | void **shadow_base = getpage( 85 | (char*)stack_base+SHADOW_STACK_OFFSET, stack_size); 86 | if((char*)shadow_base != (char*)stack_base+SHADOW_STACK_OFFSET) 87 | errExit("Failed to mmap() at constant offset"); 88 | #endif 89 | if(shadow_base == MAP_FAILED) 90 | errExit("failed to mmap() a shadow stack"); 91 | 92 | #ifdef SHADOW_STACK_MPK 93 | //bind mpk to the shadow stack 94 | status = pkey_mprotect(shadow_base, stack_size, 95 | PROT_READ | PROT_WRITE, PKEY); 96 | if (status == -1) 97 | errExit("pkey_mprotect"); 98 | #endif 99 | } 100 | 101 | #ifdef SHADOW_STACK_REG 102 | static void init_shadow_stack_reg(pthread_t thread) 103 | { 104 | //get the start of stack memory and stack size 105 | pthread_attr_t attr; 106 | pthread_attr_init(&attr); 107 | pthread_getattr_np(thread, &attr); 108 | void *stack_base; 109 | size_t stack_size; 110 | int status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 111 | if(status) 112 | errExit("get stack size"); 113 | void **clave = mmap(NULL, getpagesize(), 114 | PROT_READ | PROT_WRITE, 115 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 116 | if(clave == MAP_FAILED) 117 | errExit("SHADOW_STACK_REG_CLAVE"); 118 | 119 | void *shadowstack = getpage(NULL, stack_size); 120 | #ifdef SHADOW_STACK_MPK 121 | //bind mpk to the shadow stack 122 | status = pkey_mprotect(shadowstack, stack_size, 123 | PROT_READ | PROT_WRITE, PKEY); 124 | if (status == -1) 125 | errExit("pkey_mprotect shadowstack"); 126 | #endif 127 | #ifdef SHADOW_STACK_MPX 128 | mpxrt_prepare(stack_size); 129 | #endif 130 | clave[0] = (void*)((size_t)shadowstack - (size_t)stack_base);//(void*)((size_t)shadowstack + 16); 131 | //location of shadow stack 132 | clave[1] = shadowstack; 133 | //top of shadow stack, if using minimal style 134 | clave[2] = shadowstack; 135 | //function call count, if counting... 136 | clave[3] = 0; 137 | //location of this page 138 | clave[4] = (void*)clave; 139 | arch_prctl(ARCH_SET_GS, (unsigned long)(clave)); 140 | } 141 | #endif 142 | 143 | #ifdef SHADOW_STACK_SEG 144 | static void init_shadow_stack_seg(pthread_t thread) 145 | { 146 | //get the start of stack memory and stack size 147 | pthread_attr_t attr; 148 | pthread_attr_init(&attr); 149 | pthread_getattr_np(thread, &attr); 150 | void *stack_base; 151 | size_t stack_size; 152 | int status = 0; 153 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 154 | if(status) 155 | errExit("get stack size"); 156 | void **page = getmem(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS); 157 | if(page == MAP_FAIED) 158 | page = getpage(NULL, stack_size); 159 | if(page == MAP_FAILED) 160 | errExit("sub thread mmap()"); 161 | page[0] = (void*)(page+2); 162 | page[1] = (void*)page; 163 | 164 | arch_prctl(ARCH_SET_GS, (unsigned long)(page)); 165 | 166 | #ifdef SHADOW_STACK_MPK 167 | //bind mpk to the shadow stack 168 | status = pkey_mprotect(page, stack_size, 169 | PROT_READ | PROT_WRITE, PKEY); 170 | if (status == -1) 171 | errExit("pkey_mprotect"); 172 | #endif 173 | } 174 | #endif 175 | 176 | static void* thread_init(void *ptr) 177 | { 178 | FunctionCall *call = (FunctionCall*)ptr; 179 | #ifdef SHADOW_STACK_REG 180 | init_shadow_stack_reg(pthread_self()); 181 | __asm__ volatile ("movq %gs:8, %r15"); 182 | #endif 183 | #ifdef SHADOW_STACK_MEM_SCHEME 184 | init_shadow_stack(pthread_self()); 185 | #endif 186 | #ifdef SHADOW_STACK_CON 187 | init_shadow_stack(pthread_self()); 188 | #endif 189 | #ifdef SHADOW_STACK_SEG 190 | init_shadow_stack_seg(pthread_self()); 191 | #endif 192 | void *(*start_routine)(void*) = call->start_routine; 193 | void *arg = call->arg; 194 | free(call); 195 | void *ret = start_routine(arg); 196 | 197 | pthread_attr_t attr; 198 | pthread_getattr_np(pthread_self(), &attr); 199 | void *stack_base; 200 | size_t stack_size; 201 | int status = 0; 202 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 203 | if(status) 204 | errExit("get stack size"); 205 | 206 | //retrieve shadow stack location 207 | asm volatile("movq %gs:8, %rax"); 208 | asm volatile("movq %%rax, %0":"=rim"(stack_base)); 209 | status = munmap(stack_base, stack_size); 210 | void *clave; 211 | asm volatile("movq %gs:32, %rax"); 212 | asm volatile("movq %%rax, %0":"=rim"(clave)); 213 | munmap(clave, getpagesize()); 214 | return ret; 215 | } 216 | 217 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 218 | void *(*start_routine) (void *), void *arg) 219 | { 220 | if(real_pthread_create == NULL)real_pthread_create = dlsym(RTLD_NEXT, "pthread_create"); 221 | 222 | FunctionCall *call = (FunctionCall*)malloc(sizeof(FunctionCall)); 223 | call->start_routine = start_routine; 224 | call->arg = arg; 225 | 226 | int err = real_pthread_create(thread, attr, thread_init, (void*)call); 227 | if(err != 0) 228 | { 229 | free(call); 230 | } 231 | return err; 232 | } 233 | 234 | -------------------------------------------------------------------------------- /Compiler-Impl/src/setjmp.s: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 2 | .global __setjmp 3 | .global _setjmp 4 | .global setjmp 5 | .type __setjmp,@function 6 | .type _setjmp,@function 7 | .type setjmp,@function 8 | 9 | .global __sigsetjmp 10 | .global _sigsetjmp 11 | .global sigsetjmp 12 | .type __sigsetjmp,@function 13 | .type _sigsetjmp,@function 14 | .type sigsetjmp,@function 15 | .intel_syntax noprefix 16 | #include 17 | __setjmp: 18 | _setjmp: 19 | setjmp: 20 | __sigsetjmp: 21 | _sigsetjmp: 22 | sigsetjmp: 23 | /* 24 | mov rdx, 0x7fc7fc0ee000 25 | //top of shadow stack 26 | mov rax, [rdx] 27 | //get RA 28 | mov rcx, [rsp] 29 | mov [rax], rcx 30 | mov [rax+8], rsp 31 | add rax, 16 32 | mov [rdx], rax 33 | */ 34 | 35 | /* rdi is jmp_buf, move registers onto it */ 36 | mov [rdi], rbx 37 | mov [rdi+8], rbp 38 | mov [rdi+16], r12 39 | mov [rdi+24], r13 40 | mov [rdi+32], r14 41 | mov [rdi+40], r15 42 | /* this is our rsp WITHOUT current ret addr */ 43 | lea rdx, [rsp+8] 44 | mov [rdi+48], rdx 45 | /* save return addr ptr for new rip */ 46 | mov rdx, [rsp] 47 | mov [rdi+56], rdx 48 | /*Always return 0*/ 49 | xor rax, rax 50 | ret 51 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_target(ShadowStack) 2 | 3 | set(SHADOWSTACK_SOURCES shadow_stack.c mpxrt-utils.c) 4 | 5 | include_directories(..) 6 | find_package (Threads) 7 | 8 | #add_compiler_rt_runtime(clang_rt.ShadowStack 9 | # SHARED 10 | # ARCHS x86_64 11 | # SOURCES ${SHADOWSTACK_SOURCES} 12 | # CFLAGS ${SANITIZER_COMMON_FLAGS} 13 | # PARENT_TARGET memsafety) 14 | 15 | add_compiler_rt_runtime(clang_rt.ShadowStack 16 | STATIC 17 | ARCHS x86_64 18 | SOURCES ${SHADOWSTACK_SOURCES} 19 | CFLAGS ${SANITIZER_COMMON_FLAGS} 20 | LINK_LIBS ${CMAKE_THREAD_LIBS_INIT} 21 | PARENT_TARGET memsafety) 22 | 23 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/config_mpx.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define to 1 if you have the header file. */ 5 | #define HAVE_DLFCN_H 1 6 | 7 | /* Define to 1 if you have the header file. */ 8 | #define HAVE_INTTYPES_H 1 9 | 10 | /* Define to 1 if you have the header file. */ 11 | #define HAVE_MEMORY_H 1 12 | 13 | /* Define to 1 if you have the `secure_getenv' function. */ 14 | #define HAVE_SECURE_GETENV 1 15 | 16 | /* Define to 1 if you have the header file. */ 17 | #define HAVE_STDINT_H 1 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #define HAVE_STDLIB_H 1 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #define HAVE_STRINGS_H 1 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_STRING_H 1 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_SYS_STAT_H 1 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #define HAVE_SYS_TYPES_H 1 33 | 34 | /* Define to 1 if you have the header file. */ 35 | #define HAVE_UNISTD_H 1 36 | 37 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 38 | */ 39 | #define LT_OBJDIR ".libs/" 40 | 41 | /* Define to 1 if your C compiler doesn't accept -c and -o together. */ 42 | /* #undef NO_MINUS_C_MINUS_O */ 43 | 44 | /* Name of package */ 45 | #define PACKAGE "package-unused" 46 | 47 | /* Define to the address where bug reports for this package should be sent. */ 48 | #define PACKAGE_BUGREPORT "libmpx" 49 | 50 | /* Define to the full name of this package. */ 51 | #define PACKAGE_NAME "package-unused" 52 | 53 | /* Define to the full name and version of this package. */ 54 | #define PACKAGE_STRING "package-unused version-unused" 55 | 56 | /* Define to the one symbol short name of this package. */ 57 | #define PACKAGE_TARNAME "package-unused" 58 | 59 | /* Define to the home page for this package. */ 60 | #define PACKAGE_URL "" 61 | 62 | /* Define to the version of this package. */ 63 | #define PACKAGE_VERSION "version-unused" 64 | 65 | /* Define to 1 if you have the ANSI C header files. */ 66 | #define STDC_HEADERS 1 67 | 68 | /* Enable extensions on AIX 3, Interix. */ 69 | #ifndef _ALL_SOURCE 70 | # define _ALL_SOURCE 1 71 | #endif 72 | /* Enable GNU extensions on systems that have them. */ 73 | #ifndef _GNU_SOURCE 74 | # define _GNU_SOURCE 1 75 | #endif 76 | /* Enable threading extensions on Solaris. */ 77 | #ifndef _POSIX_PTHREAD_SEMANTICS 78 | # define _POSIX_PTHREAD_SEMANTICS 1 79 | #endif 80 | /* Enable extensions on HP NonStop. */ 81 | #ifndef _TANDEM_SOURCE 82 | # define _TANDEM_SOURCE 1 83 | #endif 84 | /* Enable general extensions on Solaris. */ 85 | #ifndef __EXTENSIONS__ 86 | # define __EXTENSIONS__ 1 87 | #endif 88 | 89 | 90 | /* Version number of package */ 91 | #define VERSION "version-unused" 92 | 93 | /* Define to 1 if on MINIX. */ 94 | /* #undef _MINIX */ 95 | 96 | /* Define to 2 if the system does not provide POSIX.1 features except with 97 | this defined. */ 98 | /* #undef _POSIX_1_SOURCE */ 99 | 100 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 101 | /* #undef _POSIX_SOURCE */ 102 | 103 | // SCOTT ADDITIONS: 104 | #define bit_MPX (1 << 14) 105 | #define bit_BNDREGS (1 << 3) 106 | #define bit_BNDCSR (1 << 4) 107 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/mpk.h: -------------------------------------------------------------------------------- 1 | #ifndef __MPK 2 | #define __MPK 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //these constatns are not defined in sys/mman.h, hardcode them 11 | //PKRU[2i] is the access-disable bit for protection key i (ADi); 12 | //PKRU[2i+1] is the write-disable bit 13 | //for protection key i (WDi) 14 | //checked on intel's manual, section 4.6.2, protection keys 15 | #define PKEY_DISABLE_ACCESS 0x1 16 | #define PKEY_DISABLE_WRITE 0x2 17 | 18 | #define errExit(msg) do { perror(msg); exit(errno); \ 19 | } while (0) 20 | 21 | __attribute__((always_inline)) 22 | static inline int 23 | wrpkru(unsigned int pkru) 24 | { 25 | unsigned int eax = pkru; 26 | unsigned int ecx = 0; 27 | unsigned int edx = 0; 28 | 29 | asm volatile(".byte 0x0f,0x01,0xef\n\t" 30 | : : "a" (eax), "c" (ecx), "d" (edx)); 31 | return 0; 32 | } 33 | 34 | __attribute__((always_inline)) 35 | static inline int 36 | pkey_set(int pkey, unsigned long rights, unsigned long flags) 37 | { 38 | unsigned int pkru = (rights << (pkey << 1)); 39 | return wrpkru(pkru); 40 | } 41 | 42 | __attribute__((always_inline)) 43 | static inline int 44 | pkey_mprotect(void *ptr, size_t size, unsigned long orig_prot, 45 | unsigned long pkey) 46 | { 47 | return syscall(SYS_pkey_mprotect, ptr, size, orig_prot, pkey); 48 | } 49 | 50 | __attribute__((always_inline)) 51 | static inline int 52 | pkey_alloc(void) 53 | { 54 | return syscall(SYS_pkey_alloc, 0, 0); 55 | } 56 | 57 | __attribute__((always_inline)) 58 | static inline int 59 | pkey_free(unsigned long pkey) 60 | { 61 | return syscall(SYS_pkey_free, pkey); 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/mpxrt-utils.c: -------------------------------------------------------------------------------- 1 | /* mpxrt-utils.c -*-C++-*- 2 | * 3 | ************************************************************************* 4 | * 5 | * @copyright 6 | * Copyright (C) 2014, Intel Corporation 7 | * All rights reserved. 8 | * 9 | * @copyright 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in 18 | * the documentation and/or other materials provided with the 19 | * distribution. 20 | * * Neither the name of Intel Corporation nor the names of its 21 | * contributors may be used to endorse or promote products derived 22 | * from this software without specific prior written permission. 23 | * 24 | * @copyright 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 32 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 35 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | **************************************************************************/ 39 | 40 | //#define __STDC_FORMAT_MACROS 41 | #include "config_mpx.h" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include "mpxrt-utils.h" 51 | 52 | //#ifndef HAVE_SECURE_GETENV 53 | //#define secure_getenv __secure_getenv 54 | //#endif 55 | // musl doesnt have secure_getenv 56 | #define secure_getenv getenv 57 | 58 | #define MPX_RT_OUT "CHKP_RT_OUT_FILE" 59 | #define MPX_RT_ERR "CHKP_RT_ERR_FILE" 60 | #define MPX_RT_VERBOSE "CHKP_RT_VERBOSE" 61 | #define MPX_RT_VERBOSE_DEFAULT VERB_BR 62 | #define MPX_RT_MODE "CHKP_RT_MODE" 63 | #define MPX_RT_MODE_DEFAULT MPX_RT_COUNT 64 | #define MPX_RT_MODE_DEFAULT_STR "count" 65 | #define MPX_RT_HELP "CHKP_RT_HELP" 66 | #define MPX_RT_ADDPID "CHKP_RT_ADDPID" 67 | #define MPX_RT_BNDPRESERVE "CHKP_RT_BNDPRESERVE" 68 | #define MPX_RT_BNDPRESERVE_DEFAULT 1 69 | #define MPX_RT_PRINT_SUMMARY "CHKP_RT_PRINT_SUMMARY" 70 | 71 | #define MAX_FILE_NAME PATH_MAX 72 | 73 | typedef struct env_var_s { 74 | char *env_name; 75 | char *env_val; 76 | struct env_var_s *next; 77 | } env_var_t; 78 | 79 | typedef struct { 80 | env_var_t *first; 81 | env_var_t *last; 82 | } env_var_list_t; 83 | 84 | /* Following vars are initialized at process startup only 85 | and thus are considered to be thread safe. */ 86 | static int summary; 87 | static int add_pid; 88 | static mpx_rt_mode_t mode; 89 | static env_var_list_t env_var_list; 90 | static verbose_type verbose_val; 91 | static FILE *out; 92 | static FILE *err; 93 | static char out_name[MAX_FILE_NAME]; 94 | static char err_name[MAX_FILE_NAME]; 95 | 96 | /* Following vars are read at process finalization only. 97 | All write accesses use the same value and thus are 98 | considered to be thread safe. */ 99 | static int out_file_dirty; 100 | static int err_file_dirty; 101 | static int files_overwritten; 102 | 103 | /* Mutex used to sync output. */ 104 | static pthread_mutex_t lock; 105 | 106 | static void * 107 | malloc_check (size_t size) 108 | { 109 | void *res = malloc (size); 110 | if (!res) 111 | __mpxrt_print (VERB_ERROR, "Couldn't allocate %zu bytes.", size); 112 | else 113 | memset (res, 0, size); 114 | return res; 115 | } 116 | 117 | static void 118 | env_var_list_add (const char* env, const char* val) 119 | { 120 | env_var_t* n; 121 | 122 | if (val == 0) 123 | return; 124 | 125 | n = (env_var_t *)malloc_check (sizeof (env_var_t)); 126 | if (!n) 127 | return; 128 | 129 | if (env_var_list.first == 0) 130 | env_var_list.first = n; 131 | 132 | if (env_var_list.last) 133 | env_var_list.last->next = n; 134 | 135 | env_var_list.last = n; 136 | 137 | n->env_name = (char *)malloc_check (strlen (env) + 1); 138 | n->env_val = (char *)malloc_check (strlen (val) + 1); 139 | 140 | if (!n->env_name || !n->env_val) 141 | return; 142 | 143 | strcpy (n->env_name, env); 144 | strcpy (n->env_val, val); 145 | } 146 | 147 | static void 148 | set_file_stream (FILE** file, char* file_name, 149 | const char* env, FILE* deflt) 150 | { 151 | /* 152 | int pid; 153 | if (env != 0) 154 | { 155 | if (add_pid) 156 | { 157 | pid = getpid (); 158 | snprintf (file_name, MAX_FILE_NAME, "%s.%d", env, pid); 159 | } 160 | else 161 | snprintf (file_name, MAX_FILE_NAME, "%s", env); 162 | 163 | *file = fopen (file_name, "we"); 164 | if (*file != 0) 165 | return; 166 | } 167 | *file = deflt; 168 | */ 169 | } 170 | 171 | /* 172 | * this function will be called after fork in the child 173 | * open new files with pid of the process 174 | */ 175 | static void 176 | open_child_files () 177 | { 178 | /* 179 | char *out_env; 180 | char *err_env; 181 | 182 | out_env = secure_getenv (MPX_RT_OUT); 183 | err_env = secure_getenv (MPX_RT_ERR); 184 | 185 | if (add_pid == 0 && (out_env != 0 || err_env != 0)) 186 | { 187 | __mpxrt_print (VERB_ERROR, "MPX RUNTIME WARNING: out/err files are " 188 | "overwritten in new processes since %s was not set.\n", 189 | MPX_RT_ADDPID); 190 | files_overwritten = 1; 191 | } 192 | 193 | set_file_stream (&out, out_name, out_env, stdout); 194 | if (out_env == 0 || err_env == 0 || (strcmp (out_env, err_env) != 0)) 195 | set_file_stream (&err, err_name, err_env, stderr); 196 | else 197 | // in case we get the same file name for err and out 198 | err = out; 199 | */ 200 | } 201 | 202 | /* 203 | * this function is called after fork in the parent 204 | */ 205 | static void 206 | at_fork_check (void) 207 | { 208 | char *out_env; 209 | char *err_env; 210 | 211 | out_env = secure_getenv (MPX_RT_OUT); 212 | err_env = secure_getenv (MPX_RT_ERR); 213 | 214 | if (add_pid == 0 && (out_env != 0 || err_env != 0)) 215 | files_overwritten = 1; 216 | } 217 | 218 | static mpx_rt_mode_t 219 | set_mpx_rt_mode (const char *env) 220 | { 221 | return MPX_RT_STOP; 222 | //if (env == 0) 223 | // return MPX_RT_MODE_DEFAULT; 224 | //else if (strcmp (env, "stop") == 0) 225 | // return MPX_RT_STOP; 226 | //else if (strcmp (env,"count") == 0) 227 | // return MPX_RT_COUNT; 228 | //{ 229 | // __mpxrt_print (VERB_ERROR, "Illegal value '%s' for %s. Legal values are" 230 | // "[stop | count]\nUsing default value %s\n", 231 | // env, MPX_RT_MODE, MPX_RT_MODE_DEFAULT_STR); 232 | // return MPX_RT_MODE_DEFAULT; 233 | //} 234 | } 235 | 236 | static void 237 | print_help (void) 238 | { 239 | /* 240 | fprintf (out, "MPX Runtime environment variables help.\n"); 241 | 242 | fprintf (out, "%s \t set output file for info & debug [default: stdout]\n", 243 | MPX_RT_OUT); 244 | fprintf (out, "%s \t set output file for error [default: stderr]\n", 245 | MPX_RT_ERR); 246 | fprintf (out, "%s \t set verbosity type [default: %d]\n" 247 | "\t\t\t 0 - print only internal run time errors\n" 248 | "\t\t\t 1 - just print summary\n" 249 | "\t\t\t 2 - print summary and bound violation information\n " 250 | "\t\t\t 3 - print debug information\n", 251 | MPX_RT_VERBOSE, MPX_RT_VERBOSE_DEFAULT); 252 | fprintf (out, "%s \t\t set MPX runtime behavior on #BR exception." 253 | " [stop | count]\n" 254 | "\t\t\t [default: %s]\n", MPX_RT_MODE, MPX_RT_MODE_DEFAULT_STR); 255 | fprintf (out, "%s \t\t generate out,err file for each process.\n" 256 | "\t\t\t generated file will be MPX_RT_{OUT,ERR}_FILE.pid\n" 257 | "\t\t\t [default: no]\n", MPX_RT_ADDPID); 258 | fprintf (out, "%s \t set value for BNDPRESERVE bit.\n" 259 | "\t\t\t BNDPRESERVE = 0 flush bounds on unprefixed call/ret/jmp\n" 260 | "\t\t\t BNDPRESERVE = 1 do NOT flush bounds\n" 261 | "\t\t\t [default: %d]\n", MPX_RT_BNDPRESERVE, 262 | MPX_RT_BNDPRESERVE_DEFAULT); 263 | fprintf (out, "%s \t print summary at the end of the run\n" 264 | "\t\t\t [default: no]\n", MPX_RT_PRINT_SUMMARY); 265 | 266 | fprintf (out, "%s \t\t print this help and exit.\n" 267 | "\t\t\t [default: no]\n", MPX_RT_HELP); 268 | 269 | exit (0); 270 | */ 271 | } 272 | 273 | static void 274 | validate_bndpreserve (const char *env, int *bndpreserve) 275 | { 276 | // SCOTT HACK 277 | *bndpreserve = 1; 278 | 279 | //if (env == 0) 280 | // bndpreserve = MPX_RT_BNDPRESERVE_DEFAULT; 281 | //else if (strcmp (env, "0") == 0) 282 | // *bndpreserve = 0; 283 | //else if (strcmp (env, "1") == 0) 284 | // *bndpreserve = 1; 285 | //else 286 | // { 287 | // __mpxrt_print (VERB_ERROR, "Illegal value '%s' for %s. Legal values " 288 | // "are [0 | 1]\nUsing default value %d\n", 289 | // env, MPX_RT_BNDPRESERVE, MPX_RT_BNDPRESERVE_DEFAULT); 290 | // *bndpreserve = MPX_RT_BNDPRESERVE_DEFAULT; 291 | // } 292 | } 293 | 294 | static verbose_type 295 | init_verbose_val (const char *env) 296 | { 297 | /* 298 | if (env == 0) 299 | return MPX_RT_VERBOSE_DEFAULT; 300 | else if (strcmp(env, "0") == 0) 301 | return VERB_ERROR; 302 | else if (strcmp(env, "1") == 0) 303 | return VERB_INFO; 304 | else if (strcmp(env, "2") == 0) 305 | return VERB_BR; 306 | else if (strcmp(env, "3") == 0) 307 | return VERB_DEBUG; 308 | 309 | __mpxrt_print (VERB_ERROR, "Illegal value '%s' for %s. Legal values " 310 | "are [0..3]\nUsing default value %d\n", 311 | env, MPX_RT_VERBOSE, (int)MPX_RT_VERBOSE_DEFAULT); 312 | */ 313 | return MPX_RT_VERBOSE_DEFAULT; 314 | } 315 | 316 | static void 317 | env_var_print_summary (void) 318 | { 319 | env_var_t* node; 320 | 321 | __mpxrt_print (VERB_DEBUG, "Used environment variables:\n"); 322 | 323 | node = env_var_list.first; 324 | while (node != 0) 325 | { 326 | __mpxrt_print (VERB_DEBUG, " %s = %s\n", node->env_name, node->env_val); 327 | node = node->next; 328 | } 329 | } 330 | 331 | /* Return 1 if passes env var value should enable feature. */ 332 | 333 | static int 334 | check_yes (const char *val) 335 | { 336 | return val && (!strcmp (val, "yes") || !strcmp (val, "1")); 337 | } 338 | 339 | void 340 | __mpxrt_init_env_vars (int* bndpreserve) 341 | { 342 | /* 343 | char *out_env; 344 | char *err_env; 345 | char *env; 346 | 347 | //pthread_mutex_init (&lock, NULL); 348 | 349 | out_env = secure_getenv (MPX_RT_OUT); 350 | env_var_list_add (MPX_RT_OUT, out_env); 351 | 352 | err_env = secure_getenv (MPX_RT_ERR); 353 | env_var_list_add (MPX_RT_ERR, err_env); 354 | 355 | env = secure_getenv (MPX_RT_ADDPID); 356 | env_var_list_add (MPX_RT_ADDPID, env); 357 | add_pid = check_yes (env); 358 | 359 | //set_file_stream (&out, out_name, out_env, stdout); 360 | //if (out_env == 0 || err_env == 0 || (strcmp (out_env, err_env) != 0)) 361 | //set_file_stream (&err, err_name, err_env, stderr); 362 | //else 363 | // in case we get the same file name for err and out 364 | //err = out; 365 | 366 | env = secure_getenv (MPX_RT_VERBOSE); 367 | env_var_list_add (MPX_RT_VERBOSE, env); 368 | verbose_val = init_verbose_val (env); 369 | 370 | env = secure_getenv (MPX_RT_MODE); 371 | env_var_list_add (MPX_RT_MODE, env); 372 | mode = set_mpx_rt_mode (env); 373 | 374 | env = secure_getenv (MPX_RT_BNDPRESERVE); 375 | env_var_list_add (MPX_RT_BNDPRESERVE, env); 376 | validate_bndpreserve (env, bndpreserve); 377 | 378 | env = secure_getenv (MPX_RT_PRINT_SUMMARY); 379 | env_var_list_add (MPX_RT_PRINT_SUMMARY, env); 380 | summary = check_yes (env); 381 | 382 | env = secure_getenv (MPX_RT_HELP); 383 | if (check_yes (env)) 384 | print_help (); 385 | 386 | 387 | * at fork - create new files for output and err according 388 | * to the env vars. 389 | */ 390 | //Kelvin, ok get ride of pthread dependecy for now. 391 | //pthread_atfork (NULL, at_fork_check, open_child_files); 392 | 393 | //env_var_print_summary (); 394 | } 395 | 396 | void 397 | __mpxrt_utils_free (void) 398 | { 399 | /* 400 | if (files_overwritten) 401 | __mpxrt_print (VERB_INFO, "\nMPX RUNTIME WARNING: out/err files are" 402 | " overwritten in new processes since %s was not set.\n", 403 | MPX_RT_ADDPID); 404 | 405 | if (out && out != stdout) 406 | { 407 | fclose (out); 408 | if (out_file_dirty != 1) 409 | remove (out_name); 410 | } 411 | 412 | if (err && err != stderr) 413 | { 414 | fclose (err); 415 | if (err_file_dirty != 1) 416 | remove (err_name); 417 | } 418 | 419 | //pthread_mutex_destroy (&lock); 420 | */ 421 | } 422 | 423 | void 424 | __mpxrt_write_uint (verbose_type vt, uint64_t val, unsigned base) 425 | { 426 | /* 427 | static const char digits[] = { 428 | '0', '1', '2', '3', '4', '5', '6', '7', 429 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 430 | char str[65]; 431 | int pos = 64;; 432 | 433 | str[pos--] = 0; 434 | 435 | if (vt > verbose_val || base <= 1 || base > sizeof (digits)) 436 | return; 437 | 438 | if (val < base) 439 | str[pos--] = digits[val]; 440 | else 441 | while (val) 442 | { 443 | str[pos--] = digits[val % base]; 444 | val = val / base; 445 | } 446 | 447 | __mpxrt_write (vt, str + pos + 1); 448 | */ 449 | } 450 | 451 | void 452 | __mpxrt_write (verbose_type vt, const char* str) 453 | { 454 | /* 455 | va_list argp; 456 | FILE *print_to; 457 | 458 | if (vt > verbose_val) 459 | return; 460 | 461 | if (vt == VERB_ERROR) 462 | { 463 | print_to = err; 464 | err_file_dirty = 1; 465 | } 466 | else 467 | { 468 | print_to = out; 469 | out_file_dirty = 1; 470 | } 471 | //pthread_mutex_lock (&lock); 472 | write (fileno (print_to), str, strlen (str)); 473 | //pthread_mutex_unlock (&lock); 474 | va_end (argp); 475 | */ 476 | } 477 | 478 | void 479 | __mpxrt_print (verbose_type vt, const char* frmt, ...) 480 | { 481 | /* 482 | va_list argp; 483 | FILE *print_to; 484 | 485 | if (vt > verbose_val) 486 | return; 487 | 488 | va_start (argp, frmt); 489 | if (vt == VERB_ERROR) 490 | { 491 | print_to = err; 492 | err_file_dirty = 1; 493 | } 494 | else 495 | { 496 | print_to = out; 497 | out_file_dirty = 1; 498 | } 499 | //pthread_mutex_lock (&lock); 500 | vfprintf (print_to, frmt, argp); 501 | fflush (print_to); 502 | //pthread_mutex_unlock (&lock); 503 | va_end (argp); 504 | */ 505 | } 506 | 507 | mpx_rt_mode_t 508 | __mpxrt_mode (void) 509 | { 510 | return mode; 511 | } 512 | 513 | void 514 | __mpxrt_print_summary (uint64_t num_brs, uint64_t l1_size) 515 | { 516 | /* 517 | if (summary == 0) 518 | return; 519 | 520 | out_file_dirty = 1; 521 | 522 | //pthread_mutex_lock (&lock); 523 | fprintf (out, "MPX runtime summary:\n"); 524 | fprintf (out, " Number of bounds violations: %" PRIu64 ".\n", num_brs); 525 | fprintf (out, " Size of allocated L1: %" PRIu64 "B\n", l1_size); 526 | fflush (out); 527 | //pthread_mutex_unlock (&lock); 528 | */ 529 | } 530 | 531 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/mpxrt-utils.h: -------------------------------------------------------------------------------- 1 | /* mpxrt-utils.h -*-C++-*- 2 | * 3 | ************************************************************************* 4 | * 5 | * @copyright 6 | * Copyright (C) 2014, Intel Corporation 7 | * All rights reserved. 8 | * 9 | * @copyright 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in 18 | * the documentation and/or other materials provided with the 19 | * distribution. 20 | * * Neither the name of Intel Corporation nor the names of its 21 | * contributors may be used to endorse or promote products derived 22 | * from this software without specific prior written permission. 23 | * 24 | * @copyright 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 32 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 35 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | **************************************************************************/ 39 | 40 | #ifndef MPXRT_UTILS_H 41 | #define MPXRT_UTILS_H 42 | 43 | #include 44 | 45 | typedef enum { 46 | VERB_ERROR, 47 | VERB_INFO, 48 | VERB_BR, 49 | VERB_DEBUG 50 | } verbose_type; 51 | 52 | typedef enum { 53 | MPX_RT_COUNT, 54 | MPX_RT_STOP 55 | } mpx_rt_mode_t; 56 | 57 | void __mpxrt_init_env_vars (int* bndpreserve); 58 | void __mpxrt_write_uint (verbose_type vt, uint64_t val, unsigned base); 59 | void __mpxrt_write (verbose_type vt, const char* str); 60 | void __mpxrt_print (verbose_type vt, const char* frmt, ...); 61 | mpx_rt_mode_t __mpxrt_mode (void); 62 | void __mpxrt_utils_free (void); 63 | void __mpxrt_print_summary (uint64_t num_brs, uint64_t l1_size); 64 | 65 | #endif /* MPXRT_UTILS_H */ 66 | 67 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/mpxrt.h: -------------------------------------------------------------------------------- 1 | /* mpxrt.h -*-C++-*- 2 | * 3 | ************************************************************************* 4 | * 5 | * @copyright 6 | * Copyright (C) 2015, Intel Corporation 7 | * All rights reserved. 8 | * 9 | * @copyright 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in 18 | * the documentation and/or other materials provided with the 19 | * distribution. 20 | * * Neither the name of Intel Corporation nor the names of its 21 | * contributors may be used to endorse or promote products derived 22 | * from this software without specific prior written permission. 23 | * 24 | * @copyright 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 32 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 35 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | **************************************************************************/ 39 | #ifdef __i386__ 40 | 41 | /* i386 directory size is 4MB. */ 42 | #define NUM_L1_BITS 20 43 | #define NUM_L2_BITS 10 44 | #define NUM_IGN_BITS 2 45 | #define MPX_L1_ADDR_MASK 0xfffff000UL 46 | #define MPX_L2_ADDR_MASK 0xfffffffcUL 47 | #define MPX_L2_VALID_MASK 0x00000001UL 48 | 49 | #define REG_IP_IDX REG_EIP 50 | #define REX_PREFIX 51 | 52 | #define XSAVE_OFFSET_IN_FPMEM sizeof (struct _libc_fpstate) 53 | 54 | #else /* __i386__ */ 55 | 56 | /* x86_64 directory size is 2GB. */ 57 | #define NUM_L1_BITS 28 58 | #define NUM_L2_BITS 17 59 | #define NUM_IGN_BITS 3 60 | #define MPX_L1_ADDR_MASK 0xfffffffffffff000ULL 61 | #define MPX_L2_ADDR_MASK 0xfffffffffffffff8ULL 62 | #define MPX_L2_VALID_MASK 0x0000000000000001ULL 63 | 64 | #define REG_IP_IDX REG_RIP 65 | #define REX_PREFIX "0x48, " 66 | 67 | #define XSAVE_OFFSET_IN_FPMEM 0 68 | 69 | #endif /* !__i386__ */ 70 | 71 | #define MPX_L1_SIZE ((1UL << NUM_L1_BITS) * sizeof (void *)) 72 | 73 | /* Get address of bounds directory. */ 74 | void * 75 | get_bd (); 76 | 77 | -------------------------------------------------------------------------------- /Compiler-Impl/src/shadowstack/shadow_stack.c: -------------------------------------------------------------------------------- 1 | /* mpxrt.c -*-C++-*- 2 | * 3 | ************************************************************************* 4 | * 5 | * @copyright 6 | * Copyright (C) 2014, Intel Corporation 7 | * All rights reserved. 8 | * 9 | * @copyright 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in 18 | * the documentation and/or other materials provided with the 19 | * distribution. 20 | * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived 21 | * from this software without specific prior written permission. 22 | * 23 | * @copyright 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 31 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 34 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | **************************************************************************/ 38 | 39 | //#define __STDC_FORMAT_MACROS 40 | #include <../ShadowStackConstants.h> 41 | #include <../ShadowStackFeatures.h> 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | static int executed = 0; 53 | 54 | 55 | 56 | #ifdef SHADOW_STACK_MPX 57 | #include "config_mpx.h" 58 | //#include 59 | #include "mpxrt-utils.h" 60 | #include "mpxrt.h" 61 | 62 | #define MPX_ENABLE_BIT_NO 0 63 | #define BNDPRESERVE_BIT_NO 1 64 | 65 | struct xsave_hdr_struct 66 | { 67 | uint64_t xstate_bv; 68 | uint64_t reserved1[2]; 69 | uint64_t reserved2[5]; 70 | } __attribute__ ((packed)); 71 | 72 | struct bndregs_struct 73 | { 74 | uint64_t bndregs[8]; 75 | } __attribute__ ((packed)); 76 | 77 | struct bndcsr_struct { 78 | uint64_t cfg_reg_u; 79 | uint64_t status_reg; 80 | } __attribute__((packed)); 81 | 82 | struct xsave_struct 83 | { 84 | uint8_t fpu_sse[512]; 85 | struct xsave_hdr_struct xsave_hdr; 86 | uint8_t ymm[256]; 87 | uint8_t lwp[128]; 88 | struct bndregs_struct bndregs; 89 | struct bndcsr_struct bndcsr; 90 | } __attribute__ ((packed)); 91 | 92 | /* Following vars are initialized at process startup only 93 | and thus are considered to be thread safe. */ 94 | static void *l1base = NULL; 95 | static int bndpreserve; 96 | static int enable = 1; 97 | 98 | /* Var holding number of occured BRs. It is modified from 99 | signal handler only and thus it should be thread safe. */ 100 | static uint64_t num_bnd_chk = 0; 101 | 102 | static inline void 103 | xrstor_state (struct xsave_struct *fx, uint64_t mask) 104 | { 105 | uint32_t lmask = mask; 106 | uint32_t hmask = mask >> 32; 107 | 108 | asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" 109 | : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 110 | : "memory"); 111 | } 112 | 113 | //static inline void 114 | //xsave_state (struct xsave_struct *fx, uint64_t mask) 115 | //{ 116 | // uint32_t lmask = mask; 117 | // uint32_t hmask = mask >> 32; 118 | // 119 | // asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x27\n\t" 120 | // : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 121 | // : "memory"); 122 | //} 123 | 124 | //static inline uint64_t 125 | //xgetbv (uint32_t index) 126 | //{ 127 | // uint32_t eax, edx; 128 | // 129 | // asm volatile (".byte 0x0f,0x01,0xd0" /* xgetbv */ 130 | // : "=a" (eax), "=d" (edx) 131 | // : "c" (index)); 132 | // return eax + ((uint64_t)edx << 32); 133 | //} 134 | 135 | static uint64_t 136 | read_mpx_status_sig (ucontext_t *uctxt) 137 | { 138 | uint8_t *regs = (uint8_t *)uctxt->uc_mcontext.fpregs + XSAVE_OFFSET_IN_FPMEM; 139 | struct xsave_struct *xsave_buf = (struct xsave_struct *)regs; 140 | return xsave_buf->bndcsr.status_reg; 141 | } 142 | 143 | static uint8_t * 144 | get_next_inst_ip (uint8_t *addr) 145 | { 146 | uint8_t *ip = addr; 147 | uint8_t sib; 148 | 149 | /* Determine the prefix. */ 150 | switch (*ip) 151 | { 152 | case 0xf2: 153 | case 0xf3: 154 | case 0x66: 155 | ip++; 156 | break; 157 | } 158 | 159 | /* Look for rex prefix. */ 160 | if ((*ip & 0x40) == 0x40) 161 | ip++; 162 | 163 | /* Make sure we have a MPX instruction. */ 164 | if (*ip++ != 0x0f) 165 | return addr; 166 | 167 | /* Skip the op code byte. */ 168 | ip++; 169 | 170 | /* Get the moderm byte. */ 171 | uint8_t modrm = *ip++; 172 | 173 | /* Break it down into parts. */ 174 | uint8_t rm = modrm & 7; 175 | uint8_t mod = (modrm >> 6); 176 | 177 | /* Init the parts of the address mode. */ 178 | uint8_t base = 8; 179 | 180 | /* Is it a mem mode? */ 181 | if (mod != 3) 182 | { 183 | /* Look for scaled indexed addressing. */ 184 | if (rm == 4) 185 | { 186 | /* SIB addressing. */ 187 | sib = *ip++; 188 | base = sib & 7; 189 | switch (mod) 190 | { 191 | case 0: 192 | if (base == 5) 193 | ip += 4; 194 | break; 195 | 196 | case 1: 197 | ip++; 198 | break; 199 | 200 | case 2: 201 | ip += 4; 202 | break; 203 | } 204 | } 205 | else 206 | { 207 | /* MODRM addressing. */ 208 | switch (mod) 209 | { 210 | case 0: 211 | if (rm == 5) 212 | /* DISP32 addressing, no base. */ 213 | ip += 4; 214 | break; 215 | 216 | case 1: 217 | ip++; 218 | break; 219 | 220 | case 2: 221 | ip += 4; 222 | break; 223 | } 224 | } 225 | } 226 | return ip; 227 | } 228 | 229 | static void 230 | handler (int sig __attribute__ ((unused)), 231 | siginfo_t *info __attribute__ ((unused)), 232 | void *vucontext, 233 | struct xsave_struct *buf __attribute__ ((unused))) 234 | { 235 | ucontext_t* uctxt; 236 | greg_t trapno; 237 | greg_t ip; 238 | 239 | uctxt = vucontext; 240 | trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO]; 241 | ip = uctxt->uc_mcontext.gregs[REG_IP_IDX]; 242 | 243 | if (trapno == 5) 244 | { 245 | uint64_t status = read_mpx_status_sig (uctxt); 246 | uint64_t br_reason = status & 0x3; 247 | 248 | __mpxrt_write (VERB_BR, "Saw a #BR! status "); 249 | __mpxrt_write_uint (VERB_BR, status, 10); 250 | __mpxrt_write (VERB_BR, " at 0x"); 251 | __mpxrt_write_uint (VERB_BR, ip, 16); 252 | __mpxrt_write (VERB_BR, "\n"); 253 | 254 | switch (br_reason) 255 | { 256 | case 1: /* traditional BR */ 257 | num_bnd_chk++; 258 | uctxt->uc_mcontext.gregs[REG_IP_IDX] = 259 | (greg_t)get_next_inst_ip ((uint8_t *)ip); 260 | if (__mpxrt_mode () == MPX_RT_STOP) 261 | exit (255); 262 | return; 263 | 264 | default: 265 | __mpxrt_write (VERB_BR, "Unexpected status with bound exception: "); 266 | __mpxrt_write_uint (VERB_BR, status, 10); 267 | __mpxrt_write (VERB_BR, "\n"); 268 | break; 269 | } 270 | } 271 | else if (trapno == 14) 272 | { 273 | __mpxrt_write (VERB_ERROR, "In signal handler, trapno = "); 274 | __mpxrt_write_uint (VERB_ERROR, trapno, 10); 275 | __mpxrt_write (VERB_ERROR, ", ip = 0x"); 276 | __mpxrt_write_uint (VERB_ERROR, ip, 16); 277 | __mpxrt_write (VERB_ERROR, "\n"); 278 | exit (255); 279 | } 280 | else 281 | { 282 | __mpxrt_write (VERB_ERROR, "Unexpected trap "); 283 | __mpxrt_write_uint (VERB_ERROR, trapno, 10); 284 | __mpxrt_write (VERB_ERROR, "! at 0x"); 285 | __mpxrt_write_uint (VERB_ERROR, ip, 16); 286 | __mpxrt_write (VERB_ERROR, "\n"); 287 | exit (255); 288 | } 289 | } 290 | 291 | /* Using wrapper to the real handler in order to save the bnd regs 292 | using xsave before any unprefixed call. an unprefixed call to 293 | __i686.get_pc_thunk.bx is added by the linker in 32bit at the 294 | beginning of handler function since there are references to 295 | global variables. */ 296 | static void 297 | handler_wrap (int signum, siginfo_t* si, void* vucontext) 298 | { 299 | /* Since the OS currently not handling chkptr regs. 300 | We need to store them for later use. They might be 301 | init due to unprefixed call,Jcc,ret. avoiding calling 302 | function since the function will be unprefixed as well. */ 303 | uint8_t __attribute__ ((__aligned__ (64))) buffer[4096]; 304 | struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer; 305 | uint64_t mask = 0x18; 306 | uint32_t lmask = mask; 307 | uint32_t hmask = mask >> 32; 308 | 309 | asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x27\n\t" 310 | : : "D" (xsave_buf), "m" (*xsave_buf), 311 | "a" (lmask), "d" (hmask) 312 | : "memory"); 313 | 314 | handler (signum, si, vucontext, xsave_buf); 315 | } 316 | 317 | //static bool 318 | //check_mpx_support (void) 319 | //{ 320 | // unsigned int eax, ebx, ecx, edx; 321 | // unsigned int max_level = __get_cpuid_max (0, NULL); 322 | // 323 | // if (max_level < 13) 324 | // { 325 | // __mpxrt_print (VERB_DEBUG, "No required CPUID level support.\n"); 326 | // return false; 327 | // } 328 | // 329 | // __cpuid_count (0, 0, eax, ebx, ecx, edx); 330 | // if (!(ecx & bit_XSAVE)) 331 | // { 332 | // __mpxrt_print (VERB_DEBUG, "No XSAVE support.\n"); 333 | // return false; 334 | // } 335 | // 336 | // if (!(ecx & bit_OSXSAVE)) 337 | // { 338 | // __mpxrt_print (VERB_DEBUG, "No OSXSAVE support.\n"); 339 | // return false; 340 | // } 341 | // 342 | // __cpuid_count (7, 0, eax, ebx, ecx, edx); 343 | // if (!(ebx & bit_MPX)) 344 | // { 345 | // __mpxrt_print (VERB_DEBUG, "No MPX support.\n"); 346 | // return false; 347 | // } 348 | // 349 | // __cpuid_count (13, 0, eax, ebx, ecx, edx); 350 | // if (!(eax & bit_BNDREGS)) 351 | // { 352 | // __mpxrt_print (VERB_DEBUG, "No BNDREGS support.\n"); 353 | // return false; 354 | // } 355 | // 356 | // if (!(eax & bit_BNDCSR)) 357 | // { 358 | // __mpxrt_print (VERB_DEBUG, "No BNDCSR support.\n"); 359 | // return false; 360 | // } 361 | // 362 | // return true; 363 | //} 364 | 365 | static void 366 | enable_mpx (void) 367 | { 368 | uint8_t __attribute__ ((__aligned__ (64))) buffer[4096]; 369 | struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer; 370 | 371 | memset (buffer, 0, sizeof (buffer)); 372 | xrstor_state (xsave_buf, 0x18); 373 | 374 | __mpxrt_print (VERB_DEBUG, "Initalizing MPX...\n"); 375 | __mpxrt_print (VERB_DEBUG, " Enable bit: %d\n", enable); 376 | __mpxrt_print (VERB_DEBUG, " BNDPRESERVE bit: %d\n", bndpreserve); 377 | 378 | /* Enable MPX. */ 379 | xsave_buf->xsave_hdr.xstate_bv = 0x10; 380 | xsave_buf->bndcsr.cfg_reg_u = (unsigned long)l1base; 381 | xsave_buf->bndcsr.cfg_reg_u |= enable << MPX_ENABLE_BIT_NO; 382 | xsave_buf->bndcsr.cfg_reg_u |= bndpreserve << BNDPRESERVE_BIT_NO; 383 | xsave_buf->bndcsr.status_reg = 0; 384 | 385 | xrstor_state (xsave_buf, 0x10); 386 | } 387 | 388 | static void 389 | disable_mpx (void) 390 | { 391 | uint8_t __attribute__ ((__aligned__ (64))) buffer[4096]; 392 | struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer; 393 | 394 | memset(buffer, 0, sizeof(buffer)); 395 | xrstor_state(xsave_buf, 0x18); 396 | 397 | /* Disable MPX. */ 398 | xsave_buf->xsave_hdr.xstate_bv = 0x10; 399 | xsave_buf->bndcsr.cfg_reg_u = 0; 400 | xsave_buf->bndcsr.status_reg = 0; 401 | 402 | xrstor_state(xsave_buf, 0x10); 403 | } 404 | 405 | bool 406 | process_specific_init (void) 407 | { 408 | //if (!check_mpx_support ()) 409 | // return false; 410 | 411 | l1base = mmap (NULL, MPX_L1_SIZE, PROT_READ | PROT_WRITE, 412 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 413 | if (l1base == MAP_FAILED) 414 | { 415 | perror ("mmap"); 416 | exit (EXIT_FAILURE); 417 | } 418 | 419 | enable_mpx (); 420 | 421 | if (prctl (43, 0, 0, 0, 0)) 422 | { 423 | __mpxrt_print (VERB_ERROR, "No MPX support\n"); 424 | disable_mpx (); 425 | return false; 426 | } 427 | 428 | return true; 429 | } 430 | 431 | static bool 432 | process_specific_finish (void) 433 | { 434 | //if (!check_mpx_support ()) 435 | // return false; 436 | 437 | if (prctl (44, 0, 0, 0, 0)) 438 | { 439 | __mpxrt_print (VERB_ERROR, "No MPX support\n"); 440 | return false; 441 | } 442 | 443 | munmap (l1base, MPX_L1_SIZE); 444 | 445 | return true; 446 | } 447 | 448 | static void 449 | setup_handler (void) 450 | { 451 | int r,rs; 452 | struct sigaction newact; 453 | 454 | /* #BR is mapped to sigsegv */ 455 | int signum = SIGSEGV; 456 | 457 | newact.sa_handler = 0; 458 | newact.sa_sigaction = handler_wrap; 459 | 460 | /* sigset_t - signals to block while in the handler 461 | get the old signal mask. */ 462 | rs = sigprocmask (SIG_SETMASK, 0, &newact.sa_mask); 463 | assert (rs == 0); 464 | 465 | /* Call sa_sigaction, not sa_handler. */ 466 | newact.sa_flags = SA_SIGINFO; 467 | /* In case we call user's handler on SIGSEGV (not bound 468 | violation exception) we want to allow bound checking 469 | inside the user handler -> nested exception. */ 470 | newact.sa_flags |= SA_NODEFER; 471 | 472 | newact.sa_restorer = 0; 473 | r = sigaction (signum, &newact, 0); 474 | assert (r == 0); 475 | } 476 | 477 | static void mpxrt_prepare (size_t area_size) 478 | { 479 | //__mpxrt_init_env_vars (&bndpreserve); 480 | //setup_handler (); 481 | process_specific_init (); 482 | 483 | //printf("[CFIXX LOG]: About to do mpx initialization\n"); 484 | // setup unsafe region mpx bounds 485 | //size_t unsafe_bounds[2] = {0ull, (1ull << 32) - 1}; 486 | //asm("bndmov %0, %%bnd0" 487 | // : 488 | // : "m" (unsafe_bounds) 489 | //); 490 | 491 | /* NHB: CFIXX - fixed address, bounds moved so that I just have to do one check*/ 492 | //Actual offset is: 0xffff80fd697b9fff 493 | //Round down to 2^16 byte align: 0xffff80fd697b0000 494 | //divide by 2^16: 0xffff80fd697b 495 | 496 | asm( 497 | //"movw $0xffff80fd697b, %%es\n\t" 498 | "movq $0x000000000000, %%rax\n\t" 499 | "movq %0, %%rbx\n\t" 500 | "bndmk (%%rax, %%rbx, 0x1), %%bnd0" 501 | : 502 | : "rim"(0xFFFFFFFFFFFFFFFFL - area_size) 503 | : "%rax", "%rbx" 504 | ); 505 | 506 | //"movq $0x7fffcdbffffe, %%rbx\n\t" 507 | //"movq $0xfffffffe6dfffffe, %%rbx\n\t" 508 | //"movq $0xfffffffffffffe6d, %%rbx\n\t" 509 | 510 | } 511 | 512 | 513 | static void __attribute__ ((destructor)) 514 | mpxrt_cleanup (void) 515 | { 516 | if(!executed)return; 517 | executed = 0; 518 | __mpxrt_print_summary (num_bnd_chk, MPX_L1_SIZE); 519 | __mpxrt_utils_free (); 520 | process_specific_finish (); 521 | } 522 | 523 | /* Get address of bounds directory. */ 524 | void * 525 | get_bd () 526 | { 527 | return l1base; 528 | } 529 | 530 | #endif 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | #include 550 | #include 551 | #include 552 | #include 553 | #include 554 | #include 555 | 556 | #ifdef SHADOW_STACK_MPK 557 | #include "mpk.h" 558 | #endif 559 | 560 | int set_gsbase(void *addr) 561 | { 562 | #ifdef __FreeBSD__ 563 | #include 564 | #include 565 | #define pthread_getattr_np pthread_attr_get_np 566 | return (sysarch(AMD64_SET_GSBASE, &addr)); 567 | #else 568 | #include 569 | #include 570 | return arch_prctl(ARCH_SET_GS, (unsigned long)addr); 571 | #endif 572 | } 573 | 574 | #ifndef errExit 575 | #define errExit(msg) do { perror(msg); exit(errno); \ 576 | } while (0) 577 | #endif 578 | 579 | #ifndef MAP_FAIED 580 | #define MAP_FAIED ((void*)-1) 581 | #endif 582 | 583 | //glibc doesn't have a wrapper, declare it 584 | int arch_prctl(int code, unsigned long addr); 585 | 586 | #ifdef SHADOW_STACK_MPK 587 | static void init_pkey() 588 | { 589 | //allocate MPK 590 | int MPK = pkey_alloc(); 591 | //pkey is hardcoded to be 1 592 | if(MPK != 1) 593 | { 594 | printf("pkey_alloc unexpected behavior!\n"); 595 | exit(1); 596 | } 597 | } 598 | #endif 599 | 600 | static void *getmem(void *ptr, size_t size, int prot, int flags) 601 | { 602 | return mmap(ptr, size, prot, flags, -1, 0); 603 | } 604 | 605 | static void *getpage(void *ptr, size_t page_size) 606 | { 607 | #ifdef SHADOW_STACK_MPX 608 | void *page = getmem(SHADOW_STACK_PTR, page_size, 609 | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE); 610 | if(page != SHADOW_STACK_PTR) 611 | errExit("Failed to mmap() at hardcoded location!"); 612 | return page; 613 | #else 614 | return getmem(ptr, page_size, 615 | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE); 616 | #endif 617 | } 618 | 619 | static void init_shadow_stack(pthread_t thread) 620 | { 621 | //get the start of stack memory and stack size 622 | pthread_attr_t attr; 623 | pthread_attr_init(&attr); 624 | int status = pthread_getattr_np(thread, &attr); 625 | if(status) 626 | errExit("get stack attributes"); 627 | 628 | void *stack_base; 629 | size_t stack_size; 630 | //getstack(&stack_base, &stack_size); 631 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 632 | if(status) 633 | errExit("get stack size"); 634 | 635 | #ifdef SHADOW_STACK_MEM_SCHEME 636 | void **shadow_base = getpage(SHADOW_STACK_PTR, stack_size); 637 | if(shadow_base != SHADOW_STACK_PTR) 638 | errExit("Failed to mmap() at hardcoded location"); 639 | *shadow_base = (shadow_base+1); 640 | #ifdef SHADOW_STACK_MPX 641 | mpxrt_prepare(stack_size); 642 | #endif 643 | #else 644 | 645 | //allocate the shadowstack at constant offset 646 | void **shadow_base = getpage( 647 | (char*)stack_base+SHADOW_STACK_OFFSET, stack_size); 648 | #endif 649 | if(shadow_base == MAP_FAILED) 650 | errExit("failed to mmap() a shadow stack"); 651 | 652 | #ifdef SHADOW_STACK_MPK 653 | //bind mpk to the shadow stack 654 | status = pkey_mprotect(shadow_base, stack_size, 655 | PROT_READ | PROT_WRITE, PKEY); 656 | if (status == -1) 657 | errExit("pkey_mprotect"); 658 | #endif 659 | } 660 | 661 | #ifdef SHADOW_STACK_REG 662 | static void init_shadow_stack_reg(pthread_t thread) 663 | { 664 | //get the start of stack memory and stack size 665 | const size_t pagesize = getpagesize(); 666 | pthread_attr_t attr; 667 | pthread_attr_init(&attr); 668 | pthread_getattr_np(thread, &attr); 669 | void *stack_base; 670 | size_t stack_size = (2<<20) * 8; 671 | int status = 0; 672 | //getstack(&stack_base, &stack_size); 673 | status = pthread_attr_getstack(&attr, &stack_base, &stack_size); 674 | if(status) 675 | errExit("get stack size"); 676 | void **clave = getpage(NULL, pagesize); 677 | if(clave == MAP_FAILED) 678 | errExit("SHADOW_STACK_REG_CLAVE"); 679 | 680 | char *sentinel = getmem(SHADOW_STACK_SENTINEL, pagesize*2, PROT_READ|PROT_WRITE, 681 | MAP_FIXED | MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS); 682 | if(sentinel == (char*)MAP_FAILED) 683 | { 684 | errExit("SHADOW_STACK_SENTINEL"); 685 | } 686 | mprotect(sentinel+pagesize, pagesize, PROT_NONE); 687 | 688 | void *shadowstack = getpage(NULL, stack_size); 689 | #ifdef SHADOW_STACK_MPK 690 | //bind mpk to the shadow stack 691 | status = pkey_mprotect(shadowstack, stack_size, 692 | PROT_READ | PROT_WRITE, PKEY); 693 | if (status == -1) 694 | errExit("pkey_mprotect shadowstack"); 695 | #endif 696 | #ifdef SHADOW_STACK_MPX 697 | mpxrt_prepare(stack_size); 698 | #endif 699 | clave[0] = (void*)((size_t)shadowstack - (size_t)stack_base);//(void*)((size_t)shadowstack + 16); 700 | //location of shadow stack 701 | clave[1] = shadowstack; 702 | //top of shadow stack, if using minimal style 703 | clave[2] = shadowstack; 704 | //function call count, if counting... 705 | clave[3] = 0; 706 | 707 | //location of this page 708 | clave[4] = (void*)clave; 709 | set_gsbase(clave); 710 | } 711 | 712 | #endif 713 | 714 | // #ifdef SHADOW_STACK_SEG 715 | static void init_shadow_stack_seg(pthread_t thread) 716 | { 717 | //get the start of stack memory and stack size 718 | pthread_attr_t attr; 719 | pthread_attr_init(&attr); 720 | pthread_getattr_np(thread, &attr); 721 | size_t stack_size; 722 | int status = 0; 723 | status = pthread_attr_getstacksize(&attr, &stack_size); 724 | if(status) 725 | errExit("get stack size"); 726 | void **page = getmem(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS); 727 | if(page == MAP_FAIED) 728 | page = getpage(NULL, stack_size); 729 | if(page == MAP_FAILED) 730 | errExit("main thread mmap()"); 731 | 732 | page[0] = (void*)(page+2); 733 | page[1] = (void*)(page); 734 | set_gsbase(page); 735 | 736 | #ifdef SHADOW_STACK_MPK 737 | //bind mpk to the shadow stack 738 | status = pkey_mprotect(page, stack_size, 739 | PROT_READ | PROT_WRITE, PKEY); 740 | if (status == -1) 741 | errExit("pkey_mprotect"); 742 | #endif 743 | #ifdef SHADOW_STACK_MPX 744 | mpxrt_prepare(stack_size); 745 | #endif 746 | } 747 | // #endif 748 | 749 | 750 | #ifdef COUNT_FUNCTION_CALLS 751 | static void __attribute__ ((destructor)) 752 | function_call_log (void) 753 | { 754 | char buf[180]; 755 | int fd = open("/proc/self/comm", O_RDONLY); 756 | if(fd < 0) 757 | errExit("open(\"/proc/self/comm\")"); 758 | int ret = read(fd, buf, sizeof(buf)); 759 | if(ret <= 0) 760 | errExit("read(\"/proc/self/comm\", buf)"); 761 | buf[ret-1] = 0; 762 | close(fd); 763 | 764 | char filename[260]; 765 | int len = sprintf(filename, "%s/%s.txt", getenv("HOME"), buf); 766 | fd = open(filename, O_CREAT | O_WRONLY |O_APPEND, 0740); 767 | if(fd < 0) 768 | errExit(filename); 769 | 770 | size_t function_calls = 0; 771 | void **shadowstack = NULL; 772 | 773 | asm volatile("movq %gs:24, %rax"); 774 | asm volatile("movq %%rax, %0":"=r*m"(function_calls)::); 775 | //asm volatile("movq %gs:8, %rax"); 776 | //asm volatile("movq %%rax, %0":"=r*m"(shadowstack)::); 777 | // function_calls = 0; 778 | //while(*shadowstack) 779 | //{ 780 | // shadowstack++; 781 | // function_calls++; 782 | //} 783 | len = sprintf(buf, "%lu\n", function_calls); 784 | if(write(fd, buf, len) < 0) 785 | perror("write() to log file"); 786 | close(fd); 787 | } 788 | #endif 789 | 790 | __attribute__((constructor(0))) 791 | void init_all(){ 792 | if(!executed){ 793 | #ifdef SHADOW_STACK_MPK 794 | init_pkey(); 795 | #endif 796 | #ifdef SHADOW_STACK_REG 797 | init_shadow_stack_reg(pthread_self()); 798 | #endif 799 | #ifdef SHADOW_STACK_MEM_SCHEME 800 | init_shadow_stack(pthread_self()); 801 | #endif 802 | #ifdef SHADOW_STACK_CON 803 | init_shadow_stack(pthread_self()); 804 | #endif 805 | #ifdef SHADOW_STACK_SEG 806 | init_shadow_stack_seg(pthread_self()); 807 | #endif 808 | // init_shadow_stack_seg(pthread_self()); 809 | //#ifdef SHADOW_STACK_MPX 810 | // getpage(SHADOW_STACK_PTR, PRACTICAL_STACK_SIZE); 811 | // mpxrt_prepare(PRACTICAL_STACK_SIZE); 812 | //#endif 813 | executed = 1; 814 | } 815 | } 816 | -------------------------------------------------------------------------------- /Compiler-Impl/src/stackoverflow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | typedef void *(*pthread_start_routine) (void *); 7 | 8 | pid_t ok_function() 9 | { 10 | return getppid() & getpid(); 11 | } 12 | 13 | void the_goal() 14 | { 15 | execlp("bash", "bash", NULL); 16 | } 17 | 18 | void unsafe_function() 19 | { 20 | //get the base pointer 21 | void **base = NULL; 22 | asm("mov %%rbp, %0" : "=r"(base)::); 23 | 24 | //don't try this at home 25 | //overwrite the return addr 26 | base[1] = the_goal; 27 | } 28 | 29 | int main(int argc, const char *argv[]) 30 | { 31 | printf("About to call a safe function...\n"); 32 | ok_function(); 33 | printf("Retunred from safe function\n"); 34 | 35 | printf("About to overwrite the stack...\n"); 36 | if(argc == 2 && strcmp(argv[1], "mt") == 0) 37 | { 38 | pthread_t thread; 39 | int tid = pthread_create(&thread, NULL, (pthread_start_routine)unsafe_function, NULL); 40 | printf("TID: %d\n", tid); 41 | pthread_join(thread, NULL); 42 | }else 43 | { 44 | unsafe_function(); 45 | } 46 | printf("Retunred from an unsafe function. This should not happen\n"); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /Compiler-Impl/src/x86-CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_TARGET_DEFINITIONS X86.td) 2 | 3 | tablegen(LLVM X86GenAsmMatcher.inc -gen-asm-matcher) 4 | tablegen(LLVM X86GenAsmWriter.inc -gen-asm-writer) 5 | tablegen(LLVM X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1) 6 | tablegen(LLVM X86GenCallingConv.inc -gen-callingconv) 7 | tablegen(LLVM X86GenDAGISel.inc -gen-dag-isel) 8 | tablegen(LLVM X86GenDisassemblerTables.inc -gen-disassembler) 9 | tablegen(LLVM X86GenEVEX2VEXTables.inc -gen-x86-EVEX2VEX-tables) 10 | tablegen(LLVM X86GenFastISel.inc -gen-fast-isel) 11 | tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel) 12 | tablegen(LLVM X86GenInstrInfo.inc -gen-instr-info) 13 | tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank) 14 | tablegen(LLVM X86GenRegisterInfo.inc -gen-register-info) 15 | tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget) 16 | 17 | if (X86_GEN_FOLD_TABLES) 18 | tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables) 19 | endif() 20 | 21 | add_public_tablegen_target(X86CommonTableGen) 22 | 23 | set(sources 24 | ShadowCallStack.cpp 25 | X86AsmPrinter.cpp 26 | X86CallFrameOptimization.cpp 27 | X86CallingConv.cpp 28 | X86CallLowering.cpp 29 | X86CmovConversion.cpp 30 | X86DomainReassignment.cpp 31 | X86ExpandPseudo.cpp 32 | X86FastISel.cpp 33 | X86FixupBWInsts.cpp 34 | X86FixupLEAs.cpp 35 | X86AvoidStoreForwardingBlocks.cpp 36 | X86FixupSetCC.cpp 37 | X86FlagsCopyLowering.cpp 38 | X86FloatingPoint.cpp 39 | X86FrameLowering.cpp 40 | X86InstructionSelector.cpp 41 | X86ISelDAGToDAG.cpp 42 | X86ISelLowering.cpp 43 | X86IndirectBranchTracking.cpp 44 | X86InterleavedAccess.cpp 45 | X86InstrFMA3Info.cpp 46 | X86InstrInfo.cpp 47 | X86EvexToVex.cpp 48 | X86LegalizerInfo.cpp 49 | X86MCInstLower.cpp 50 | X86MachineFunctionInfo.cpp 51 | X86MacroFusion.cpp 52 | X86OptimizeLEAs.cpp 53 | X86PadShortFunction.cpp 54 | X86RegisterBankInfo.cpp 55 | X86RegisterInfo.cpp 56 | X86RetpolineThunks.cpp 57 | X86SelectionDAGInfo.cpp 58 | X86ShuffleDecodeConstantPool.cpp 59 | X86Subtarget.cpp 60 | X86TargetMachine.cpp 61 | X86TargetObjectFile.cpp 62 | X86TargetTransformInfo.cpp 63 | X86VZeroUpper.cpp 64 | X86WinAllocaExpander.cpp 65 | X86WinEHState.cpp 66 | X86ShadowStackMem.cpp 67 | X86ShadowStackCon.cpp 68 | X86ShadowStackReg.cpp 69 | X86ShadowStackMPX.cpp 70 | X86ShadowStackSeg.cpp 71 | X86FunctionCountPass.cpp 72 | ) 73 | 74 | add_llvm_target(X86CodeGen ${sources}) 75 | 76 | add_subdirectory(AsmParser) 77 | add_subdirectory(Disassembler) 78 | add_subdirectory(InstPrinter) 79 | add_subdirectory(MCTargetDesc) 80 | add_subdirectory(TargetInfo) 81 | add_subdirectory(Utils) 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShadowStack 2 | LLVM Implementation of different ShadowStack schemes for x86_64 3 | 4 | How to build & run: 5 | ``` 6 | cd Compiler-Impl 7 | ./configure.sh 8 | make 9 | ``` 10 | 11 | This will put compiler binaries in debug-build 12 | To get a release build, do 13 | `make release` 14 | 15 | 16 | To run different versions of shadow stack, toggle the macros in `Compiler-Impl/src/ShadowStackFeatures.h` 17 | --------------------------------------------------------------------------------