From d8a7904e06e77baf137b6713f9bf79f74ae6edfe Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Fri, 27 Mar 2020 14:19:07 +0100 Subject: [PATCH] LVI hardening tests for cmake --- .../cmake_plus_one_c.checks | 6 ++++++ .../cmake_plus_one_c_asm.checks | 16 +++++++++++++++ .../cmake_plus_one_cxx.checks | 6 ++++++ .../cmake_plus_one_cxx_asm.checks | 16 +++++++++++++++ .../enclave/Cargo.toml | 1 + .../enclave/build.rs | 15 ++++++++++++++ .../enclave/libcmake_foo/CMakeLists.txt | 4 ++++ .../enclave/libcmake_foo/src/foo.c | 17 ++++++++++++++++ .../enclave/libcmake_foo/src/foo_cxx.cpp | 20 +++++++++++++++++++ .../enclave/src/main.rs | 9 +++++++++ .../x86_64-fortanix-unknown-sgx-lvi/script.sh | 10 ++++++++++ 11 files changed, 120 insertions(+) create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c create mode 100644 src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks new file mode 100644 index 000000000000..f551356b2ff8 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks @@ -0,0 +1,6 @@ +CHECK: cmake_plus_one_c +CHECK: lfence +CHECK: popq +CHECK-NEXT: popq [[REGISTER:%[a-z]+]] +CHECK-NEXT: lfence +CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks new file mode 100644 index 000000000000..87c806f137a9 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks @@ -0,0 +1,16 @@ +CHECK: cmake_plus_one_c_asm +CHECK: lfence +CHECK: lfence +CHECK: lfence +CHECK: lfence +CHECK: movl +CHECK: lfence +CHECK-NEXT: incl +CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} +CHECK-NEXT: shlq $0, (%rsp) +CHECK-NEXT: lfence +CHECK-NEXT: retq +CHECK: popq +CHECK-NEXT: popq [[REGISTER:%[a-z]+]] +CHECK-NEXT: lfence +CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks new file mode 100644 index 000000000000..0f403e0203c1 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks @@ -0,0 +1,6 @@ +CHECK: cmake_plus_one_cxx +CHECK: lfence +CHECK: popq +CHECK-NEXT: popq [[REGISTER:%[a-z]+]] +CHECK-NEXT: lfence +CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks new file mode 100644 index 000000000000..9cac8711ea84 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks @@ -0,0 +1,16 @@ +CHECK: cmake_plus_one_cxx_asm +CHECK: lfence +CHECK: lfence +CHECK: lfence +CHECK: lfence +CHECK: movl +CHECK: lfence +CHECK-NEXT: incl +CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} +CHECK-NEXT: shlq $0, (%rsp) +CHECK-NEXT: lfence +CHECK-NEXT: retq +CHECK: popq +CHECK-NEXT: popq [[REGISTER:%[a-z]+]] +CHECK-NEXT: lfence +CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml index da1b1e7f06c5..89490686584d 100644 --- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml @@ -10,3 +10,4 @@ edition = "2018" [build-dependencies] cc = "1.0" +cmake = "0.1" diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs index 66ddea3793aa..eff25e8641b7 100644 --- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs @@ -8,4 +8,19 @@ fn main() { .cpp_set_stdlib(None) .file("foo_cxx.cpp") .compile("foo_cxx"); + + // When the cmake crate detects the clang compiler, it passes the + // "--target" argument to the linker which subsequently fails. The + // `CMAKE_C_COMPILER_FORCED` option makes sure that `cmake` does not + // tries to test the compiler. From version 3.6 the option + // `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` can be used + // https://cmake.org/cmake/help/v3.5/module/CMakeForceCompiler.html + let dst = cmake::Config::new("libcmake_foo") + .build_target("cmake_foo") + .define("CMAKE_C_COMPILER_FORCED", "1") + .define("CMAKE_CXX_COMPILER_FORCED", "1") + .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1") + .build(); + println!("cargo:rustc-link-search=native={}/build/", dst.display()); + println!("cargo:rustc-link-lib=static=cmake_foo"); } diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt new file mode 100644 index 000000000000..f501fe6f7dde --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(cmake_foo STATIC + src/foo.c + src/foo_cxx.cpp +) diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c new file mode 100644 index 000000000000..cbfde6ce9299 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c @@ -0,0 +1,17 @@ +int cmake_plus_one_c(int *arg) { + return *arg + 1; +} + +int cmake_plus_one_c_asm(int *arg) { + int value = 0; + + asm volatile ( " movl (%1), %0\n" + " inc %0\n" + " jmp 1f\n" + " retq\n" // never executed, but a shortcut to determine how the assembler deals with `ret` instructions + "1:\n" + : "=r"(value) + : "r"(arg) ); + + return value; +} diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp new file mode 100644 index 000000000000..63a89111c119 --- /dev/null +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp @@ -0,0 +1,20 @@ +extern "C" int cmake_plus_one_cxx(int *arg); +extern "C" int cmake_plus_one_cxx_asm(int *arg); + +int cmake_plus_one_cxx(int *arg) { + return *arg + 1; +} + +int cmake_plus_one_cxx_asm(int *arg) { + int value = 0; + + asm volatile ( " movl (%1), %0\n" + " inc %0\n" + " jmp 1f\n" + " retq\n" // never executed, but a shortcut to determine how the assembler deals with `ret` instructions + "1:\n" + : "=r"(value) + : "r"(arg) ); + + return value; +} diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs index afbee78e3450..358547c13621 100644 --- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs @@ -3,6 +3,10 @@ extern { fn cc_plus_one_c_asm(arg : &u32) -> u32; fn cc_plus_one_cxx(arg : &u32) -> u32; fn cc_plus_one_cxx_asm(arg : &u32) -> u32; + fn cmake_plus_one_c(arg : &u32) -> u32; + fn cmake_plus_one_c_asm(arg : &u32) -> u32; + fn cmake_plus_one_cxx(arg : &u32) -> u32; + fn cmake_plus_one_cxx_asm(arg : &u32) -> u32; } fn main() { @@ -13,5 +17,10 @@ fn main() { println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cc_plus_one_c_asm(&value)); println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cc_plus_one_cxx(&value)); println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cc_plus_one_cxx_asm(&value)); + + println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cmake_plus_one_c(&value)); + println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cmake_plus_one_c_asm(&value)); + println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cmake_plus_one_cxx(&value)); + println!("Answer to the Ultimate Question of Life, the Universe, and Everything: {}!", cmake_plus_one_cxx_asm(&value)); } } diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh index be2d247de0bd..1595dbbbb9f2 100644 --- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh @@ -39,7 +39,17 @@ build #check "libunwind::Registers_x86_64::jumpto()" jumpto.checks check "std::io::stdio::_print::h87f0c238421c45bc" print.checks +#TODO: the current passes cannot handle module level assembly! +# No checks are implemented check cc_plus_one_c cc_plus_one_c.checks check cc_plus_one_c_asm cc_plus_one_c_asm.checks check cc_plus_one_cxx cc_plus_one_cxx.checks check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks + +check cmake_plus_one_c cmake_plus_one_c.checks +check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks +check cmake_plus_one_cxx cmake_plus_one_cxx.checks +check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks + +#WARNING clang/clang++ use an integrated assembler when given an assembly file. +# LVI patches are *not* applied