Skip to content

Commit

Permalink
Add missing module flags for CFI and KCFI sanitizers
Browse files Browse the repository at this point in the history
Set the cfi-normalize-integers and kcfi-offset module flags when
Control-Flow Integrity sanitizers are used, so functions generated by
the LLVM backend use the same CFI/KCFI options as rustc.

cfi-normalize-integers tells LLVM to also use integer normalization
for generated functions when -Zsanitizer-cfi-normalize-integers is
used.

kcfi-offset specifies the number of prefix nops between the KCFI
type hash and the function entry when -Z patchable-function-entry is
used. Note that LLVM assumes all indirectly callable functions use the
same number of prefix NOPs with -Zsanitizer=kcfi.
  • Loading branch information
samitolvanen committed Aug 21, 2024
1 parent 6b678c5 commit 40f1d9d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
31 changes: 31 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
Expand Down Expand Up @@ -226,6 +227,20 @@ pub unsafe fn create_module<'ll>(
}
}

// If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
// See https://github.com/llvm/llvm-project/pull/104826
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr().cast();
unsafe {
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
cfi_normalize_integers,
1,
);
}
}

// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr();
Expand All @@ -245,6 +260,22 @@ pub unsafe fn create_module<'ll>(
unsafe {
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
}

// Add "kcfi-offset" module flag with -Z patchable-function-entry (See
// https://reviews.llvm.org/D141172).
let pfe =
PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
if pfe.prefix() > 0 {
let kcfi_offset = c"kcfi-offset".as_ptr().cast();
unsafe {
llvm::LLVMRustAddModuleFlagU32(
llmod,
llvm::LLVMModFlagBehavior::Override,
kcfi_offset,
pfe.prefix().into(),
);
}
}
}

// Control Flow Guard is currently only supported by the MSVC linker on Windows.
Expand Down
10 changes: 10 additions & 0 deletions tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Verifies that "cfi-normalize-integers" module flag is added.
//
//@ needs-sanitizer-cfi
//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers

#![crate_type = "lib"]

pub fn foo() {}

// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1}
21 changes: 21 additions & 0 deletions tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Verifies that "cfi-normalize-integers" module flag is added.
//
//@ revisions: aarch64 x86_64
//@ [aarch64] compile-flags: --target aarch64-unknown-none
//@ [aarch64] needs-llvm-components: aarch64
//@ [x86_64] compile-flags: --target x86_64-unknown-none
//@ [x86_64] needs-llvm-components: x86
//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers

#![feature(no_core, lang_items)]
#![crate_type = "lib"]
#![no_core]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

pub fn foo() {}

// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1}
21 changes: 21 additions & 0 deletions tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Verifies that "kcfi-offset" module flag is added.
//
//@ revisions: aarch64 x86_64
//@ [aarch64] compile-flags: --target aarch64-unknown-none
//@ [aarch64] needs-llvm-components: aarch64
//@ [x86_64] compile-flags: --target x86_64-unknown-none
//@ [x86_64] needs-llvm-components: x86
//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Z patchable-function-entry=4,3

#![feature(no_core, lang_items, patchable_function_entry)]
#![crate_type = "lib"]
#![no_core]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

pub fn foo() {}

// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-offset", i32 3}

0 comments on commit 40f1d9d

Please sign in to comment.