Skip to content

Commit 1fefdbe

Browse files
author
Ariel Ben-Yehuda
committed
Implement -Z allow-partial-mitigations (RFC 3855)
This implements `-Z allow-partial-mitigations` as an unstable option, currently with support for control-flow-guard and stack-protector. As a difference from the RFC, we have `-Z allow-partial-mitigations=!foo` rather than `-Z deny-partial-mitigations=foo`, since I couldn't find an easy way to have an allow/deny pair of flags where the latter flag wins. To allow for stabilization, this is only enabled starting from the next edition. Maybe a better policy is possible (bikeshed).
1 parent 2c0f486 commit 1fefdbe

19 files changed

+538
-9
lines changed

compiler/rustc_interface/src/passes.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ fn configure_and_expand(
304304

305305
resolver.resolve_crate(&krate);
306306

307-
CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate);
308-
CStore::from_tcx(tcx).report_incompatible_async_drop_feature(tcx, &krate);
307+
CStore::from_tcx(tcx).report_session_incompatibilities(tcx, &krate);
309308
krate
310309
}
311310

compiler/rustc_metadata/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ metadata_link_ordinal_raw_dylib =
153153
metadata_missing_native_library =
154154
could not find native static library `{$libname}`, perhaps an -L flag is missing?
155155
156+
metadata_mitigation_less_strict_in_dependency =
157+
your program uses the crate `{$extern_crate}`, that is not protected by `{$mitigation_name}{$mitigation_level}`
158+
.note = Recompile that crate with the mitigation enabled, or use `-Z allow-partial-mitigations={$mitigation_name}` to allow creating an artifact that has the mitigation only partially enabled
159+
.help = It is possible to disable `-Z allow-partial-mitigations={$mitigation_name}` via `-Z allow-partial-mitigations=!{$mitigation_name}`
160+
156161
metadata_multiple_candidates =
157162
multiple candidates for `{$flavor}` dependency `{$crate_name}` found
158163

compiler/rustc_metadata/src/creader.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Validates all used crates and extern libraries and loads their metadata
22
3+
use std::collections::BTreeMap;
34
use std::error::Error;
45
use std::path::Path;
56
use std::str::FromStr;
@@ -25,8 +26,8 @@ use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
2526
use rustc_proc_macro::bridge::client::ProcMacro;
2627
use rustc_session::Session;
2728
use rustc_session::config::{
28-
CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers,
29-
TargetModifier,
29+
CrateType, EnforcedMitigationLevel, ExtendedTargetModifierInfo, ExternLocation, Externs,
30+
OptionsTargetModifiers, TargetModifier,
3031
};
3132
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
3233
use rustc_session::lint::{self, BuiltinLintDiag};
@@ -453,6 +454,12 @@ impl CStore {
453454
}
454455
}
455456

