Skip to content

Commit

Permalink
sanitizers: Add stable and unstable sanitizers
Browse files Browse the repository at this point in the history
Add suppport for separating sanitizers support in stable and unstable
for supported targets.
  • Loading branch information
rcvalle authored and Ramon de C Valle committed Apr 24, 2024
1 parent 7f2fc33 commit 4c35022
Show file tree
Hide file tree
Showing 145 changed files with 607 additions and 339 deletions.
3 changes: 1 addition & 2 deletions compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use rustc_session::config;
pub use rustc_target::abi::call::*;
use rustc_target::abi::{self, HasDataLayout, Int, Size};
pub use rustc_target::spec::abi::Abi;
use rustc_target::spec::SanitizerSet;

use libc::c_uint;
use smallvec::SmallVec;
Expand Down Expand Up @@ -82,7 +81,7 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
attrs.push(llattr.create_attr(cx.llcx));
}
}
} else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
} else if cx.tcx.sess.is_sanitizer_memory_enabled() {
// If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
// memory sanitizer's behavior.

Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn sanitize_attrs<'ll>(
no_sanitize: SanitizerSet,
) -> SmallVec<[&'ll Attribute; 4]> {
let mut attrs = SmallVec::new();
let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
let enabled = cx.tcx.sess.opts.cg.sanitizer - no_sanitize;
if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
}
Expand Down Expand Up @@ -192,13 +192,7 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
// Currently stack probes seem somewhat incompatible with the address
// sanitizer and thread sanitizer. With asan we're already protected from
// stack overflow anyway so we don't really need stack probes regardless.
if cx
.sess()
.opts
.unstable_opts
.sanitizer
.intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD)
{
if cx.sess().is_sanitizer_address_enabled() || cx.sess().is_sanitizer_thread_enabled() {
return None;
}

Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ fn add_sanitizer_libraries(
return;
}

let sanitizer = sess.opts.unstable_opts.sanitizer;
let sanitizer = sess.opts.cg.sanitizer;
if sanitizer.contains(SanitizerSet::ADDRESS) {
link_sanitizer_runtime(sess, flavor, linker, "asan");
}
Expand Down Expand Up @@ -2350,11 +2350,7 @@ fn add_order_independent_options(
&& crate_type == CrateType::Executable
&& !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
{
let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
"asan/"
} else {
""
};
let prefix = if sess.is_sanitizer_address_enabled() { "asan/" } else { "" };
cmd.arg(format!("--dynamic-linker={prefix}ld.so.1"));
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_middle::ty::{self, SymbolName, TyCtxt};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::{SanitizerSet, TlsModel};
use rustc_target::spec::TlsModel;

pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
crates_export_threshold(tcx.crate_types())
Expand Down Expand Up @@ -265,15 +265,15 @@ fn exported_symbols_provider_local(
}));
}

