diff options
| author | Ramon de C Valle <rcvalle@users.noreply.github.com> | 2024-02-01 13:16:30 -0800 |
|---|---|---|
| committer | Ramon de C Valle <rcvalle@users.noreply.github.com> | 2024-03-01 18:50:40 -0800 |
| commit | dee4e02102197adc29be9bf98083297dd3f5e2ed (patch) | |
| tree | 510d1bc6652086782ea25e69a0a0b2a985f623aa /compiler | |
| parent | eaee1e9453bfb4e1fb3753aa37450bb47cd7629d (diff) | |
| download | rust-dee4e02102197adc29be9bf98083297dd3f5e2ed.tar.gz rust-dee4e02102197adc29be9bf98083297dd3f5e2ed.zip | |
Add initial support for DataFlowSanitizer
Adds initial support for DataFlowSanitizer to the Rust compiler. It currently supports `-Zsanitizer-dataflow-abilist`. Additional options for it can be passed to LLVM command line argument processor via LLVM arguments using `llvm-args` codegen option (e.g., `-Cllvm-args=-dfsan-combine-pointer-labels-on-load=false`).
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/back/write.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 16 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs | 1 |
9 files changed, 60 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 08aab849868..031bbd63361 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -519,12 +519,22 @@ pub(crate) unsafe fn llvm_optimize( let pgo_sample_use_path = get_pgo_sample_use_path(config); let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO; let instr_profile_output_path = get_instr_profile_output_path(config); + let sanitize_dataflow_abilist: Vec<_> = config + .sanitizer_dataflow_abilist + .iter() + .map(|file| CString::new(file.as_str()).unwrap()) + .collect(); + let sanitize_dataflow_abilist_ptrs: Vec<_> = + sanitize_dataflow_abilist.iter().map(|file| file.as_ptr()).collect(); // Sanitizer instrumentation is only inserted during the pre-link optimization stage. let sanitizer_options = if !is_lto { Some(llvm::SanitizerOptions { sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS), sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS), sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI), + sanitize_dataflow: config.sanitizer.contains(SanitizerSet::DATAFLOW), + sanitize_dataflow_abilist: sanitize_dataflow_abilist_ptrs.as_ptr(), + sanitize_dataflow_abilist_len: sanitize_dataflow_abilist_ptrs.len(), sanitize_kcfi: config.sanitizer.contains(SanitizerSet::KCFI), sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY), sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3c20b579349..f4e83330874 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -480,6 +480,9 @@ pub struct SanitizerOptions { pub sanitize_address: bool, pub sanitize_address_recover: bool, pub sanitize_cfi: bool, + pub sanitize_dataflow: bool, + pub sanitize_dataflow_abilist: *const *const c_char, + pub sanitize_dataflow_abilist_len: size_t, pub sanitize_kcfi: bool, pub sanitize_memory: bool, pub sanitize_memory_recover: bool, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 0c77f7c51bc..fcb3602b734 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1221,6 +1221,9 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::ADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "asan"); } + if sanitizer.contains(SanitizerSet::DATAFLOW) { + link_sanitizer_runtime(sess, flavor, linker, "dfsan"); + } if sanitizer.contains(SanitizerSet::LEAK) { link_sanitizer_runtime(sess, flavor, linker, "lsan"); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 97089dff31b..60865d06ab9 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -95,6 +95,7 @@ pub struct ModuleConfig { pub sanitizer: SanitizerSet, pub sanitizer_recover: SanitizerSet, + pub sanitizer_dataflow_abilist: Vec<String>, pub sanitizer_memory_track_origins: usize, // Flags indicating which outputs to produce. @@ -197,6 +198,10 @@ impl ModuleConfig { ), sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()), + sanitizer_dataflow_abilist: if_regular!( + sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(), + Vec::new() + ), sanitizer_recover: if_regular!( sess.opts.unstable_opts.sanitizer_recover, SanitizerSet::empty() diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 112553b2f70..5e1fc248b80 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -811,6 +811,7 @@ fn test_unstable_options_tracking_hash() { tracked!(sanitizer_cfi_canonical_jump_tables, None); 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_memory_track_origins, 2); tracked!(sanitizer_recover, SanitizerSet::ADDRESS); tracked!(saturating_float_casts, Some(true)); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 5b1cc52f1f6..4ec784e2590 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -42,6 +42,7 @@ #endif #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" +#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h" #include "llvm/Support/TimeProfiler.h" #if LLVM_VERSION_GE(19, 0) #include "llvm/Support/PGOOptions.h" @@ -686,6 +687,9 @@ struct LLVMRustSanitizerOptions { bool SanitizeAddress; bool SanitizeAddressRecover; bool SanitizeCFI; + bool SanitizeDataFlow; + char **SanitizeDataFlowABIList; + size_t SanitizeDataFlowABIListLen; bool SanitizeKCFI; bool SanitizeMemory; bool SanitizeMemoryRecover; @@ -883,6 +887,18 @@ LLVMRustOptimize( } if (SanitizerOptions) { + if (SanitizerOptions->SanitizeDataFlow) { + std::vector<std::string> ABIListFiles( + SanitizerOptions->SanitizeDataFlowABIList, + SanitizerOptions->SanitizeDataFlowABIList + + SanitizerOptions->SanitizeDataFlowABIListLen); + OptimizerLastEPCallbacks.push_back( + [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(DataFlowSanitizerPass(ABIListFiles)); + } + ); + } + if (SanitizerOptions->SanitizeMemory) { MemorySanitizerOptions Options( SanitizerOptions->SanitizeMemoryTrackOrigins, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 743f4760339..42c9d5e10eb 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -371,7 +371,8 @@ mod desc { pub const parse_list: &str = "a space-separated list of strings"; pub const parse_list_with_polarity: &str = "a comma-separated list of strings, with elements beginning with + or -"; - pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; + pub const parse_comma_list: &str = "a comma-separated list of strings"; + pub const parse_opt_comma_list: &str = parse_comma_list; pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; pub const parse_threads: &str = parse_number; @@ -381,7 +382,7 @@ mod desc { pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_oom_strategy: &str = "either `panic` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`"; + pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`"; pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -602,6 +603,18 @@ mod parse { } } + pub(crate) fn parse_comma_list(slot: &mut Vec<String>, v: Option<&str>) -> bool { + match v { + Some(s) => { + let mut v: Vec<_> = s.split(',').map(|s| s.to_string()).collect(); + v.sort_unstable(); + *slot = v; + true + } + None => false, + } + } + pub(crate) fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>) -> bool { match v { Some(s) => { @@ -718,6 +731,7 @@ mod parse { *slot |= match s { "address" => SanitizerSet::ADDRESS, "cfi" => SanitizerSet::CFI, + "dataflow" => SanitizerSet::DATAFLOW, "kcfi" => SanitizerSet::KCFI, "kernel-address" => SanitizerSet::KERNELADDRESS, "leak" => SanitizerSet::LEAK, @@ -1846,6 +1860,8 @@ written to standard error output)"), "enable generalizing pointer types (default: no)"), sanitizer_cfi_normalize_integers: Option<bool> = (None, parse_opt_bool, [TRACKED], "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_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED], "enable origins tracking in MemorySanitizer"), sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 651d5632277..9f68e3602a0 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1221,6 +1221,7 @@ bitflags::bitflags! { const KCFI = 1 << 8; const KERNELADDRESS = 1 << 9; const SAFESTACK = 1 << 10; + const DATAFLOW = 1 << 11; } } rustc_data_structures::external_bitflags_debug! { SanitizerSet } @@ -1233,6 +1234,7 @@ impl SanitizerSet { Some(match self { SanitizerSet::ADDRESS => "address", SanitizerSet::CFI => "cfi", + SanitizerSet::DATAFLOW => "dataflow", SanitizerSet::KCFI => "kcfi", SanitizerSet::KERNELADDRESS => "kernel-address", SanitizerSet::LEAK => "leak", @@ -2790,6 +2792,7 @@ impl Target { base.$key_name |= match s.as_str() { Some("address") => SanitizerSet::ADDRESS, Some("cfi") => SanitizerSet::CFI, + Some("dataflow") => SanitizerSet::DATAFLOW, Some("kcfi") => SanitizerSet::KCFI, Some("kernel-address") => SanitizerSet::KERNELADDRESS, Some("leak") => SanitizerSet::LEAK, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 2296b58f45d..1510f3b390c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -10,6 +10,7 @@ pub fn target() -> Target { base.static_position_independent_executables = true; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI + | SanitizerSet::DATAFLOW | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::SAFESTACK |
