diff options
| author | bors <bors@rust-lang.org> | 2021-10-27 09:19:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-10-27 09:19:42 +0000 |
| commit | a8f6e614f86be429b5862f30e023063f619aeed2 (patch) | |
| tree | 329266e75828737d5cd8f66a7b27bb02379f9308 /compiler/rustc_codegen_ssa/src/mir | |
| parent | 47aeac648ed56095688c1c20972c9b72bd0da7ce (diff) | |
| parent | c5708caf6a858b76b5519f81d2061ef85d9976b6 (diff) | |
| download | rust-a8f6e614f86be429b5862f30e023063f619aeed2.tar.gz rust-a8f6e614f86be429b5862f30e023063f619aeed2.zip | |
Auto merge of #89652 - rcvalle:rust-cfi, r=nagisa
Add LLVM CFI support to the Rust compiler This PR adds LLVM Control Flow Integrity (CFI) support to the Rust compiler. It initially provides forward-edge control flow protection for Rust-compiled code only by aggregating function pointers in groups identified by their number of arguments. Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed binaries" (i.e., for when C or C++ and Rust -compiled code share the same virtual address space) will be provided in later work as part of this project by defining and using compatible type identifiers (see Type metadata in the design document in the tracking issue #89653). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). Thank you, `@eddyb` and `@pcc,` for all the help!
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/mod.rs | 8 |
2 files changed, 43 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 7c25438380a..297dcde99b3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; +use rustc_symbol_mangling::typeid_for_fnabi; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -818,12 +819,43 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(&mut bx, location, &mut llargs, last_arg); } - let fn_ptr = match (llfn, instance) { - (Some(llfn), _) => llfn, - (None, Some(instance)) => bx.get_fn_addr(instance), + let (is_indirect_call, fn_ptr) = match (llfn, instance) { + (Some(llfn), _) => (true, llfn), + (None, Some(instance)) => (false, bx.get_fn_addr(instance)), _ => span_bug!(span, "no llfn for call"), }; + // For backends that support CFI using type membership (i.e., testing whether a given + // pointer is associated with a type identifier). + if bx.tcx().sess.is_sanitizer_cfi_enabled() && is_indirect_call { + // Emit type metadata and checks. + // FIXME(rcvalle): Add support for generalized identifiers. + // FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers. + let typeid = typeid_for_fnabi(bx.tcx(), fn_abi); + let typeid_metadata = bx.typeid_metadata(typeid.clone()); + + // Test whether the function pointer is associated with the type identifier. + let cond = bx.type_test(fn_ptr, typeid_metadata); + let mut bx_pass = bx.build_sibling_block("type_test.pass"); + let mut bx_fail = bx.build_sibling_block("type_test.fail"); + bx.cond_br(cond, bx_pass.llbb(), bx_fail.llbb()); + + helper.do_call( + self, + &mut bx_pass, + fn_abi, + fn_ptr, + &llargs, + destination.as_ref().map(|&(_, target)| (ret_dest, target)), + cleanup, + ); + + bx_fail.abort(); + bx_fail.unreachable(); + + return; + } + helper.do_call( self, &mut bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 476ddbd9398..1cd400eecfb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -4,6 +4,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; +use rustc_symbol_mangling::typeid_for_fnabi; use rustc_target::abi::call::{FnAbi, PassMode}; use std::iter; @@ -244,6 +245,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( for (bb, _) in traversal::reverse_postorder(&mir) { fx.codegen_block(bb); } + + // For backends that support CFI using type membership (i.e., testing whether a given pointer + // is associated with a type identifier). + if cx.tcx().sess.is_sanitizer_cfi_enabled() { + let typeid = typeid_for_fnabi(cx.tcx(), fn_abi); + bx.type_metadata(llfn, typeid.clone()); + } } /// Produces, for each argument, a `Value` pointing at the |
