mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-14 04:56:49 +00:00
KCFI: Add KCFI arity indicator support
Adds KCFI arity indicator support to the Rust compiler (see rust-lang/rust#138311, https://github.com/llvm/llvm-project/pull/121070, and https://lore.kernel.org/lkml/CANiq72=3ghFxy8E=AU9p+0imFxKr5iU3sd0hVUXed5BA+KjdNQ@mail.gmail.com/).
This commit is contained in:
parent
bad13a970a
commit
a98546b961
@ -56,6 +56,8 @@ codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO
|
||||
codegen_llvm_run_passes = failed to run LLVM passes
|
||||
codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
|
||||
|
||||
codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0 = `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.
|
||||
|
||||
codegen_llvm_sanitizer_memtag_requires_mte =
|
||||
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
|
||||
|
||||
|
@ -327,6 +327,22 @@ pub(crate) unsafe fn create_module<'ll>(
|
||||
pfe.prefix().into(),
|
||||
);
|
||||
}
|
||||
|
||||
// Add "kcfi-arity" module flag if KCFI arity indicator is enabled. (See
|
||||
// https://github.com/llvm/llvm-project/pull/117121.)
|
||||
if sess.is_sanitizer_kcfi_arity_enabled() {
|
||||
// KCFI arity indicator requires LLVM 21.0.0 or later.
|
||||
if llvm_version < (21, 0, 0) {
|
||||
tcx.dcx().emit_err(crate::errors::SanitizerKcfiArityRequiresLLVM2100);
|
||||
}
|
||||
|
||||
llvm::add_module_flag_u32(
|
||||
llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Override,
|
||||
"kcfi-arity",
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by MSVC and LLVM on Windows.
|
||||
|
@ -217,3 +217,7 @@ pub(crate) struct MismatchedDataLayout<'a> {
|
||||
pub(crate) struct FixedX18InvalidArch<'a> {
|
||||
pub arch: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0)]
|
||||
pub(crate) struct SanitizerKcfiArityRequiresLLVM2100;
|
||||
|
@ -853,6 +853,7 @@ fn test_unstable_options_tracking_hash() {
|
||||
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
|
||||
tracked!(sanitizer_cfi_normalize_integers, Some(true));
|
||||
tracked!(sanitizer_dataflow_abilist, vec![String::from("/rustc/abc")]);
|
||||
tracked!(sanitizer_kcfi_arity, Some(true));
|
||||
tracked!(sanitizer_memory_track_origins, 2);
|
||||
tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
|
||||
tracked!(saturating_float_casts, Some(true));
|
||||
|
@ -94,6 +94,8 @@ session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Cli
|
||||
|
||||
session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
|
||||
|
||||
session_sanitizer_kcfi_arity_requires_kcfi = `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`
|
||||
|
||||
session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort`
|
||||
|
||||
session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
|
||||
|
@ -147,6 +147,10 @@ pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi;
|
||||
#[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)]
|
||||
pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_sanitizer_kcfi_arity_requires_kcfi)]
|
||||
pub(crate) struct SanitizerKcfiArityRequiresKcfi;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_sanitizer_kcfi_requires_panic_abort)]
|
||||
pub(crate) struct SanitizerKcfiRequiresPanicAbort;
|
||||
|
@ -2443,6 +2443,8 @@ written to standard error output)"),
|
||||
"enable normalizing integer types (default: no)"),
|
||||
sanitizer_dataflow_abilist: Vec<String> = (Vec::new(), parse_comma_list, [TRACKED],
|
||||
"additional ABI list files that control how shadow parameters are passed (comma separated)"),
|
||||
sanitizer_kcfi_arity: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable KCFI arity indicator (default: no)"),
|
||||
sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED],
|
||||
"enable origins tracking in MemorySanitizer"),
|
||||
sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
|
||||
|
@ -381,6 +381,10 @@ impl Session {
|
||||
self.opts.unstable_opts.sanitizer_cfi_normalize_integers == Some(true)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_kcfi_arity_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer_kcfi_arity == Some(true)
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
|
||||
}
|
||||
@ -1211,6 +1215,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||
}
|
||||
}
|
||||
|
||||
// KCFI arity indicator requires KCFI.
|
||||
if sess.is_sanitizer_kcfi_arity_enabled() && !sess.is_sanitizer_kcfi_enabled() {
|
||||
sess.dcx().emit_err(errors::SanitizerKcfiArityRequiresKcfi);
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
|
61
tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
Normal file
61
tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
Normal file
@ -0,0 +1,61 @@
|
||||
// Verifies that KCFI arity indicator is emitted.
|
||||
//
|
||||
//@ add-core-stubs
|
||||
//@ revisions: x86_64
|
||||
//@ assembly-output: emit-asm
|
||||
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -Cllvm-args=-x86-asm-syntax=intel -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity -Copt-level=0
|
||||
//@ [x86_64] needs-llvm-components: x86
|
||||
//@ min-llvm-version: 21.0.0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub fn add_one(x: i32) -> i32 {
|
||||
// CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}:
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: mov ecx, 2628068948
|
||||
x + 1
|
||||
}
|
||||
|
||||
pub fn add_two(x: i32, _y: i32) -> i32 {
|
||||
// CHECK-LABEL: __cfi__{{.*}}7add_two{{.*}}:
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: mov edx, 2505940310
|
||||
x + 2
|
||||
}
|
||||
|
||||
pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
|
||||
// CHECK-LABEL: __cfi__{{.*}}8do_twice{{.*}}:
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: mov edx, 653723426
|
||||
f(arg) + f(arg)
|
||||
}
|
19
tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs
Normal file
19
tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Verifies that "kcfi-arity" module flag is added.
|
||||
//
|
||||
//@ add-core-stubs
|
||||
//@ revisions: x86_64
|
||||
//@ [x86_64] compile-flags: --target x86_64-unknown-none
|
||||
//@ [x86_64] needs-llvm-components: x86
|
||||
//@ compile-flags: -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity
|
||||
//@ min-llvm-version: 21.0.0
|
||||
|
||||
#![feature(no_core, lang_items)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
pub fn foo() {}
|
||||
|
||||
// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-arity", i32 1}
|
9
tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs
Normal file
9
tests/ui/sanitizer/kcfi-arity-requires-kcfi.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// Verifies that `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`.
|
||||
//
|
||||
//@ needs-sanitizer-kcfi
|
||||
//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-kcfi-arity
|
||||
|
||||
//~? ERROR `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
#![no_main]
|
4
tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr
Normal file
4
tests/ui/sanitizer/kcfi-arity-requires-kcfi.stderr
Normal file
@ -0,0 +1,4 @@
|
||||
error: `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
11
tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs
Normal file
11
tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Verifies that `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.
|
||||
//
|
||||
//@ needs-sanitizer-kcfi
|
||||
//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity
|
||||
//@ build-fail
|
||||
//@ max-llvm-major-version: 20
|
||||
|
||||
//~? ERROR `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
#![no_main]
|
@ -0,0 +1,4 @@
|
||||
error: `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
Loading…
Reference in New Issue
Block a user