mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #144395 - folkertdev:fortanix-run-make-test, r=jieyouxu
update fortanix tests Firstly, as far as I can tell, no CI job actually runs any of the fortanix tests? Maybe I'm missing the job that runs these tests though? In any case, the `assembly` tests now use `minicore`, meaning that they will run regardless of the host architecture (specifically, they will run during a standard PR CI build). The run-make test is actually broken, and I'd propose to make it just `cargo build` rather than `cargo run`. We can have a separate test for actually running the program, if desired. Also this test is subject to https://github.com/rust-lang/rust/issues/128733, so I'd like to re-evaluate what parts of the C/C++ compilation are actually required or useful. cc [``@jethrogb](https://github.com/jethrogb)`` [``@raoulstrackx](https://github.com/raoulstrackx)`` [``@aditijannu](https://github.com/aditijannu)`` r? ``@jieyouxu``
This commit is contained in:
@@ -1,17 +1,24 @@
|
||||
// Test LVI load hardening on SGX enclave code
|
||||
// Test LVI load hardening on SGX enclave code, specifically that `ret` is rewritten.
|
||||
|
||||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type staticlib
|
||||
//@ only-x86_64-fortanix-unknown-sgx
|
||||
//@ compile-flags: --target x86_64-fortanix-unknown-sgx -Copt-level=0
|
||||
//@ needs-llvm-components: x86
|
||||
|
||||
#![feature(no_core, lang_items, f16)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn plus_one(r: &mut u64) {
|
||||
*r = *r + 1;
|
||||
pub extern "C" fn dereference(a: &mut u64) -> u64 {
|
||||
// CHECK-LABEL: dereference
|
||||
// CHECK: lfence
|
||||
// CHECK: mov
|
||||
// CHECK: popq [[REGISTER:%[a-z]+]]
|
||||
// CHECK-NEXT: lfence
|
||||
// CHECK-NEXT: jmpq *[[REGISTER]]
|
||||
*a
|
||||
}
|
||||
|
||||
// CHECK: plus_one
|
||||
// CHECK: lfence
|
||||
// CHECK-NEXT: incq
|
||||
// CHECK: popq [[REGISTER:%[a-z]+]]
|
||||
// CHECK-NEXT: lfence
|
||||
// CHECK-NEXT: jmpq *[[REGISTER]]
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
// Test LVI ret hardening on generic rust code
|
||||
|
||||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type staticlib
|
||||
//@ only-x86_64-fortanix-unknown-sgx
|
||||
//@ compile-flags: --target x86_64-fortanix-unknown-sgx
|
||||
//@ needs-llvm-components: x86
|
||||
|
||||
#![feature(no_core, lang_items, f16)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn myret() {}
|
||||
// CHECK: myret:
|
||||
// CHECK-LABEL: myret:
|
||||
// CHECK: popq [[REGISTER:%[a-z]+]]
|
||||
// CHECK-NEXT: lfence
|
||||
// CHECK-NEXT: jmpq *[[REGISTER]]
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
// Test LVI load hardening on SGX inline assembly code
|
||||
|
||||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type staticlib
|
||||
//@ only-x86_64-fortanix-unknown-sgx
|
||||
//@ compile-flags: --target x86_64-fortanix-unknown-sgx
|
||||
//@ needs-llvm-components: x86
|
||||
|
||||
use std::arch::asm;
|
||||
#![feature(no_core, lang_items, f16)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get(ptr: *const u64) -> u64 {
|
||||
// CHECK-LABEL: get
|
||||
// CHECK: movq
|
||||
// CHECK-NEXT: lfence
|
||||
let value: u64;
|
||||
unsafe {
|
||||
asm!("mov {}, [{}]",
|
||||
@@ -17,18 +26,13 @@ pub extern "C" fn get(ptr: *const u64) -> u64 {
|
||||
value
|
||||
}
|
||||
|
||||
// CHECK: get
|
||||
// CHECK: movq
|
||||
// CHECK-NEXT: lfence
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn myret() {
|
||||
// CHECK-LABEL: myret
|
||||
// CHECK: shlq $0, (%rsp)
|
||||
// CHECK-NEXT: lfence
|
||||
// CHECK-NEXT: retq
|
||||
unsafe {
|
||||
asm!("ret");
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: myret
|
||||
// CHECK: shlq $0, (%rsp)
|
||||
// CHECK-NEXT: lfence
|
||||
// CHECK-NEXT: retq
|
||||
|
||||
@@ -13,42 +13,56 @@
|
||||
|
||||
//@ only-x86_64-fortanix-unknown-sgx
|
||||
|
||||
use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target};
|
||||
use run_make_support::{
|
||||
cargo, cwd, llvm_filecheck, llvm_objdump, regex, run, set_current_dir, target,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let main_dir = cwd();
|
||||
set_current_dir("enclave");
|
||||
// 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")
|
||||
cargo()
|
||||
.arg("-v")
|
||||
.arg("run")
|
||||
.arg("build")
|
||||
.arg("--target")
|
||||
.arg(target())
|
||||
.current_dir("enclave")
|
||||
.env("CC_x86_64_fortanix_unknown_sgx", "clang")
|
||||
.env(
|
||||
"CFLAGS_x86_64_fortanix_unknown_sgx",
|
||||
"-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening",
|
||||
)
|
||||
.env("CXX_x86_64_fortanix_unknown_sgx", "clang++")
|
||||
.env(
|
||||
"CXXFLAGS_x86_64_fortanix_unknown_sgx",
|
||||
"-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening",
|
||||
)
|
||||
.run();
|
||||
set_current_dir(&main_dir);
|
||||
// Rust has various ways of adding code to a binary:
|
||||
|
||||
// Rust has several ways of including machine code into a binary:
|
||||
//
|
||||
// - Rust code
|
||||
// - Inline assembly
|
||||
// - Global assembly
|
||||
// - C/C++ code compiled as part of Rust crates
|
||||
// For those different kinds, we do have very small code examples that should be
|
||||
// mitigated in some way. Mostly we check that ret instructions should no longer be present.
|
||||
//
|
||||
// For each of those, check that the mitigations are applied. Mostly we check
|
||||
// that ret instructions are no longer present.
|
||||
|
||||
// Check that normal rust code has the right mitigations.
|
||||
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 that rust global assembly has the right mitigations.
|
||||
check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks");
|
||||
|
||||
// Check that C code compiled using the `cc` crate has the right mitigations.
|
||||
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("cc_plus_one_asm", "cc_plus_one_asm.checks");
|
||||
|
||||
// Check that C++ code compiled using the `cc` crate has the right mitigations.
|
||||
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_c_global_asm", "cmake_plus_one_c_global_asm.checks");
|
||||
@@ -71,8 +85,7 @@ fn check(func_re: &str, mut checks: &str) {
|
||||
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
|
||||
.args(&["--demangle", &format!("--disassemble-symbols={func}")])
|
||||
.run()
|
||||
.stdout_utf8();
|
||||
let dump = dump.as_bytes();
|
||||
.stdout();
|
||||
|
||||
// Unique case, must succeed at one of two possible tests.
|
||||
// This is because frame pointers are optional, and them being enabled requires
|
||||
|
||||
Reference in New Issue
Block a user