if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
if tcx.sess.is_sanitizer_memory_enabled() {
let mut msan_weak_symbols = Vec::new();

// Similar to profiling, preserve weak msan symbol during LTO.
if tcx.sess.opts.unstable_opts.sanitizer_recover.contains(SanitizerSet::MEMORY) {
if tcx.sess.is_sanitizer_memory_enabled() {
msan_weak_symbols.push("__msan_keep_going");
}

if tcx.sess.opts.unstable_opts.sanitizer_memory_track_origins != 0 {
if tcx.sess.is_sanitizer_memory_track_origins_enabled() {
msan_weak_symbols.push("__msan_track_origins");
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl ModuleConfig {
false
),

sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
sanitizer: if_regular!(sess.opts.cg.sanitizer, SanitizerSet::empty()),
sanitizer_dataflow_abilist: if_regular!(
sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
Vec::new()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(profile_use, Some(PathBuf::from("abc")));
tracked!(relocation_model, Some(RelocModel::Pic));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(sanitizer, SanitizerSet::ADDRESS);
tracked!(soft_float, true);
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
Expand Down Expand Up @@ -824,7 +825,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
tracked!(sanitizer, SanitizerSet::ADDRESS);
tracked!(sanitizer_cfi_canonical_jump_tables, None);
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
tracked!(sanitizer_cfi_normalize_integers, Some(true));
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_session/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only suppo
session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
session_cannot_mix_and_match_sanitizers = `-Csanitizer={$first}` is incompatible with `-Csanitizer={$second}`
session_cli_feature_diagnostic_help =
add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
Expand Down Expand Up @@ -86,15 +86,15 @@ session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C pr
session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Csanitizer=cfi`
session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Csanitizer=cfi` or `-Csanitizer=kcfi`
session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Csanitizer=cfi` or `-Csanitizer=kcfi`
session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`
session_sanitizer_cfi_requires_lto = `-Csanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`
session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
session_sanitizer_cfi_requires_single_codegen_unit = `-Csanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort`
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/config/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
}

for mut s in sess.opts.unstable_opts.sanitizer {
for mut s in sess.opts.cg.sanitizer {
// KASAN is still ASAN under the hood, so it uses the same attribute.
if s == SanitizerSet::KERNELADDRESS {
s = SanitizerSet::ADDRESS;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1554,6 +1554,8 @@ options! {
"output remarks for these optimization passes (space separated, or \"all\")"),
rpath: bool = (false, parse_bool, [UNTRACKED],
"set rpath values in libs/exes (default: no)"),
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
"use a sanitizer"),
save_temps: bool = (false, parse_bool, [UNTRACKED],
"save all temporary output files during compilation (default: no)"),
soft_float: bool = (false, parse_bool, [TRACKED],
Expand Down Expand Up @@ -1907,8 +1909,6 @@ options! {
remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"directory into which to write optimization remarks (if not specified, they will be \
written to standard error output)"),
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
"use a sanitizer"),
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],
"enable canonical jump tables (default: yes)"),
sanitizer_cfi_generalize_pointers: Option<bool> = (None, parse_opt_bool, [TRACKED],
Expand Down
39 changes: 28 additions & 11 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,12 @@ impl Session {
self.instrument_coverage() && self.opts.unstable_opts.coverage_options.mcdc
}

pub fn is_sanitizer_address_enabled(&self) -> bool {
self.opts.cg.sanitizer.contains(SanitizerSet::ADDRESS)
}

pub fn is_sanitizer_cfi_enabled(&self) -> bool {
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
self.opts.cg.sanitizer.contains(SanitizerSet::CFI)
}

pub fn is_sanitizer_cfi_canonical_jump_tables_disabled(&self) -> bool {
Expand All @@ -377,7 +381,19 @@ impl Session {
}

pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
self.opts.cg.sanitizer.contains(SanitizerSet::KCFI)
}

pub fn is_sanitizer_memory_enabled(&self) -> bool {
self.opts.cg.sanitizer.contains(SanitizerSet::MEMORY)
}

pub fn is_sanitizer_memory_track_origins_enabled(&self) -> bool {
self.opts.unstable_opts.sanitizer_memory_track_origins != 0
}

pub fn is_sanitizer_thread_enabled(&self) -> bool {
self.opts.cg.sanitizer.contains(SanitizerSet::THREAD)
}

pub fn is_split_lto_unit_enabled(&self) -> bool {
Expand Down Expand Up @@ -595,7 +611,7 @@ impl Session {
// AddressSanitizer and KernelAddressSanitizer uses 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.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
|| self.opts.cg.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
}

pub fn diagnostic_width(&self) -> usize {
Expand Down Expand Up @@ -722,7 +738,7 @@ impl Session {
let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
|| self.opts.output_types.contains_key(&OutputType::Bitcode)
// AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
|| self.opts.cg.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
!more_names
}
}
Expand Down Expand Up @@ -1167,8 +1183,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}

// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
let supported_sanitizers = sess.target.options.supported_sanitizers;
let unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers;
let supported_sanitizers = if sess.unstable_options() {
sess.target.options.supported_sanitizers.supported_sanitizers()
} else {
sess.target.options.supported_sanitizers.stable_sanitizers()
};
let unsupported_sanitizers = sess.opts.cg.sanitizer - supported_sanitizers;
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
Expand All @@ -1182,7 +1202,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
let mut sanitizer_iter = sess.opts.cg.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
sess.dcx().emit_err(errors::CannotMixAndMatchSanitizers {
first: first.to_string(),
Expand All @@ -1191,10 +1211,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}

// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None)
&& !sess.opts.unstable_opts.sanitizer.is_empty()
&& !sess.target.is_like_msvc
{
if sess.crt_static(None) && !sess.opts.cg.sanitizer.is_empty() && !sess.target.is_like_msvc {
sess.dcx().emit_err(errors::CannotEnableCrtStaticLinux);
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_target/src/spec/base/android.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{base, SanitizerSet, TargetOptions, TlsModel};
use crate::spec::{base, SanitizerSet, SanitizerSupport, TargetOptions, TlsModel};

pub fn opts() -> TargetOptions {
let mut base = base::linux::opts();
Expand All @@ -7,7 +7,8 @@ pub fn opts() -> TargetOptions {
base.default_dwarf_version = 2;
base.tls_model = TlsModel::Emulated;
base.has_thread_local = false;
base.supported_sanitizers = SanitizerSet::ADDRESS;
base.supported_sanitizers =
SanitizerSupport { stable: SanitizerSet::empty(), unstable: SanitizerSet::ADDRESS };
// This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
// for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
// was to always emit `uwtable`).
Expand Down
Loading

0 comments on commit 4c35022

Please sign in to comment.