diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 485307622291e..45587befcea66 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -587,6 +587,7 @@ impl SingleAttributeParser for SanitizeParser { r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, + r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, @@ -654,7 +655,9 @@ impl SingleAttributeParser for SanitizeParser { Some(sym::memtag) => apply(SanitizerSet::MEMTAG), Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK), Some(sym::thread) => apply(SanitizerSet::THREAD), - Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS), + Some(sym::hwaddress) | Some(sym::kernel_hwaddress) => { + apply(SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS) + } Some(sym::realtime) => match value.value_as_str() { Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking), Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking), @@ -678,6 +681,8 @@ impl SingleAttributeParser for SanitizeParser { sym::shadow_call_stack, sym::thread, sym::hwaddress, + sym::kernel_address, + sym::kernel_hwaddress, sym::realtime, ], ); diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 546fa87ff5612..01af9f243ab2e 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -120,7 +120,8 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( if enabled.contains(SanitizerSet::THREAD) { attrs.push(llvm::AttributeKind::SanitizeThread.create_attr(cx.llcx)); } - if enabled.contains(SanitizerSet::HWADDRESS) { + if enabled.contains(SanitizerSet::HWADDRESS) || enabled.contains(SanitizerSet::KERNELHWADDRESS) + { attrs.push(llvm::AttributeKind::SanitizeHWAddress.create_attr(cx.llcx)); } if enabled.contains(SanitizerSet::SHADOWCALLSTACK) { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index d7ab1356fafe7..4427613de588d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -652,6 +652,10 @@ pub(crate) unsafe fn llvm_optimize( sanitize_kernel_address_recover: config .sanitizer_recover .contains(SanitizerSet::KERNELADDRESS), + sanitize_kernel_hwaddress: config.sanitizer.contains(SanitizerSet::KERNELHWADDRESS), + sanitize_kernel_hwaddress_recover: config + .sanitizer_recover + .contains(SanitizerSet::KERNELHWADDRESS), }) } else { None diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index d00e70638b45a..2276809477121 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -210,10 +210,14 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { } pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) { - if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) + || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELADDRESS) + { unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) }; } - if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) + || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELHWADDRESS) + { unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) }; } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index f9af42494cada..751e5c0eed689 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -464,6 +464,8 @@ pub(crate) struct SanitizerOptions { pub sanitize_hwaddress_recover: bool, pub sanitize_kernel_address: bool, pub sanitize_kernel_address_recover: bool, + pub sanitize_kernel_hwaddress: bool, + pub sanitize_kernel_hwaddress_recover: bool, } /// LLVMRustRelocModel diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 388503c720532..a54a34f95b886 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1235,6 +1235,7 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::LEAK) && !sanitizer.contains(SanitizerSet::ADDRESS) && !sanitizer.contains(SanitizerSet::HWADDRESS) + && !sanitizer.contains(SanitizerSet::KERNELHWADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "lsan"); } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index db8f459ef0451..116772b051b15 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -778,7 +778,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ DuplicatesOk, EncodeCrossCrate::No, effective_target_features, experimental!(force_target_feature) ), gated!( - sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding, + sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding, EncodeCrossCrate::No, sanitize, experimental!(sanitize), ), gated!( diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 568335f7dcb51..f928cba968c2a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -544,6 +544,8 @@ struct LLVMRustSanitizerOptions { bool SanitizeHWAddressRecover; bool SanitizeKernelAddress; bool SanitizeKernelAddressRecover; + bool SanitizeKernelHWAddress; + bool SanitizeKernelHWAddressRecover; }; extern "C" typedef void (*registerEnzymeAndPassPipelineFn)( @@ -775,13 +777,15 @@ extern "C" LLVMRustResult LLVMRustOptimize( !TM->getTargetTriple().isOSWindows())); }); } - if (SanitizerOptions->SanitizeHWAddress) { + if (SanitizerOptions->SanitizeHWAddress || + SanitizerOptions->SanitizeKernelHWAddress) { OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase phase) { HWAddressSanitizerOptions opts( - /*CompileKernel=*/false, - SanitizerOptions->SanitizeHWAddressRecover, + SanitizerOptions->SanitizeKernelHWAddress, + SanitizerOptions->SanitizeHWAddressRecover || + SanitizerOptions->SanitizeKernelHWAddressRecover, /*DisableOptimization=*/false); MPM.addPass(HWAddressSanitizerPass(opts)); }); diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index cd0556de5c22c..f73a9bcfd93c5 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -229,6 +229,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { if s == SanitizerSet::KERNELADDRESS { s = SanitizerSet::ADDRESS; } + // KHWASAN is still HWASAN under the hood, so it uses the same attribute. + if s == SanitizerSet::KERNELHWADDRESS { + s = SanitizerSet::HWADDRESS; + } ins_str!(sym::sanitize, &s.to_string()); } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c2de098c68e8d..25b8d16afb78b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -106,6 +106,7 @@ mod target_modifier_consistency_check { | SanitizerSet::SHADOWCALLSTACK | SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS | SanitizerSet::SAFESTACK | SanitizerSet::DATAFLOW; @@ -810,7 +811,7 @@ mod desc { pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; + pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub(crate) const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -1252,6 +1253,7 @@ pub mod parse { "dataflow" => SanitizerSet::DATAFLOW, "kcfi" => SanitizerSet::KCFI, "kernel-address" => SanitizerSet::KERNELADDRESS, + "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "memtag" => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index dc18b05c75763..a018c1b825366 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -521,10 +521,10 @@ impl Session { /// Checks if LLVM lifetime markers should be emitted. pub fn emit_lifetime_markers(&self) -> bool { self.opts.optimize != config::OptLevel::No - // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. + // AddressSanitizer, KernelAddressSanitizer and KernelHWAddressSanitizer use lifetimes to detect use after scope bugs. // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. - || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) + || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::KERNELHWADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) } pub fn diagnostic_width(&self) -> usize { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f87189b4de42c..07ff2325644a9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1112,6 +1112,7 @@ symbols! { iterator_collect_fn, kcfi, kernel_address, + kernel_hwaddress, keylocker_x86, keyword, kind, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d9c872c9b4352..76917d7624813 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1175,9 +1175,10 @@ bitflags::bitflags! { const SHADOWCALLSTACK = 1 << 7; const KCFI = 1 << 8; const KERNELADDRESS = 1 << 9; - const SAFESTACK = 1 << 10; - const DATAFLOW = 1 << 11; - const REALTIME = 1 << 12; + const KERNELHWADDRESS = 1 << 10; + const SAFESTACK = 1 << 11; + const DATAFLOW = 1 << 12; + const REALTIME = 1 << 13; } } rustc_data_structures::external_bitflags_debug! { SanitizerSet } @@ -1191,24 +1192,32 @@ impl SanitizerSet { (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS), (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG), (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS), + (SanitizerSet::ADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK), (SanitizerSet::LEAK, SanitizerSet::MEMORY), (SanitizerSet::LEAK, SanitizerSet::THREAD), (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS), + (SanitizerSet::LEAK, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::LEAK, SanitizerSet::SAFESTACK), (SanitizerSet::MEMORY, SanitizerSet::THREAD), (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS), (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS), + (SanitizerSet::MEMORY, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK), (SanitizerSet::THREAD, SanitizerSet::HWADDRESS), (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS), + (SanitizerSet::THREAD, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::THREAD, SanitizerSet::SAFESTACK), (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG), (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS), + (SanitizerSet::HWADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK), (SanitizerSet::CFI, SanitizerSet::KCFI), (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS), + (SanitizerSet::MEMTAG, SanitizerSet::KERNELHWADDRESS), + (SanitizerSet::KERNELADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK), + (SanitizerSet::KERNELHWADDRESS, SanitizerSet::SAFESTACK), ]; /// Return sanitizer's name @@ -1221,6 +1230,7 @@ impl SanitizerSet { SanitizerSet::DATAFLOW => "dataflow", SanitizerSet::KCFI => "kcfi", SanitizerSet::KERNELADDRESS => "kernel-address", + SanitizerSet::KERNELHWADDRESS => "kernel-hwaddress", SanitizerSet::LEAK => "leak", SanitizerSet::MEMORY => "memory", SanitizerSet::MEMTAG => "memtag", @@ -1266,6 +1276,7 @@ impl FromStr for SanitizerSet { "dataflow" => SanitizerSet::DATAFLOW, "kcfi" => SanitizerSet::KCFI, "kernel-address" => SanitizerSet::KERNELADDRESS, + "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "memtag" => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs index 07512c01dc4a8..13a52f88de892 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs @@ -21,7 +21,10 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, endian: Endian::Big, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index 1c166030d5e5d..ab34cf3001de5 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -21,7 +21,10 @@ pub(crate) fn target() -> Target { &["--fix-cortex-a53-843419"], ), features: "+v8a,+strict-align,+neon".into(), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index ad444c139bff6..89ef53b43862b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -20,7 +20,10 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, default_uwtable: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs index 19b7ebe036747..ef21440c320a8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs @@ -21,7 +21,10 @@ pub(crate) fn target() -> Target { &["--fix-cortex-a53-843419"], ), features: "+v8a,+strict-align,+neon".into(), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs index 8f8bbb4a41caf..96a782fe0ac04 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs @@ -8,7 +8,10 @@ pub(crate) fn target() -> Target { // based off the aarch64-unknown-none target at time of addition linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs index 63f518873c609..f90a3d27266a1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs @@ -11,7 +11,10 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::HWADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, default_uwtable: true, diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 54c0f2ec74309..cd67f0a29b094 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -168,6 +168,7 @@ pub enum Sanitizer { Dataflow, Kcfi, KernelAddress, + KernelHwaddress, Leak, Memory, Memtag, diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 230578d79ffbe..8c62249e58fda 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -175,7 +175,9 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-cfi", "needs-sanitizer-dataflow", "needs-sanitizer-hwaddress", + "needs-sanitizer-kasan", "needs-sanitizer-kcfi", + "needs-sanitizer-khwasan", "needs-sanitizer-leak", "needs-sanitizer-memory", "needs-sanitizer-memtag", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 168d5e9eb649b..e9f3d6c28d6ef 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -46,6 +46,11 @@ pub(super) fn handle_needs( condition: cache.sanitizer_kasan, ignore_reason: "ignored on targets without kernel address sanitizer", }, + Need { + name: "needs-sanitizer-khwasan", + condition: cache.sanitizer_khwasan, + ignore_reason: "ignored on targets without kernel hardware-assisted address sanitizer", + }, Need { name: "needs-sanitizer-leak", condition: cache.sanitizer_leak, @@ -332,6 +337,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_dataflow: bool, sanitizer_kcfi: bool, sanitizer_kasan: bool, + sanitizer_khwasan: bool, sanitizer_leak: bool, sanitizer_memory: bool, sanitizer_thread: bool, @@ -359,6 +365,7 @@ impl CachedNeedsConditions { sanitizer_dataflow: sanitizers.contains(&Sanitizer::Dataflow), sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi), sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress), + sanitizer_khwasan: sanitizers.contains(&Sanitizer::KernelHwaddress), sanitizer_leak: sanitizers.contains(&Sanitizer::Leak), sanitizer_memory: sanitizers.contains(&Sanitizer::Memory), sanitizer_thread: sanitizers.contains(&Sanitizer::Thread), diff --git a/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs new file mode 100644 index 0000000000000..e76d44e38e03a --- /dev/null +++ b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -0,0 +1,30 @@ +// Verifies that HWASAN and KHWASAN emit different assembly instrumentation on AArch64. +// +//@ add-minicore +//@ assembly-output: emit-asm +//@ revisions: hwasan khwasan +//@[hwasan] compile-flags: -Zsanitizer=hwaddress +//@[khwasan] compile-flags: -Zsanitizer=kernel-hwaddress +//@ compile-flags: --target aarch64-unknown-none -Copt-level=1 +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; + +// hwasan-LABEL: test: +// hwasan: adrp x{{[0-9]+}}, :gottprel:__hwasan_tls +// hwasan: mrs x{{[0-9]+}}, TPIDR_EL0 +// hwasan: bl __hwasan_check_x0_0_short_v2 + +// khwasan-LABEL: test: +// khwasan-NOT: __hwasan_tls +// khwasan: orr x{{[0-9]+}}, x0, #0xff00000000000000 +// khwasan: bl __hwasan_check_x0_67043328_fixed_0_short_v2 + +#[no_mangle] +pub fn test(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs new file mode 100644 index 0000000000000..eea7443c0f00b --- /dev/null +++ b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -0,0 +1,28 @@ +// Verifies that HWASAN and KHWASAN emit different instrumentation. +// +//@ add-minicore +//@ revisions: hwasan khwasan +//@[hwasan] compile-flags: -Zsanitizer=hwaddress +//@[khwasan] compile-flags: -Zsanitizer=kernel-hwaddress +//@ compile-flags: --target aarch64-unknown-none -Copt-level=0 +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(no_core, lang_items, sanitize)] +#![no_core] + +extern crate minicore; + +// hwasan-LABEL: define {{.*}} @test +// hwasan: @__hwasan_tls +// hwasan: call void @llvm.hwasan.check.memaccess.shortgranules +// hwasan: declare void @__hwasan_init() + +// khwasan-LABEL: define {{.*}} @test +// khwasan-NOT: @__hwasan_init +// khwasan: call ptr asm +// khwasan: call void @llvm.hwasan.check.memaccess.shortgranules.fixedshadow +#[no_mangle] +pub fn test(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/kasan-recover.rs b/tests/codegen-llvm/sanitizer/kasan-recover.rs new file mode 100644 index 0000000000000..8f0e6eb3a605d --- /dev/null +++ b/tests/codegen-llvm/sanitizer/kasan-recover.rs @@ -0,0 +1,33 @@ +// Verifies that KernelAddressSanitizer recovery mode can be enabled +// with -Zsanitizer-recover=kernel-address. +// +//@ add-minicore +//@ revisions: KASAN KASAN-RECOVER +//@ compile-flags: -Copt-level=0 +//@[KASAN] compile-flags: -Zsanitizer=kernel-address --target x86_64-unknown-none +//@[KASAN] needs-llvm-components: x86 +//@[KASAN-RECOVER] compile-flags: -Zsanitizer=kernel-address +//@[KASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-address --target x86_64-unknown-none +//@[KASAN-RECOVER] needs-llvm-components: x86 + +#![feature(no_core, sanitize, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// KASAN-LABEL: define{{.*}}@penguin( +// KASAN: call void @__asan_report_load4( +// KASAN: unreachable +// KASAN: } + +// KASAN-RECOVER-LABEL: define{{.*}}@penguin( +// KASAN-RECOVER: call void @__asan_report_load4_noabort( +// KASAN-RECOVER-NOT: unreachable +// KASAN-RECOVER: } + +#[no_mangle] +pub unsafe fn penguin(p: *mut i32) -> i32 { + *p +} diff --git a/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs new file mode 100644 index 0000000000000..01b129cb69207 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs @@ -0,0 +1,21 @@ +// Verifies that `-Zsanitizer=kernel-hwaddress` enables lifetime markers. + +//@ add-minicore +//@ compile-flags: -Zsanitizer=kernel-hwaddress -Copt-level=0 +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK-LABEL: ; khwasan_lifetime_markers::test +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @llvm.lifetime.end +pub fn test() { + let _x = [0u8; 10]; +} diff --git a/tests/codegen-llvm/sanitizer/khwasan-recover.rs b/tests/codegen-llvm/sanitizer/khwasan-recover.rs new file mode 100644 index 0000000000000..957b867a61ad9 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/khwasan-recover.rs @@ -0,0 +1,37 @@ +// Verifies that KernelHWAddressSanitizer recovery mode can be enabled +// with -Zsanitizer-recover=kernel-hwaddress. +// +//@ add-minicore +//@[KHWASAN] needs-llvm-components: aarch64 +//@[KHWASAN-RECOVER] needs-llvm-components: aarch64 +//@ revisions: KHWASAN KHWASAN-RECOVER +//@ no-prefer-dynamic +//@ compile-flags: -Copt-level=0 +//@[KHWASAN] compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none +//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer=kernel-hwaddress +//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-hwaddress +//@[KHWASAN-RECOVER] compile-flags: --target aarch64-unknown-none + +#![feature(no_core, sanitize, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// KHWASAN-LABEL: define{{.*}}@penguin( +// KHWASAN: call void @llvm.hwasan.check.memaccess +// KHWASAN: ret i32 +// KHWASAN: } +// KHWASAN: declare void @__hwasan_load4(i64) + +// KHWASAN-RECOVER-LABEL: define{{.*}}@penguin( +// KHWASAN-RECOVER: call void asm sideeffect "brk #2338", "{x0}"(i64 %{{[0-9]+}}) +// KHWASAN-RECOVER-NOT: unreachable +// KHWASAN-RECOVER: } +// KHWASAN-RECOVER: declare void @__hwasan_load4_noabort(i64) + +#[no_mangle] +pub unsafe fn penguin(p: *mut i32) -> i32 { + *p +} diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs new file mode 100644 index 0000000000000..c0e23f5f596ba --- /dev/null +++ b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs @@ -0,0 +1,38 @@ +// Verifies that the `#[sanitize(hwaddress = "off")]` attribute also turns off +// the kernel hardware-assisted address sanitizer. +// +//@ add-minicore +//@ compile-flags: -Zsanitizer=kernel-hwaddress -Ctarget-feature=-crt-static -Copt-level=0 +//@ revisions: aarch64 aarch64v8r +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 +//@[aarch64v8r] compile-flags: --target aarch64v8r-unknown-none +//@[aarch64v8r] needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, sanitize, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK-NOT: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @unsanitized +// CHECK: start: +// CHECK-NOT: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[sanitize(hwaddress = "off")] +#[no_mangle] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @sanitized +// CHECK: start: +// CHECK: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[no_mangle] +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs new file mode 100644 index 0000000000000..007195bff4ff5 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs @@ -0,0 +1,29 @@ +// Verifies that the `#[sanitize(kernel_hwaddress = "off")]` attribute also turns off +// the hardware-assisted address sanitizer. +// +//@ needs-sanitizer-hwaddress +//@ compile-flags: -Zsanitizer=hwaddress -Ctarget-feature=-crt-static -Copt-level=0 + +#![crate_type = "lib"] +#![feature(sanitize)] + +// CHECK-NOT: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @unsanitized +// CHECK: start: +// CHECK-NOT: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[sanitize(kernel_hwaddress = "off")] +#[no_mangle] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @sanitized +// CHECK: start: +// CHECK: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[no_mangle] +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index efa0a7f4af9ac..0ba2f0b0f2096 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread` + = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index 26ef31603d887..5d2bbd1a33ba3 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `sanitize` attribute input LL | #[sanitize(brontosaurus = "off")] | ^^^^^^^^^^^------------^^^^^^^^^^ | | - | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime" + | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress", "kernel_address", "kernel_hwaddress" or "realtime" error: multiple `sanitize` attributes --> $DIR/invalid-sanitize.rs:7:1 diff --git a/tests/ui/sanitizer/cfg-khwasan.rs b/tests/ui/sanitizer/cfg-khwasan.rs new file mode 100644 index 0000000000000..c2b0505a34c26 --- /dev/null +++ b/tests/ui/sanitizer/cfg-khwasan.rs @@ -0,0 +1,22 @@ +// Verifies that when compiling with -Zsanitizer=kernel-hwaddress, +// the `#[cfg(sanitize = "hwaddress")]` attribute is configured. + +//@ add-minicore +//@ check-pass +//@ compile-flags: -Zsanitizer=kernel-hwaddress +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 +//@ ignore-backends: gcc + +#![crate_type = "rlib"] +#![feature(cfg_sanitize, no_core)] +#![no_core] + +extern crate minicore; +use minicore::*; + +const _: fn() -> () = main; + +#[cfg(sanitize = "hwaddress")] +fn main() {} diff --git a/tests/ui/sanitizer/incompatible-khwasan.rs b/tests/ui/sanitizer/incompatible-khwasan.rs new file mode 100644 index 0000000000000..638dcd8c3a887 --- /dev/null +++ b/tests/ui/sanitizer/incompatible-khwasan.rs @@ -0,0 +1,8 @@ +//@ compile-flags: -Z sanitizer=kernel-hwaddress -Z sanitizer=kernel-address --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress` diff --git a/tests/ui/sanitizer/incompatible-khwasan.stderr b/tests/ui/sanitizer/incompatible-khwasan.stderr new file mode 100644 index 0000000000000..35246fb266230 --- /dev/null +++ b/tests/ui/sanitizer/incompatible-khwasan.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress` + +error: aborting due to 1 previous error + diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.rs b/tests/ui/sanitizer/unsupported-target-khwasan.rs new file mode 100644 index 0000000000000..bef6d95e57b21 --- /dev/null +++ b/tests/ui/sanitizer/unsupported-target-khwasan.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Z sanitizer=kernel-hwaddress --target x86_64-unknown-none +//@ needs-llvm-components: x86 +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR kernel-hwaddress sanitizer is not supported for this target diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.stderr b/tests/ui/sanitizer/unsupported-target-khwasan.stderr new file mode 100644 index 0000000000000..8b122a610ee40 --- /dev/null +++ b/tests/ui/sanitizer/unsupported-target-khwasan.stderr @@ -0,0 +1,4 @@ +error: kernel-hwaddress sanitizer is not supported for this target + +error: aborting due to 1 previous error +