Skip to content

Commit

Permalink
rewrite x86_64-fortanix-unknown-sgx-lvi to rmake
Browse files Browse the repository at this point in the history
  • Loading branch information
Oneirical committed Aug 13, 2024
1 parent 80eb5a8 commit 1f9cc33
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
1 change: 0 additions & 1 deletion src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@ run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/sysroot-crates-are-unstable/Makefile
run-make/translation/Makefile
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# FIXME(Oneirical): Disabled for now. Remove this if the rmake.rs replacement
# is shown to work, or restore it if the rmake.rs replacement does not work.

include ../tools.mk

#only-x86_64-fortanix-unknown-sgx
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#!/bin/bash

# FIXME(Oneirical): Disabled for now. Remove this if the rmake.rs replacement
# is shown to work, or restore it if the rmake.rs replacement does not work.

set -exuo pipefail

function build {
Expand Down
92 changes: 92 additions & 0 deletions tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This security test checks that the disassembled form of certain symbols
// is "hardened" - that means, the assembly instructions match a pattern that shows
// lack of vulnerability to a Load Value Injection attack.
// To do so, a test crate is compiled, and certain symbols are found, disassembled
// and checked one by one.
// See https://github.com/rust-lang/rust/pull/77008

//@ only-x86_64-fortanix-unknown-sgx

use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, target};

fn main() {
let main_dir = cwd();
std::env::set_current_dir("enclave").unwrap();
// HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
// These come from the top-level Rust workspace, that this crate is not a
// member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
cmd("cargo")
.env("RUSTC_BOOTSTRAP", "1")
.arg("-v")
.arg("run")
.arg("--target")
.arg(target())
.run();
std::env::set_current_dir(&main_dir).unwrap();
check("unw_getcontext", "unw_getcontext.checks");
check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks");

check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks");

check("st_plus_one_global_asm", "rust_plus_one_global_asm.checks");

check("_plus_one_c", "cc_plus_one_c.checks");
check("_plus_one_c_asm", "cc_plus_one_c_asm.checks");
check("_plus_one_cxx", "cc_plus_one_cxx.checks");
check("_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks");
check("_plus_one_asm", "cc_plus_one_asm.checks");

check("ake_plus_one_c", "cmake_plus_one_c.checks");
check("ake_plus_one_c_asm", "cmake_plus_one_c_asm.checks");
check("ake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks");
check("ake_plus_one_cxx", "cmake_plus_one_cxx.checks");
check("ake_plus_one_cxx_asm", "cmake_plus_one_cxx_asm.checks");
check("cmake_plus_one_cxx_global_asm", "cmake_plus_one_cxx_global_asm.checks");
check("cmake_plus_one_asm", "cmake_plus_one_asm.checks");
}

fn check(func_re: &str, checks: &str) {
let dump = llvm_objdump()
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
.args(&["--syms", "--demangle"])
.run()
.stdout_utf8();
let re = regex::Regex::new(&format!("[[:blank:]]+{func_re}")).unwrap();
let func = re.find_iter(&dump).map(|m| m.as_str().trim()).collect::<Vec<&str>>().join(",");
let dump = llvm_objdump()
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
.args(&["--syms", &format!("--disassemble-symbols={func}")])
.run()
.stdout_utf8();
let dump = dump.as_bytes();

// Unique case, must succeed at one of two possible tests.
if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
if !output.status().success() {
llvm_filecheck().stdin(&dump).patterns("print.without_frame_pointers.checks").run();
llvm_filecheck()
.args(&["--implicit-check-not", "ret"])
.stdin(dump)
.patterns("print.without_frame_pointers.checks")
.run();
} else {
llvm_filecheck()
.args(&["--implicit-check-not", "ret"])
.stdin(dump)
.patterns(checks)
.run();
}
return;
}
llvm_filecheck().stdin(&dump).patterns(checks).run();
if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
.contains(&func_re)
{
// The assembler cannot avoid explicit `ret` instructions. Sequences
// of `shlq $0x0, (%rsp); lfence; retq` are used instead.
// https://www.intel.com/content/www/us/en/developer/articles/technical/
// software-security-guidance/technical-documentation/load-value-injection.html
llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
}
}

0 comments on commit 1f9cc33

Please sign in to comment.