Skip to content

Commit 6369a98

Browse files
committed
Auto merge of #77008 - fortanix:raoul/lvi-tests, r=Mark-Simulacrum
LVI hardening tests Mitigating the speculative execution LVI attack against SGX enclaves requires compiler changes (i.e., adding lfences). This pull requests adds various tests to check if this happens correctly.
2 parents db7ee7c + 159d11f commit 6369a98

32 files changed

+519
-2
lines changed

src/bootstrap/native.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,14 @@ impl Step for TestHelpers {
630630
if builder.config.dry_run {
631631
return;
632632
}
633-
let target = self.target;
633+
// The x86_64-fortanix-unknown-sgx target doesn't have a working C
634+
// toolchain. However, some x86_64 ELF objects can be linked
635+
// without issues. Use this hack to compile the test helpers.
636+
let target = if self.target == "x86_64-fortanix-unknown-sgx" {
637+
TargetSelection::from_user("x86_64-unknown-linux-gnu")
638+
} else {
639+
self.target
640+
};
634641
let dst = builder.test_helpers_out(target);
635642
let src = builder.src.join("src/test/auxiliary/rust_test_helpers.c");
636643
if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
@@ -654,7 +661,6 @@ impl Step for TestHelpers {
654661
}
655662
cfg.compiler(builder.cc(target));
656663
}
657-
658664
cfg.cargo_metadata(false)
659665
.out_dir(&dst)
660666
.target(&target.triple)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Test LVI load hardening on SGX enclave code
2+
3+
// assembly-output: emit-asm
4+
// compile-flags: --crate-type staticlib
5+
// only-x86_64-fortanix-unknown-sgx
6+
7+
#[no_mangle]
8+
pub extern fn plus_one(r: &mut u64) {
9+
*r = *r + 1;
10+
}
11+
12+
// CHECK: plus_one
13+
// CHECK: lfence
14+
// CHECK-NEXT: addq
15+
// CHECK: popq [[REGISTER:%[a-z]+]]
16+
// CHECK-NEXT: lfence
17+
// CHECK-NEXT: jmpq *[[REGISTER]]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test LVI ret hardening on generic rust code
2+
3+
// assembly-output: emit-asm
4+
// compile-flags: --crate-type staticlib
5+
// only-x86_64-fortanix-unknown-sgx
6+
7+
#[no_mangle]
8+
pub extern fn myret() {}
9+
// CHECK: myret:
10+
// CHECK: popq [[REGISTER:%[a-z]+]]
11+
// CHECK-NEXT: lfence
12+
// CHECK-NEXT: jmpq *[[REGISTER]]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Test LVI load hardening on SGX inline assembly code
2+
3+
// assembly-output: emit-asm
4+
// compile-flags: --crate-type staticlib
5+
// only-x86_64-fortanix-unknown-sgx
6+
7+
#![feature(asm)]
8+
9+
#[no_mangle]
10+
pub extern fn get(ptr: *const u64) -> u64 {
11+
let value : u64;
12+
unsafe {
13+
asm!(".start_inline_asm:",
14+
"mov {}, [{}]",
15+
".end_inline_asm:",
16+
out(reg) value,
17+
in(reg) ptr);
18+
}
19+
value
20+
}
21+
22+
// CHECK: get
23+
// CHECK: .start_inline_asm
24+
// CHECK-NEXT: movq
25+
// CHECK-NEXT: lfence
26+
// CHECK-NEXT: .end_inline_asm
27+
28+
#[no_mangle]
29+
pub extern fn myret() {
30+
unsafe {
31+
asm!(".start_myret_inline_asm:
32+
ret
33+
.end_myret_inline_asm:");
34+
}
35+
}
36+
37+
// CHECK: myret
38+
// CHECK: .start_myret_inline_asm
39+
// CHECK-NEXT: shlq $0, (%rsp)
40+
// CHECK-NEXT: lfence
41+
// CHECK-NEXT: retq
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
#only-x86_64-fortanix-unknown-sgx
4+
5+
# For cargo setting
6+
export RUSTC := $(RUSTC_ORIGINAL)
7+
export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
8+
# We need to be outside of 'src' dir in order to run cargo
9+
export WORK_DIR := $(TMPDIR)
10+
export TEST_DIR := $(shell pwd)
11+
12+
## clean up unused env variables which might cause harm.
13+
unexport RUSTC_LINKER
14+
unexport RUSTC_BOOTSTRAP
15+
unexport RUST_BUILD_STAGE
16+
unexport RUST_TEST_THREADS
17+
unexport RUST_TEST_TMPDIR
18+
unexport AR
19+
unexport CC
20+
unexport CXX
21+
22+
all:
23+
bash script.sh
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CHECK: cc_plus_one_asm
2+
CHECK-NEXT: movl
3+
CHECK-NEXT: lfence
4+
CHECK-NEXT: inc
5+
CHECK-NEXT: notq (%rsp)
6+
CHECK-NEXT: notq (%rsp)
7+
CHECK-NEXT: lfence
8+
CHECK-NEXT: retq
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CHECK: cc_plus_one_c
2+
CHECK: lfence
3+
CHECK: popq
4+
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
5+
CHECK-NEXT: lfence
6+
CHECK-NEXT: jmpq *[[REGISTER]]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CHECK: cc_plus_one_c_asm
2+
CHECK: lfence
3+
CHECK: lfence
4+
CHECK: lfence
5+
CHECK: lfence
6+
CHECK: lfence
7+
CHECK-NEXT: incl
8+
CHECK-NEXT: jmp
9+
CHECK-NEXT: shlq $0, (%rsp)
10+
CHECK-NEXT: lfence
11+
CHECK-NEXT: retq
12+
CHECK: popq
13+
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
14+
CHECK-NEXT: lfence
15+
CHECK-NEXT: jmpq *[[REGISTER]]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CHECK: cc_plus_one_cxx
2+
CHECK: lfence
3+
CHECK: popq
4+
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
5+
CHECK-NEXT: lfence
6+
CHECK-NEXT: jmpq *[[REGISTER]]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CHECK: cc_plus_one_cxx_asm
2+
CHECK: lfence
3+
CHECK: lfence
4+
CHECK: lfence
5+
CHECK: movl
6+
CHECK: lfence
7+
CHECK: lfence
8+
CHECK-NEXT: incl
9+
CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} <cc_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
10+
CHECK-NEXT: shlq $0, (%rsp)
11+
CHECK-NEXT: lfence
12+
CHECK-NEXT: retq
13+
CHECK: popq
14+
CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
15+
CHECK-NEXT: lfence
16+
CHECK-NEXT: jmpq *[[REGISTER]]

0 commit comments

Comments
 (0)