Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ffdde64

Browse files
committedAug 19, 2024
rewrite x86_64-fortanix-unknown-sgx-lvi to rmake
1 parent 4fe1e2b commit ffdde64

File tree

6 files changed

+111
-2
lines changed

6 files changed

+111
-2
lines changed
 

‎src/tools/run-make-support/src/env.rs

+8
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ pub fn env_var_os(name: &str) -> OsString {
2424
pub fn no_debug_assertions() -> bool {
2525
std::env::var_os("NO_DEBUG_ASSERTIONS").is_some()
2626
}
27+
28+
/// A wrapper around [`std::env::set_current_dir`] which includes the directory
29+
/// path in the panic message.
30+
#[track_caller]
31+
pub fn set_current_dir<P: AsRef<std::path::Path>>(dir: P) {
32+
std::env::set_current_dir(dir.as_ref())
33+
.expect(&format!("could not set current directory to \"{}\"", dir.as_ref().display()));
34+
}

‎src/tools/run-make-support/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
6464
pub use diff::{diff, Diff};
6565

6666
/// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers.
67-
pub use env::{env_var, env_var_os};
67+
pub use env::{env_var, env_var_os, set_current_dir};
6868

6969
/// Convenience helpers for running binaries and other commands.
7070
pub use run::{cmd, run, run_fail, run_with_args};

‎src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,3 @@ run-make/macos-deployment-target/Makefile
1111
run-make/split-debuginfo/Makefile
1212
run-make/symbol-mangling-hashed/Makefile
1313
run-make/translation/Makefile
14-
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile

‎tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile ‎tests/run-make/x86_64-fortanix-unknown-sgx-lvi/_Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# FIXME(Oneirical): Disabled for now. Remove this if the rmake.rs replacement
2+
# is shown to work, or restore it if the rmake.rs replacement does not work.
3+
14
include ../tools.mk
25

36
#only-x86_64-fortanix-unknown-sgx

‎tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh ‎tests/run-make/x86_64-fortanix-unknown-sgx-lvi/_script.sh

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#!/bin/bash
2+
3+
# FIXME(Oneirical): Disabled for now. Remove this if the rmake.rs replacement
4+
# is shown to work, or restore it if the rmake.rs replacement does not work.
5+
26
set -exuo pipefail
37

48
function build {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// ignore-tidy-linelength
2+
// Reason: intel.com link
3+
4+
// This security test checks that the disassembled form of certain symbols
5+
// is "hardened" - that means, the assembly instructions match a pattern that
6+
// mitigate potential Load Value Injection vulnerabilities.
7+
// To do so, a test crate is compiled, and certain symbols are found, disassembled
8+
// and checked one by one.
9+
// See https://github.com/rust-lang/rust/pull/77008
10+
11+
// On load value injection:
12+
// https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/load-value-injection.html
13+
14+
//@ only-x86_64-fortanix-unknown-sgx
15+
16+
use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target};
17+
18+
fn main() {
19+
let main_dir = cwd();
20+
set_current_dir("enclave");
21+
// HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
22+
// These come from the top-level Rust workspace, that this crate is not a
23+
// member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
24+
cmd("cargo")
25+
.env("RUSTC_BOOTSTRAP", "1")
26+
.arg("-v")
27+
.arg("run")
28+
.arg("--target")
29+
.arg(target())
30+
.run();
31+
set_current_dir(&main_dir);
32+
// Rust has various ways of adding code to a binary:
33+
// - Rust code
34+
// - Inline assembly
35+
// - Global assembly
36+
// - C/C++ code compiled as part of Rust crates
37+
// For those different kinds, we do have very small code examples that should be
38+
// mitigated in some way. Mostly we check that ret instructions should no longer be present.
39+
check("unw_getcontext", "unw_getcontext.checks");
40+
check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks");
41+
42+
check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks");
43+
44+
check("st_plus_one_global_asm", "rust_plus_one_global_asm.checks");
45+
46+
check("_plus_one_c", "cc_plus_one_c.checks");
47+
check("_plus_one_c_asm", "cc_plus_one_c_asm.checks");
48+
check("_plus_one_cxx", "cc_plus_one_cxx.checks");
49+
check("_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks");
50+
check("_plus_one_asm", "cc_plus_one_asm.checks");
51+
52+
check("cmake_plus_one_c", "cmake_plus_one_c.checks");
53+
check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks");
54+
check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks");
55+
check("cmake_plus_one_cxx", "cmake_plus_one_cxx.checks");
56+
check("cmake_plus_one_cxx_asm", "cmake_plus_one_cxx_asm.checks");
57+
check("cmake_plus_one_cxx_global_asm", "cmake_plus_one_cxx_global_asm.checks");
58+
check("cmake_plus_one_asm", "cmake_plus_one_asm.checks");
59+
}
60+
61+
fn check(func_re: &str, mut checks: &str) {
62+
let dump = llvm_objdump()
63+
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
64+
.args(&["--syms", "--demangle"])
65+
.run()
66+
.stdout_utf8();
67+
let re = regex::Regex::new(&format!("[[:blank:]]+{func_re}")).unwrap();
68+
let func = re.find_iter(&dump).map(|m| m.as_str().trim()).collect::<Vec<&str>>().join(",");
69+
let dump = llvm_objdump()
70+
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
71+
.args(&["--syms", &format!("--disassemble-symbols={func}")])
72+
.run()
73+
.stdout_utf8();
74+
let dump = dump.as_bytes();
75+
76+
// Unique case, must succeed at one of two possible tests.
77+
// This is because frame pointers are optional, and them being enabled requires
78+
// an additional `popq` in the pattern checking file.
79+
if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
80+
let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
81+
if !output.status().success() {
82+
checks = "print.without_frame_pointers.checks";
83+
llvm_filecheck().stdin(&dump).patterns(checks).run();
84+
}
85+
} else {
86+
llvm_filecheck().stdin(&dump).patterns(checks).run();
87+
}
88+
if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
89+
.contains(&func_re)
90+
{
91+
// The assembler cannot avoid explicit `ret` instructions. Sequences
92+
// of `shlq $0x0, (%rsp); lfence; retq` are used instead.
93+
llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
94+
}
95+
}

0 commit comments

Comments
 (0)
Failed to load comments.