457+
pub fn report_session_incompatibilities(&self, tcx: TyCtxt<'_>, krate: &Crate) {
458+
self.report_incompatible_target_modifiers(tcx, krate);
459+
self.report_incompatible_enforced_mitigations(tcx, krate);
460+
self.report_incompatible_async_drop_feature(tcx, krate);
461+
}
462+
456463
pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) {
457464
for flag_name in &tcx.sess.opts.cg.unsafe_allow_abi_mismatch {
458465
if !OptionsTargetModifiers::is_target_modifier(flag_name) {
@@ -474,6 +481,46 @@ impl CStore {
474481
}
475482
}
476483

484+
pub fn report_incompatible_enforced_mitigations(&self, tcx: TyCtxt<'_>, krate: &Crate) {
485+
let my_mitigations = tcx.sess.gather_enabled_enforced_mitigations();
486+
let mut my_mitigations: BTreeMap<_, _> = my_mitigations
487+
.iter()
488+
.filter(|mitigation| mitigation.kind.enforced_since() <= tcx.sess.edition())
489+
.map(|mitigation| (mitigation.kind, mitigation))
490+
.collect();
491+
for skipped_mitigation in tcx.sess.opts.allowed_partial_mitigations() {
492+
my_mitigations.remove(&skipped_mitigation);
493+
}
494+
const MAX_ERRORS_PER_MITIGATION: usize = 5;
495+
let mut errors_per_mitigation = BTreeMap::new();
496+
for (_cnum, data) in self.iter_crate_data() {
497+
if data.is_proc_macro_crate() {
498+
continue;
499+
}
500+
let their_mitigations = data.enforced_mitigations();
501+
for my_mitigation in my_mitigations.values() {
502+
let their_mitigation = their_mitigations
503+
.iter()
504+
.find(|mitigation| mitigation.kind == my_mitigation.kind)
505+
.map_or(EnforcedMitigationLevel::Enabled(false), |m| m.level);
506+
if their_mitigation < my_mitigation.level {
507+
let errors = errors_per_mitigation.entry(my_mitigation.kind).or_insert(0);
508+
if *errors >= MAX_ERRORS_PER_MITIGATION {
509+
continue;
510+
}
511+
*errors += 1;
512+
513+
tcx.dcx().emit_err(errors::MitigationLessStrictInDependency {
514+
span: krate.spans.inner_span.shrink_to_lo(),
515+
mitigation_name: my_mitigation.kind.to_string(),
516+
mitigation_level: my_mitigation.level.level_str().to_string(),
517+
extern_crate: data.name(),
518+
});
519+
}
520+
}
521+
}
522+
}
523+
477524
// Report about async drop types in dependency if async drop feature is disabled
478525
pub fn report_incompatible_async_drop_feature(&self, tcx: TyCtxt<'_>, krate: &Crate) {
479526
if tcx.features().async_drop() {

compiler/rustc_metadata/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,3 +615,13 @@ pub struct RawDylibMalformed {
615615
#[primary_span]
616616
pub span: Span,
617617
}
618+
619+
#[derive(Diagnostic)]
620+
#[diag(metadata_mitigation_less_strict_in_dependency)]
621+
pub struct MitigationLessStrictInDependency {
622+
#[primary_span]
623+
pub span: Span,
624+
pub mitigation_name: String,
625+
pub mitigation_level: String,
626+
pub extern_crate: Symbol,
627+
}

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_proc_macro::bridge::client::ProcMacro;
2929
use rustc_serialize::opaque::MemDecoder;
3030
use rustc_serialize::{Decodable, Decoder};
3131
use rustc_session::Session;
32-
use rustc_session::config::TargetModifier;
32+
use rustc_session::config::{EnforcedMitigation, TargetModifier};
3333
use rustc_session::cstore::{CrateSource, ExternCrate};
3434
use rustc_span::hygiene::HygieneDecodeContext;
3535
use rustc_span::{
@@ -76,9 +76,12 @@ impl MetadataBlob {
7676
/// own crate numbers.
7777
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
7878

79-
/// Target modifiers - abi or exploit mitigations flags
79+
/// Target modifiers - abi or exploit mitigations flags that cause unsoundness when mixed
8080
pub(crate) type TargetModifiers = Vec<TargetModifier>;
8181

82+
/// Enforced Mitigations
83+
pub(crate) type EnforcedMitigations = Vec<EnforcedMitigation>;
84+
8285
pub(crate) struct CrateMetadata {
8386
/// The primary crate data - binary metadata blob.
8487
blob: MetadataBlob,
@@ -984,6 +987,13 @@ impl CrateRoot {
984987
) -> impl ExactSizeIterator<Item = TargetModifier> {
985988
self.target_modifiers.decode(metadata)
986989
}
990+
991+
pub(crate) fn decode_enforced_mitigations<'a>(
992+
&self,
993+
metadata: &'a MetadataBlob,
994+
) -> impl ExactSizeIterator<Item = EnforcedMitigation> {
995+
self.enforced_mitigations.decode(metadata)
996+
}
987997
}
988998

989999
impl<'a> CrateMetadataRef<'a> {
@@ -1929,6 +1939,10 @@ impl CrateMetadata {
19291939
self.root.decode_target_modifiers(&self.blob).collect()
19301940
}
19311941

1942+
pub(crate) fn enforced_mitigations(&self) -> EnforcedMitigations {
1943+
self.root.decode_enforced_mitigations(&self.blob).collect()
1944+
}
1945+
19321946
/// Keep `new_extern_crate` if it looks better in diagnostics
19331947
pub(crate) fn update_extern_crate_diagnostics(
19341948
&mut self,

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_middle::ty::codec::TyEncoder;
2727
use rustc_middle::ty::fast_reject::{self, TreatParams};
2828
use rustc_middle::{bug, span_bug};
2929
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
30-
use rustc_session::config::{CrateType, OptLevel, TargetModifier};
30+
use rustc_session::config::{CrateType, EnforcedMitigation, OptLevel, TargetModifier};
3131
use rustc_span::hygiene::HygieneEncodeContext;
3232
use rustc_span::{
3333
ByteSymbol, ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId,
@@ -715,6 +715,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
715715
// `SourceFiles` we actually need to encode.
716716
let source_map = stat!("source-map", || self.encode_source_map());
717717
let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers());
718+
let enforced_mitigations =
719+
stat!("enforced-mitigations", || self.encode_enforced_mitigations());
718720

719721
let root = stat!("final", || {
720722
let attrs = tcx.hir_krate_attrs();
@@ -760,6 +762,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
760762
foreign_modules,
761763
source_map,
762764
target_modifiers,
765+
enforced_mitigations,
763766
traits,
764767
impls,
765768
incoherent_impls,
@@ -2093,6 +2096,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20932096
self.lazy_array(tcx.sess.opts.gather_target_modifiers())
20942097
}
20952098

2099+
fn encode_enforced_mitigations(&mut self) -> LazyArray<EnforcedMitigation> {
2100+
empty_proc_macro!(self);
2101+
let tcx = self.tcx;
2102+
self.lazy_array(tcx.sess.gather_enabled_enforced_mitigations())
2103+
}
2104+
20962105
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
20972106
empty_proc_macro!(self);
20982107
let tcx = self.tcx;

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
3434
use rustc_middle::ty::{self, Ty, TyCtxt, UnusedGenericParams};
3535
use rustc_middle::util::Providers;
3636
use rustc_serialize::opaque::FileEncoder;
37-
use rustc_session::config::{SymbolManglingVersion, TargetModifier};
37+
use rustc_session::config::{EnforcedMitigation, SymbolManglingVersion, TargetModifier};
3838
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
3939
use rustc_span::edition::Edition;
4040
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
@@ -283,6 +283,7 @@ pub(crate) struct CrateRoot {
283283

284284
source_map: LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>,
285285
target_modifiers: LazyArray<TargetModifier>,
286+
enforced_mitigations: LazyArray<EnforcedMitigation>,
286287

287288
compiler_builtins: bool,
288289
needs_allocator: bool,

compiler/rustc_metadata/src/rmeta/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ trivially_parameterized_over_tcx! {
116116
rustc_middle::ty::Visibility<DefIndex>,
117117
rustc_middle::ty::adjustment::CoerceUnsizedInfo,
118118
rustc_middle::ty::fast_reject::SimplifiedType,
119+
rustc_session::config::EnforcedMitigation,
119120
rustc_session::config::TargetModifier,
120121
rustc_session::cstore::ForeignModule,
121122
rustc_session::cstore::LinkagePreference,

compiler/rustc_session/src/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,18 @@ impl Options {
15411541
pub fn autodiff_enabled(&self) -> bool {
15421542
self.unstable_opts.autodiff.contains(&AutoDiff::Enable)
15431543
}
1544+
1545+
pub fn allowed_partial_mitigations(&self) -> impl Iterator<Item = EnforcedMitigationKind> {
1546+
let mut result = BTreeSet::default();
1547+
for mitigation in &self.unstable_opts.allow_partial_mitigations {
1548+
if mitigation.enabled {
1549+
result.insert(mitigation.kind);
1550+
} else {
1551+
result.remove(&mitigation.kind);
1552+
}
1553+
}
1554+
result.into_iter()
1555+
}
15441556
}
15451557

15461558
impl UnstableOptions {

0 commit comments

Comments
 (0)