Auto merge of #95548 - rcvalle:rust-cfi-2, r=nagisa
Add fine-grained LLVM CFI support to the Rust compiler This PR improves the LLVM Control Flow Integrity (CFI) support in the Rust compiler by providing forward-edge control flow protection for Rust-compiled code only by aggregating function pointers in groups identified by their return and parameter types. 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 identifying C char and integer type uses at the time types are encoded (see Type metadata in the design document in the tracking issue https://github.com/rust-lang/rust/issues/89653). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). Thank you again, `@eddyb,` `@nagisa,` `@pcc,` and `@tmiasko` for all the help!
This commit is contained in:
commit
db8086eb60
25 changed files with 1731 additions and 164 deletions
|
@ -18,7 +18,6 @@ rustc_middle = { path = "../rustc_middle" }
|
|||
rustc-demangle = "0.1.21"
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||
|
@ -30,6 +29,7 @@ rustc_metadata = { path = "../rustc_metadata" }
|
|||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
|
|
|
@ -626,32 +626,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn type_metadata(&mut self, function: &'ll Value, typeid: String) {
|
||||
let typeid_metadata = self.typeid_metadata(typeid);
|
||||
let v = [self.const_usize(0), typeid_metadata];
|
||||
unsafe {
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
function,
|
||||
llvm::MD_type as c_uint,
|
||||
llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
|
||||
self.cx.llcx,
|
||||
v.as_ptr(),
|
||||
v.len() as c_uint,
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn typeid_metadata(&mut self, typeid: String) -> Self::Value {
|
||||
unsafe {
|
||||
llvm::LLVMMDStringInContext(
|
||||
self.cx.llcx,
|
||||
typeid.as_ptr() as *const c_char,
|
||||
typeid.as_bytes().len() as c_uint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
|
||||
self.store_with_flags(val, ptr, align, MemFlags::empty())
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ use crate::llvm;
|
|||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
use rustc_codegen_ssa::traits::TypeMembershipMethods;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
|
||||
use smallvec::SmallVec;
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -97,6 +99,12 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
fn_abi.llvm_type(self),
|
||||
);
|
||||
fn_abi.apply_attrs_llfn(self, llfn);
|
||||
|
||||
if self.tcx.sess.is_sanitizer_cfi_enabled() {
|
||||
let typeid = typeid_for_fnabi(self.tcx, fn_abi);
|
||||
self.set_type_metadata(llfn, typeid);
|
||||
}
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use rustc_target::abi::{AddressSpace, Align, Integer, Size};
|
|||
use std::fmt;
|
||||
use std::ptr;
|
||||
|
||||
use libc::c_uint;
|
||||
use libc::{c_char, c_uint};
|
||||
|
||||
impl PartialEq for Type {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
@ -289,3 +289,31 @@ impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
ty.llvm_type(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn set_type_metadata(&self, function: &'ll Value, typeid: String) {
|
||||
let typeid_metadata = self.typeid_metadata(typeid);
|
||||
let v = [self.const_usize(0), typeid_metadata];
|
||||
unsafe {
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
function,
|
||||
llvm::MD_type as c_uint,
|
||||
llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
|
||||
self.llcx,
|
||||
v.as_ptr(),
|
||||
v.len() as c_uint,
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn typeid_metadata(&self, typeid: String) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMMDStringInContext(
|
||||
self.llcx,
|
||||
typeid.as_ptr() as *const c_char,
|
||||
typeid.len() as c_uint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue