From d198633b958627b718dbd19cb24adf0c80f936c9 Mon Sep 17 00:00:00 2001 From: Lucas Baumann Date: Fri, 23 May 2025 14:35:28 +0200 Subject: [PATCH] add realtime sanitizer --- .../src/attributes/codegen_attrs.rs | 20 +++++++++-- compiler/rustc_codegen_llvm/src/attributes.rs | 14 +++++++- compiler/rustc_codegen_llvm/src/back/write.rs | 1 + compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 ++ compiler/rustc_codegen_ssa/src/back/link.rs | 3 ++ .../rustc_codegen_ssa/src/codegen_attrs.rs | 14 +++++--- .../rustc_hir/src/attrs/data_structures.rs | 18 +++++++++- compiler/rustc_hir/src/lib.rs | 3 ++ .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 9 +++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 6 ++++ .../src/middle/codegen_fn_attrs.rs | 6 ++-- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_session/src/options.rs | 3 +- compiler/rustc_span/src/symbol.rs | 4 +++ compiler/rustc_target/src/spec/mod.rs | 3 ++ .../src/spec/targets/aarch64_apple_darwin.rs | 5 ++- .../src/spec/targets/aarch64_apple_ios.rs | 4 ++- .../src/spec/targets/aarch64_apple_ios_sim.rs | 4 ++- .../spec/targets/aarch64_unknown_linux_gnu.rs | 3 +- .../src/spec/targets/x86_64_apple_darwin.rs | 3 +- .../spec/targets/x86_64_unknown_linux_gnu.rs | 3 +- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 18 +++++----- src/doc/rustc-dev-guide/src/sanitizers.md | 2 +- src/tools/compiletest/src/common.rs | 1 + .../src/directives/directive_names.rs | 1 + src/tools/compiletest/src/directives/needs.rs | 7 ++++ tests/ui/attributes/malformed-attrs.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- tests/ui/sanitize-attr/invalid-sanitize.rs | 3 ++ .../ui/sanitize-attr/invalid-sanitize.stderr | 36 +++++++++++++++---- tests/ui/sanitizer/realtime-alloc.rs | 20 +++++++++++ tests/ui/sanitizer/realtime-blocking.rs | 25 +++++++++++++ tests/ui/sanitizer/realtime-caller.rs | 28 +++++++++++++++ 34 files changed, 240 insertions(+), 38 deletions(-) create mode 100644 tests/ui/sanitizer/realtime-alloc.rs create mode 100644 tests/ui/sanitizer/realtime-blocking.rs create mode 100644 tests/ui/sanitizer/realtime-caller.rs diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 1270f8759d1b..b4ecbe6e4de6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy}; +use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy}; use rustc_session::parse::feature_err; use super::prelude::*; @@ -592,7 +592,8 @@ impl SingleAttributeParser for SanitizeParser { r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, - r#"thread = "on|off""# + r#"thread = "on|off""#, + r#"realtime = "nonblocking|blocking|caller""#, ]); const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; @@ -606,6 +607,7 @@ impl SingleAttributeParser for SanitizeParser { let mut on_set = SanitizerSet::empty(); let mut off_set = SanitizerSet::empty(); + let mut rtsan = None; for item in list.mixed() { let Some(item) = item.meta_item() else { @@ -654,6 +656,17 @@ impl SingleAttributeParser for SanitizeParser { Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK), Some(sym::thread) => apply(SanitizerSet::THREAD), Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS), + Some(sym::realtime) => match value.value_as_str() { + Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking), + Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking), + Some(sym::caller) => rtsan = Some(RtsanSetting::Caller), + _ => { + cx.expected_specific_argument_strings( + value.value_span, + &[sym::nonblocking, sym::blocking, sym::caller], + ); + } + }, _ => { cx.expected_specific_argument_strings( item.path().span(), @@ -666,6 +679,7 @@ impl SingleAttributeParser for SanitizeParser { sym::shadow_call_stack, sym::thread, sym::hwaddress, + sym::realtime, ], ); continue; @@ -673,7 +687,7 @@ impl SingleAttributeParser for SanitizeParser { } } - Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span }) + Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span }) } } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 7b8b7ff3c291..89878d1e7e20 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,5 +1,5 @@ //! Set and unset common attributes on LLVM values. -use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting}; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, @@ -131,6 +131,18 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( if enabled.contains(SanitizerSet::SAFESTACK) { attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx)); } + if tcx.sess.sanitizers().contains(SanitizerSet::REALTIME) { + match sanitizer_fn_attr.rtsan_setting { + RtsanSetting::Nonblocking => { + attrs.push(llvm::AttributeKind::SanitizeRealtimeNonblocking.create_attr(cx.llcx)) + } + RtsanSetting::Blocking => { + attrs.push(llvm::AttributeKind::SanitizeRealtimeBlocking.create_attr(cx.llcx)) + } + // caller is the default, so no llvm attribute + RtsanSetting::Caller => (), + } + } attrs } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index b582d587d9f8..1880e43ca76a 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -633,6 +633,7 @@ pub(crate) unsafe fn llvm_optimize( sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY), sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY), sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int, + sanitize_realtime: config.sanitizer.contains(SanitizerSet::REALTIME), sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD), sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS), sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 9a391d57d6fb..1a9a6f7e112c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -290,6 +290,8 @@ pub(crate) enum AttributeKind { DeadOnReturn = 44, CapturesReadOnly = 45, CapturesNone = 46, + SanitizeRealtimeNonblocking = 47, + SanitizeRealtimeBlocking = 48, } /// LLVMIntPredicate @@ -482,6 +484,7 @@ pub(crate) struct SanitizerOptions { pub sanitize_memory: bool, pub sanitize_memory_recover: bool, pub sanitize_memory_track_origins: c_int, + pub sanitize_realtime: bool, pub sanitize_thread: bool, pub sanitize_hwaddress: bool, pub sanitize_hwaddress_recover: bool, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index fa730bae610c..ce496c713791 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1252,6 +1252,9 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::SAFESTACK) { link_sanitizer_runtime(sess, flavor, linker, "safestack"); } + if sanitizer.contains(SanitizerSet::REALTIME) { + link_sanitizer_runtime(sess, flavor, linker, "rtsan"); + } } fn link_sanitizer_runtime( diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 5dd1365f2645..8fbd41020fb0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -349,9 +349,10 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); - // Compute the disabled sanitizers. - codegen_fn_attrs.sanitizers.disabled |= - tcx.sanitizer_settings_for(did).disabled; + // Passed in sanitizer settings are always the default. + assert!(codegen_fn_attrs.sanitizers == SanitizerFnAttrs::default()); + // Replace with #[sanitize] value + codegen_fn_attrs.sanitizers = tcx.sanitizer_settings_for(did); // On trait methods, inherit the `#[align]` of the trait's method prototype. codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did)); @@ -587,7 +588,7 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs }; // Check for a sanitize annotation directly on this def. - if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set)) + if let Some((on_set, off_set, rtsan)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, rtsan, ..} => (on_set, off_set, rtsan)) { // the on set is the set of sanitizers explicitly enabled. // we mask those out since we want the set of disabled sanitizers here @@ -598,6 +599,11 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs // the on set and off set are distjoint since there's a third option: unset. // a node may not set the sanitizer setting in which case it inherits from parents. // the code above in this function does this backtracking + + // if rtsan was specified here override the parent + if let Some(rtsan) = rtsan { + settings.rtsan_setting = *rtsan; + } } settings } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a5f7debe1787..b1b872808c8f 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -382,6 +382,16 @@ pub struct DebugVisualizer { pub path: Symbol, } +#[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] +#[derive(HashStable_Generic, PrintAttribute)] +#[derive_const(Default)] +pub enum RtsanSetting { + Nonblocking, + Blocking, + #[default] + Caller, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -689,7 +699,13 @@ pub enum AttributeKind { /// /// the on set and off set are distjoint since there's a third option: unset. /// a node may not set the sanitizer setting in which case it inherits from parents. - Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span }, + /// rtsan is unset if None + Sanitize { + on_set: SanitizerSet, + off_set: SanitizerSet, + rtsan: Option, + span: Span, + }, /// Represents `#[should_panic]` ShouldPanic { reason: Option, span: Span }, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 0d0a1f6b76a2..7a5776f0d5a9 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -6,6 +6,9 @@ #![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![feature(associated_type_defaults)] #![feature(closure_track_caller)] +#![feature(const_default)] +#![feature(const_trait_impl)] +#![feature(derive_const)] #![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(variant_count)] diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 178b43c93ef6..143cc9479089 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -38,6 +38,7 @@ #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Scalar/AnnotationRemarks.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" @@ -531,6 +532,7 @@ struct LLVMRustSanitizerOptions { bool SanitizeMemory; bool SanitizeMemoryRecover; int SanitizeMemoryTrackOrigins; + bool SanitizerRealtime; bool SanitizeThread; bool SanitizeHWAddress; bool SanitizeHWAddressRecover; @@ -786,6 +788,13 @@ extern "C" LLVMRustResult LLVMRustOptimize( MPM.addPass(HWAddressSanitizerPass(opts)); }); } + if (SanitizerOptions->SanitizerRealtime) { + OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM, + OptimizationLevel Level, + ThinOrFullLTOPhase phase) { + MPM.addPass(RealtimeSanitizerPass()); + }); + } } ModulePassManager MPM; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 2d87ea232eea..f8b7cb257da8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -246,6 +246,8 @@ enum class LLVMRustAttributeKind { DeadOnReturn = 44, CapturesReadOnly = 45, CapturesNone = 46, + SanitizeRealtimeNonblocking = 47, + SanitizeRealtimeBlocking = 48, }; static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { @@ -342,6 +344,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { case LLVMRustAttributeKind::CapturesReadOnly: case LLVMRustAttributeKind::CapturesNone: report_fatal_error("Should be handled separately"); + case LLVMRustAttributeKind::SanitizeRealtimeNonblocking: + return Attribute::SanitizeRealtime; + case LLVMRustAttributeKind::SanitizeRealtimeBlocking: + return Attribute::SanitizeRealtimeBlocking; } report_fatal_error("bad LLVMRustAttributeKind"); } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index fd1f5791de4d..5a28d56d4e54 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_abi::Align; -use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr}; +use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr, RtsanSetting}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; @@ -245,11 +245,11 @@ impl CodegenFnAttrs { #[derive(Clone, Copy, Debug, HashStable, TyEncodable, TyDecodable, Eq, PartialEq)] pub struct SanitizerFnAttrs { pub disabled: SanitizerSet, + pub rtsan_setting: RtsanSetting, } impl const Default for SanitizerFnAttrs { fn default() -> Self { - Self { disabled: SanitizerSet::empty() } + Self { disabled: SanitizerSet::empty(), rtsan_setting: RtsanSetting::default() } } - } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5944a1e8da5d..81259f343375 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -212,7 +212,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => { self.check_custom_mir(dialect, phase, attr_span) } - &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => { + &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, rtsan: _, span: attr_span}) => { self.check_sanitize(attr_span, on_set | off_set, span, target); }, Attribute::Parsed(AttributeKind::Link(_, attr_span)) => { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b49194b82f3a..acb3316c027c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -808,7 +808,7 @@ mod desc { pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`"; 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`, or `thread`"; + 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_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`"; @@ -1253,6 +1253,7 @@ pub mod parse { "thread" => SanitizerSet::THREAD, "hwaddress" => SanitizerSet::HWADDRESS, "safestack" => SanitizerSet::SAFESTACK, + "realtime" => SanitizerSet::REALTIME, _ => return false, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 38718bad9e57..6570557c6500 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -583,6 +583,7 @@ symbols! { bitxor_assign, black_box, block, + blocking, bool, bool_then, borrowck_graphviz_format, @@ -616,6 +617,7 @@ symbols! { call_once, call_once_future, call_ref_future, + caller, caller_location, capture_disjoint_fields, carrying_mul_add, @@ -1561,6 +1563,7 @@ symbols! { non_exhaustive_omitted_patterns_lint, non_lifetime_binders, non_modrs_mods, + nonblocking, none, nontemporal_store, noop_method_borrow, @@ -1801,6 +1804,7 @@ symbols! { read_via_copy, readonly, realloc, + realtime, reason, reborrow, receiver, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 023c62812c86..e0741f8c824f 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1177,6 +1177,7 @@ bitflags::bitflags! { const KERNELADDRESS = 1 << 9; const SAFESTACK = 1 << 10; const DATAFLOW = 1 << 11; + const REALTIME = 1 << 12; } } rustc_data_structures::external_bitflags_debug! { SanitizerSet } @@ -1227,6 +1228,7 @@ impl SanitizerSet { SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack", SanitizerSet::THREAD => "thread", SanitizerSet::HWADDRESS => "hwaddress", + SanitizerSet::REALTIME => "realtime", _ => return None, }) } @@ -1271,6 +1273,7 @@ impl FromStr for SanitizerSet { "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK, "thread" => SanitizerSet::THREAD, "hwaddress" => SanitizerSet::HWADDRESS, + "realtime" => SanitizerSet::REALTIME, s => return Err(format!("unknown sanitizer {s}")), }) } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index e19604725559..ecfd6ebba863 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -20,7 +20,10 @@ pub(crate) fn target() -> Target { cpu: "apple-m1".into(), max_atomic_width: Some(128), // FIXME: The leak sanitizer currently fails the tests, see #88132. - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, supports_xray: true, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 3b522c34522b..85b4a0614a85 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -18,7 +18,9 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index d366ed264820..2924ba5ebb10 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -18,7 +18,9 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index c4b1f2c05eb1..f7e1cbfac263 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs @@ -30,7 +30,8 @@ pub(crate) fn target() -> Target { | SanitizerSet::MEMORY | SanitizerSet::MEMTAG | SanitizerSet::THREAD - | SanitizerSet::HWADDRESS, + | SanitizerSet::HWADDRESS + | SanitizerSet::REALTIME, supports_xray: true, ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 8892c50d8447..cb517b2a357a 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -21,7 +21,8 @@ pub(crate) fn target() -> Target { supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK - | SanitizerSet::THREAD, + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, supports_xray: true, ..opts }, 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 adb7a43a6232..defa9f146d79 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 @@ -17,7 +17,8 @@ pub(crate) fn target() -> Target { | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::SAFESTACK - | SanitizerSet::THREAD; + | SanitizerSet::THREAD + | SanitizerSet::REALTIME; base.supports_xray = true; Target { diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index b70d452b427c..e79391a107aa 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/139931 +Last change is for: https://github.com/rust-lang/rust/pull/147935 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index d43d261ad6c3..7e1b59351e04 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1262,13 +1262,13 @@ fn supported_sanitizers( }; match &*target.triple { - "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), - "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]), - "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]), + "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]), + "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan", "rtsan"]), + "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan", "rtsan"]), "aarch64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]), "aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), "aarch64-unknown-linux-gnu" => { - common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) + common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan"]) } "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) @@ -1276,7 +1276,7 @@ fn supported_sanitizers( "loongarch64-unknown-linux-gnu" | "loongarch64-unknown-linux-musl" => { common_libs("linux", "loongarch64", &["asan", "lsan", "msan", "tsan"]) } - "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), + "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]), "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]), "x86_64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]), @@ -1286,9 +1286,11 @@ fn supported_sanitizers( } "x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]), "x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]), - "x86_64-unknown-linux-gnu" => { - common_libs("linux", "x86_64", &["asan", "dfsan", "lsan", "msan", "safestack", "tsan"]) - } + "x86_64-unknown-linux-gnu" => common_libs( + "linux", + "x86_64", + &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"], + ), "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index fd91fdb2504d..53df27412f05 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -45,7 +45,7 @@ implementation: [marked][sanitizer-attribute] with appropriate LLVM attribute: `SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or `SanitizeThread`. By default all functions are instrumented, but this - behaviour can be changed with `#[sanitize(xyz = "on|off")]`. + behaviour can be changed with `#[sanitize(xyz = "on|off|")]`. * The decision whether to perform instrumentation or not is possible only at a function granularity. In the cases were those decision differ between diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 1f893fecb54b..aa8e340ee755 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -174,6 +174,7 @@ pub enum Sanitizer { ShadowCallStack, Thread, Hwaddress, + Realtime, } #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 1474df146f9c..d60819653f6c 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -165,6 +165,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-leak", "needs-sanitizer-memory", "needs-sanitizer-memtag", + "needs-sanitizer-realtime", "needs-sanitizer-safestack", "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 5e9fe59d8d1c..713a63317b72 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -69,6 +69,11 @@ pub(super) fn handle_needs( condition: cache.sanitizer_memtag, ignore_reason: "ignored on targets without memory tagging sanitizer", }, + Need { + name: "needs-sanitizer-realtime", + condition: cache.sanitizer_realtime, + ignore_reason: "ignored on targets without realtime sanitizer", + }, Need { name: "needs-sanitizer-shadow-call-stack", condition: cache.sanitizer_shadow_call_stack, @@ -320,6 +325,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_thread: bool, sanitizer_hwaddress: bool, sanitizer_memtag: bool, + sanitizer_realtime: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, xray: bool, @@ -346,6 +352,7 @@ impl CachedNeedsConditions { sanitizer_thread: sanitizers.contains(&Sanitizer::Thread), sanitizer_hwaddress: sanitizers.contains(&Sanitizer::Hwaddress), sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), + sanitizer_realtime: sanitizers.contains(&Sanitizer::Realtime), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), xray: config.target_cfg().xray, diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 5627cb452a81..d8d9c182529e 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -513,7 +513,7 @@ LL | #[sanitize(hwaddress = "on|off")] | ++++++++++++++++++++++ LL | #[sanitize(kcfi = "on|off")] | +++++++++++++++++ - = and 5 other candidates + = and 6 other candidates error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:101:1 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 8205756d64dd..d9a9981177d2 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`, `safestack`, `shadow-call-stack`, and `thread` + = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `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.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs index 957ce780ad0f..707e1a3be777 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.rs +++ b/tests/ui/sanitize-attr/invalid-sanitize.rs @@ -19,3 +19,6 @@ fn name_value() {} #[sanitize] //~ ERROR malformed `sanitize` attribute input fn just_word() {} + +#[sanitize(realtime = "on")] //~ ERROR malformed `sanitize` attribute input +fn wrong_value_realtime() {} diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index ec0a93be1420..08aa5257f3f0 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" or "hwaddress" + | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime" | help: try changing it to one of the following valid forms of the attribute | @@ -20,7 +20,7 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error: multiple `sanitize` attributes --> $DIR/invalid-sanitize.rs:6:1 @@ -68,7 +68,7 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize(address = "bogus")] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:17:1 @@ -90,7 +90,7 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize = "off"] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:20:1 @@ -108,8 +108,32 @@ LL | #[sanitize(hwaddress = "on|off")] | ++++++++++++++++++++++ LL | #[sanitize(kcfi = "on|off")] | +++++++++++++++++ - = and 5 other candidates + = and 6 other candidates -error: aborting due to 6 previous errors +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:23:1 + | +LL | #[sanitize(realtime = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^----^^ + | | + | valid arguments are "nonblocking", "blocking" or "caller" + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(address = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(cfi = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(hwaddress = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(kcfi = "on|off")] + | + = and 6 other candidates + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/sanitizer/realtime-alloc.rs b/tests/ui/sanitizer/realtime-alloc.rs new file mode 100644 index 000000000000..2b4039dcf308 --- /dev/null +++ b/tests/ui/sanitizer/realtime-alloc.rs @@ -0,0 +1,20 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ exec-env: RTSAN_OPTIONS=abort_on_error=0 +// +//@ run-fail +//@ error-pattern: Intercepted call to real-time unsafe function `malloc` in real-time context! +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + let mut vec = vec![0, 1, 2]; + println!("alloc not detected"); +} + +fn main() { + sanitizer_on(); +} diff --git a/tests/ui/sanitizer/realtime-blocking.rs b/tests/ui/sanitizer/realtime-blocking.rs new file mode 100644 index 000000000000..a27448a346f0 --- /dev/null +++ b/tests/ui/sanitizer/realtime-blocking.rs @@ -0,0 +1,25 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ exec-env: RTSAN_OPTIONS=abort_on_error=0 +// +//@ run-fail +//@ error-pattern: Call to blocking function +//@ error-pattern: realtime_blocking::blocking:: +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + blocking(); +} + +#[sanitize(realtime = "blocking")] +fn blocking() { + println!("blocking call not detected"); +} + +fn main() { + sanitizer_on(); +} diff --git a/tests/ui/sanitizer/realtime-caller.rs b/tests/ui/sanitizer/realtime-caller.rs new file mode 100644 index 000000000000..d606d71cba02 --- /dev/null +++ b/tests/ui/sanitizer/realtime-caller.rs @@ -0,0 +1,28 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ exec-env: RTSAN_OPTIONS=abort_on_error=0 +// +//@ run-fail +//@ error-pattern: RealtimeSanitizer: blocking-call +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + caller(); +} + +fn caller() { + blocking() +} + +#[sanitize(realtime = "blocking")] +fn blocking() { + println!("blocking call not detected"); +} + +fn main() { + sanitizer_on(); +}