Add cross-language LLVM CFI support to the Rust compiler
This commit adds cross-language LLVM Control Flow Integrity (CFI) support to the Rust compiler by adding the `-Zsanitizer-cfi-normalize-integers` option to be used with Clang `-fsanitize-cfi-icall-normalize-integers` for normalizing integer types (see https://reviews.llvm.org/D139395). It provides 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). For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, see design document in the tracking issue #89653. Cross-language LLVM CFI can be enabled with -Zsanitizer=cfi and -Zsanitizer-cfi-normalize-integers, and requires proper (i.e., non-rustc) LTO (i.e., -Clinker-plugin-lto).
This commit is contained in:
parent
fec9adcdbc
commit
004aa15b47
70 changed files with 1384 additions and 387 deletions
|
@ -766,10 +766,30 @@ impl Session {
|
|||
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_cfi_canonical_jump_tables_disabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer_cfi_canonical_jump_tables == Some(false)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_cfi_canonical_jump_tables_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer_cfi_canonical_jump_tables == Some(true)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_cfi_generalize_pointers_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer_cfi_generalize_pointers == Some(true)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_cfi_normalize_integers_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer_cfi_normalize_integers == Some(true)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
|
||||
}
|
||||
|
||||
pub fn is_split_lto_unit_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.split_lto_unit == Some(true)
|
||||
}
|
||||
|
||||
/// Check whether this compile session and crate type use static crt.
|
||||
pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
|
||||
if !self.target.crt_static_respected {
|
||||
|
@ -1581,17 +1601,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||
sess.emit_err(errors::CannotEnableCrtStaticLinux);
|
||||
}
|
||||
|
||||
// LLVM CFI and VFE both require LTO.
|
||||
if sess.lto() != config::Lto::Fat {
|
||||
if sess.is_sanitizer_cfi_enabled() {
|
||||
sess.emit_err(errors::SanitizerCfiEnabled);
|
||||
}
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
sess.emit_err(errors::UnstableVirtualFunctionElimination);
|
||||
}
|
||||
// LLVM CFI requires LTO.
|
||||
if sess.is_sanitizer_cfi_enabled()
|
||||
&& !(sess.lto() == config::Lto::Fat
|
||||
|| sess.lto() == config::Lto::Thin
|
||||
|| sess.opts.cg.linker_plugin_lto.enabled())
|
||||
{
|
||||
sess.emit_err(errors::SanitizerCfiRequiresLto);
|
||||
}
|
||||
|
||||
// LLVM CFI and KCFI are mutually exclusive
|
||||
// LLVM CFI is incompatible with LLVM KCFI.
|
||||
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
|
||||
sess.emit_err(errors::CannotMixAndMatchSanitizers {
|
||||
first: "cfi".to_string(),
|
||||
|
@ -1599,6 +1618,43 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||
});
|
||||
}
|
||||
|
||||
// Canonical jump tables requires CFI.
|
||||
if sess.is_sanitizer_cfi_canonical_jump_tables_disabled() {
|
||||
if !sess.is_sanitizer_cfi_enabled() {
|
||||
sess.emit_err(errors::SanitizerCfiCanonicalJumpTablesRequiresCfi);
|
||||
}
|
||||
}
|
||||
|
||||
// LLVM CFI pointer generalization requires CFI or KCFI.
|
||||
if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
|
||||
if !(sess.is_sanitizer_cfi_enabled() || sess.is_sanitizer_kcfi_enabled()) {
|
||||
sess.emit_err(errors::SanitizerCfiGeneralizePointersRequiresCfi);
|
||||
}
|
||||
}
|
||||
|
||||
// LLVM CFI integer normalization requires CFI or KCFI.
|
||||
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
|
||||
if !(sess.is_sanitizer_cfi_enabled() || sess.is_sanitizer_kcfi_enabled()) {
|
||||
sess.emit_err(errors::SanitizerCfiNormalizeIntegersRequiresCfi);
|
||||
}
|
||||
}
|
||||
|
||||
// LTO unit splitting requires LTO.
|
||||
if sess.is_split_lto_unit_enabled()
|
||||
&& !(sess.lto() == config::Lto::Fat
|
||||
|| sess.lto() == config::Lto::Thin
|
||||
|| sess.opts.cg.linker_plugin_lto.enabled())
|
||||
{
|
||||
sess.emit_err(errors::SplitLtoUnitRequiresLto);
|
||||
}
|
||||
|
||||
// VFE requires LTO.
|
||||
if sess.lto() != config::Lto::Fat {
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
sess.emit_err(errors::UnstableVirtualFunctionElimination);
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
|
||||
if !sess.target.options.supports_stack_protector {
|
||||
sess.emit_warning(errors::StackProtectorNotSupportedForTarget {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue