Skip to content

LVI hardening tests #77008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/bootstrap/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,14 @@ impl Step for TestHelpers {
if builder.config.dry_run {
return;
}
let target = self.target;
// The x86_64-fortanix-unknown-sgx target doesn't have a working C
// toolchain. However, some x86_64 ELF objects can be linked
// without issues. Use this hack to compile the test helpers.
let target = if self.target == "x86_64-fortanix-unknown-sgx" {
TargetSelection::from_user("x86_64-unknown-linux-gnu")
} else {
self.target
};
let dst = builder.test_helpers_out(target);
let src = builder.src.join("src/test/auxiliary/rust_test_helpers.c");
if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
Expand All @@ -649,7 +656,6 @@ impl Step for TestHelpers {
}
cfg.compiler(builder.cc(target));
}

cfg.cargo_metadata(false)
.out_dir(&dst)
.target(&target.triple)
Expand Down
17 changes: 17 additions & 0 deletions src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Test LVI load hardening on SGX enclave code

// assembly-output: emit-asm
// compile-flags: --crate-type staticlib
// only-x86_64-fortanix-unknown-sgx

#[no_mangle]
pub extern fn plus_one(r: &mut u64) {
*r = *r + 1;
}

// CHECK: plus_one
// CHECK: lfence
// CHECK-NEXT: addq
// CHECK: popq [[REGISTER:%[a-z]+]]
// CHECK-NEXT: lfence
// CHECK-NEXT: jmpq *[[REGISTER]]
12 changes: 12 additions & 0 deletions src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Test LVI ret hardening on generic rust code

// assembly-output: emit-asm
// compile-flags: --crate-type staticlib
// only-x86_64-fortanix-unknown-sgx

#[no_mangle]
pub extern fn myret() {}
// CHECK: myret:
// CHECK: popq [[REGISTER:%[a-z]+]]
// CHECK-NEXT: lfence
// CHECK-NEXT: jmpq *[[REGISTER]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Test LVI load hardening on SGX inline assembly code

// assembly-output: emit-asm
// compile-flags: --crate-type staticlib
// only-x86_64-fortanix-unknown-sgx

#![feature(asm)]

#[no_mangle]
pub extern fn get(ptr: *const u64) -> u64 {
let value : u64;
unsafe {
asm!(".start_inline_asm:",
"mov {}, [{}]",
".end_inline_asm:",
out(reg) value,
in(reg) ptr);
}
value
}

// CHECK: get
// CHECK: .start_inline_asm
// CHECK-NEXT: movq
// CHECK-NEXT: lfence
// CHECK-NEXT: .end_inline_asm

#[no_mangle]
pub extern fn myret() {
unsafe {
asm!(".start_myret_inline_asm:
ret
.end_myret_inline_asm:");
}
}

// CHECK: myret
// CHECK: .start_myret_inline_asm
// CHECK-NEXT: shlq $0, (%rsp)
// CHECK-NEXT: lfence
// CHECK-NEXT: retq
23 changes: 23 additions & 0 deletions src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-include ../../run-make-fulldeps/tools.mk

#only-x86_64-fortanix-unknown-sgx

# For cargo setting
export RUSTC := $(RUSTC_ORIGINAL)
export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
# We need to be outside of 'src' dir in order to run cargo
export WORK_DIR := $(TMPDIR)
export TEST_DIR := $(shell pwd)

## clean up unused env variables which might cause harm.
unexport RUSTC_LINKER
unexport RUSTC_BOOTSTRAP
unexport RUST_BUILD_STAGE
unexport RUST_TEST_THREADS
unexport RUST_TEST_TMPDIR
unexport AR
unexport CC
unexport CXX

all:
bash script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHECK: cc_plus_one_asm
CHECK-NEXT: movl
CHECK-NEXT: lfence
CHECK-NEXT: inc
CHECK-NEXT: notq (%rsp)
CHECK-NEXT: notq (%rsp)
CHECK-NEXT: lfence
CHECK-NEXT: retq
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CHECK: cc_plus_one_c
CHECK: lfence
CHECK: popq
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
CHECK-NEXT: lfence
CHECK-NEXT: jmpq *[[REGISTER]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CHECK: cc_plus_one_c_asm
CHECK: lfence
CHECK: lfence
CHECK: lfence
CHECK: lfence
CHECK: lfence
CHECK-NEXT: incl
CHECK-NEXT: jmp
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]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CHECK: cc_plus_one_cxx
CHECK: lfence
CHECK: popq
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
CHECK-NEXT: lfence
CHECK-NEXT: jmpq *[[REGISTER]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CHECK: cc_plus_one_cxx_asm
CHECK: lfence
CHECK: lfence
CHECK: lfence
CHECK: movl
CHECK: lfence
CHECK: lfence
CHECK-NEXT: incl
CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} <cc_plus_one_cxx_asm+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]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CHECK: cmake_plus_one_asm
CHECK-NEXT: movl
CHECK-NEXT: lfence
CHECK-NEXT: incl
CHECK-NEXT: shlq $0, (%rsp)
CHECK-NEXT: lfence
CHECK-NEXT: retq
Original file line number Diff line number Diff line change
@@ -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]]
Original file line number Diff line number Diff line change
@@ -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:]]+}} <cmake_plus_one_c_asm+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]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CHECK: cmake_plus_one_c_global_asm
CHECK: lfence
Original file line number Diff line number Diff line change
@@ -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]]
Original file line number Diff line number Diff line change
@@ -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:]]+}} <cmake_plus_one_cxx_asm+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]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CHECK: cmake_plus_one_cxx_global_asm
CHECK: lfence
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "enclave"
version = "0.1.0"
authors = ["Raoul Strackx <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[build-dependencies]
cc = "1.0"
cmake = "0.1"
30 changes: 30 additions & 0 deletions src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fn main() {
cc::Build::new()
.file("foo.c")
.compile("foo_c");

cc::Build::new()
.file("foo_asm.s")
.compile("foo_asm");

cc::Build::new()
.cpp(true)
.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");
}
18 changes: 18 additions & 0 deletions src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
int cc_plus_one_c(int *arg) {
return *arg + 1;
}

int cc_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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.text
.global cc_plus_one_asm
.type cc_plus_one_asm, @function
cc_plus_one_asm:
movl (%rdi), %eax
inc %eax
retq
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extern "C" int cc_plus_one_cxx(int *arg);
extern "C" int cc_plus_one_cxx_asm(int *arg);

int cc_plus_one_cxx(int *arg) {
return *arg + 1;
}

int cc_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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
enable_language(C CXX ASM)

set(C_SOURCES
src/foo.c
)

set_source_files_properties(${C_SOURCES}
PROPERTIES
LANGUAGE C)

set(CXX_SOURCES
src/foo_cxx.cpp
)

set_source_files_properties(${CXX_SOURCES}
PROPERTIES
LANGUAGE CXX)

set(ASM_SOURCES
src/foo_asm.s
)

set_source_files_properties(${ASM_SOURCES}
PROPERTIES
LANGUAGE ASM)

set(SOURCES
${C_SOURCES}
${CXX_SOURCES}
${ASM_SOURCES})

add_library(cmake_foo STATIC
${SOURCES})
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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;
}

asm(".text\n"
" .global cmake_plus_one_c_global_asm\n"
" .type cmake_plus_one_c_global_asm, @function\n"
"cmake_plus_one_c_global_asm:\n"
" movl (%rdi), %eax\n"
" inc %eax\n"
" retq\n" );
Loading