Skip to content

Commit 4c2cfc6

Browse files
committed
Added initial configuration for BSAN.
Specified bsan branch of LLVM submodule. Added Borrow sanitizer options to frontend. Added additional configuration flags for BSAN. Updated llvm submodule and ensured that retags are allowed in subsequent MIR passes. Updated LLVM project.
1 parent 5077297 commit 4c2cfc6

File tree

36 files changed

+193
-33
lines changed

36 files changed

+193
-33
lines changed

.github/workflows/sync.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: sync
2+
on: workflow_dispatch
3+
permissions:
4+
contents: read
5+
pages: write
6+
id-token: write
7+
defaults:
8+
run:
9+
shell: bash
10+
concurrency:
11+
group: "sync"
12+
cancel-in-progress: true
13+
jobs:
14+
build:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Identity
18+
run: |
19+
git config --global user.name "github-actions[bot]"
20+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
- name: Rebase
25+
run: src/ci/scripts/sync.sh
26+
- name: Build
27+
run: ./x.py build --stage 1 library

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@
5454
[submodule "src/gcc"]
5555
path = src/gcc
5656
url = https://github.com/rust-lang/gcc.git
57-
shallow = true
57+
shallow = true

Cargo.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ dependencies = [
290290
"generic-array",
291291
]
292292

293+
[[package]]
294+
name = "bsan"
295+
version = "0.1.0"
296+
293297
[[package]]
294298
name = "bstr"
295299
version = "1.10.0"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"src/rustc-std-workspace/rustc-std-workspace-alloc",
88
"src/rustc-std-workspace/rustc-std-workspace-std",
99
"src/rustdoc-json-types",
10+
"src/tools/bsan",
1011
"src/tools/build_helper",
1112
"src/tools/cargotest",
1213
"src/tools/clippy",

compiler/rustc_borrowck/src/lib.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ use rustc_middle::mir::*;
3636
use rustc_middle::query::Providers;
3737
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
3838
use rustc_middle::{bug, span_bug};
39-
use rustc_mir_dataflow::Analysis;
4039
use rustc_mir_dataflow::impls::{
4140
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
4241
};
4342
use rustc_mir_dataflow::move_paths::{
4443
InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
4544
};
45+
use rustc_mir_dataflow::Analysis;
4646
use rustc_session::lint::builtin::UNUSED_MUT;
4747
use rustc_span::{Span, Symbol};
4848
use smallvec::SmallVec;
@@ -656,8 +656,12 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
656656
state,
657657
);
658658
}
659+
StatementKind::Retag { .. } => {
660+
if !self.infcx.tcx.sess.emit_retags() {
661+
bug!("Statement not allowed in this MIR phase")
662+
}
663+
}
659664
StatementKind::Nop
660-
| StatementKind::Retag { .. }
661665
| StatementKind::Deinit(..)
662666
| StatementKind::SetDiscriminant { .. } => {
663667
bug!("Statement not allowed in this MIR phase")
@@ -1771,11 +1775,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17711775
mpi,
17721776
);
17731777
} // Only query longest prefix with a MovePath, not further
1774-
// ancestors; dataflow recurs on children when parents
1775-
// move (to support partial (re)inits).
1776-
//
1777-
// (I.e., querying parents breaks scenario 7; but may want
1778-
// to do such a query based on partial-init feature-gate.)
1778+
// ancestors; dataflow recurs on children when parents
1779+
// move (to support partial (re)inits).
1780+
//
1781+
// (I.e., querying parents breaks scenario 7; but may want
1782+
// to do such a query based on partial-init feature-gate.)
17791783
}
17801784

17811785
/// Subslices correspond to multiple move paths, so we iterate through the

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,10 +1258,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12581258
"Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
12591259
),
12601260
},
1261+
StatementKind::Retag { .. } => {
1262+
if !self.infcx.tcx.sess.emit_retags() {
1263+
bug!("Statement not allowed in this MIR phase")
1264+
}
1265+
},
12611266
StatementKind::FakeRead(..)
12621267
| StatementKind::StorageLive(..)
12631268
| StatementKind::StorageDead(..)
1264-
| StatementKind::Retag { .. }
12651269
| StatementKind::Coverage(..)
12661270
| StatementKind::ConstEvalCounter
12671271
| StatementKind::PlaceMention(..)

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ pub(crate) fn sanitize_attrs<'ll>(
114114
if enabled.contains(SanitizerSet::SAFESTACK) {
115115
attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx));
116116
}
117+
if enabled.contains(SanitizerSet::BORROW) {
118+
attrs.push(llvm::AttributeKind::SanitizeBorrow.create_attr(cx.llcx));
119+
}
117120
attrs
118121
}
119122

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ pub(crate) unsafe fn llvm_optimize(
553553
sanitize_kernel_address_recover: config
554554
.sanitizer_recover
555555
.contains(SanitizerSet::KERNELADDRESS),
556+
sanitize_borrow: config.sanitizer.contains(SanitizerSet::BORROW),
556557
})
557558
} else {
558559
None

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ pub enum AttributeKind {
252252
FnRetThunkExtern = 41,
253253
Writable = 42,
254254
DeadOnUnwind = 43,
255+
SanitizeBorrow = 44,
255256
}
256257

257258
/// LLVMIntPredicate
@@ -541,6 +542,7 @@ pub struct SanitizerOptions {
541542
pub sanitize_hwaddress_recover: bool,
542543
pub sanitize_kernel_address: bool,
543544
pub sanitize_kernel_address_recover: bool,
545+
pub sanitize_borrow: bool,
544546
}
545547

546548
/// LLVMRelocMode

compiler/rustc_codegen_llvm/src/retag.rs

Whitespace-only changes.

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,9 @@ fn add_sanitizer_libraries(
13151315
if sanitizer.contains(SanitizerSet::ADDRESS) {
13161316
link_sanitizer_runtime(sess, flavor, linker, "asan");
13171317
}
1318+
if sanitizer.contains(SanitizerSet::BORROW) {
1319+
link_sanitizer_runtime(sess, flavor, linker, "bsan");
1320+
}
13181321
if sanitizer.contains(SanitizerSet::DATAFLOW) {
13191322
link_sanitizer_runtime(sess, flavor, linker, "dfsan");
13201323
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
337337
codegen_fn_attrs.no_sanitize |=
338338
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
339339
}
340+
sym::borrow => {
341+
codegen_fn_attrs.no_sanitize |=
342+
SanitizerSet::BORROW
343+
}
340344
sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
341345
sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
342346
sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8787
let src = src_val.immediate();
8888
bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty());
8989
}
90+
91+
mir::StatementKind::Retag { .. } => if self.cx.sess().emit_retags() {},
9092
mir::StatementKind::FakeRead(..)
91-
| mir::StatementKind::Retag { .. }
9293
| mir::StatementKind::AscribeUserType(..)
9394
| mir::StatementKind::ConstEvalCounter
9495
| mir::StatementKind::PlaceMention(..)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
use crate::traits::BackendTypes;
3+
4+
pub trait BSANMethods<'tcx>: BackendTypes {
5+
/// Take an inline assembly expression and splat it out via LLVM
6+
fn track_operand(&mut self);
7+
}
8+
9+
*/

compiler/rustc_codegen_ssa/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
mod abi;
1515
mod asm;
1616
mod backend;
17+
mod bsan;
1718
mod builder;
1819
mod consts;
1920
mod coverageinfo;

compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ enum LLVMRustAttribute {
9898
FnRetThunkExtern = 41,
9999
Writable = 42,
100100
DeadOnUnwind = 43,
101+
SanitizeBorrow = 44,
101102
};
102103

103104
typedef struct OpaqueRustString *RustStringRef;

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/Transforms/IPO/LowerTypeTests.h"
3737
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
3838
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
39+
#include "llvm/Transforms/Instrumentation/BorrowSanitizer.h"
3940
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
4041
#include "llvm/Transforms/Utils/AddDiscriminators.h"
4142
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
@@ -671,6 +672,7 @@ struct LLVMRustSanitizerOptions {
671672
bool SanitizeHWAddressRecover;
672673
bool SanitizeKernelAddress;
673674
bool SanitizeKernelAddressRecover;
675+
bool SanitizeBorrow;
674676
};
675677

676678
extern "C" LLVMRustResult LLVMRustOptimize(
@@ -914,6 +916,13 @@ extern "C" LLVMRustResult LLVMRustOptimize(
914916
MPM.addPass(HWAddressSanitizerPass(opts));
915917
});
916918
}
919+
if (SanitizerOptions->SanitizeBorrow) {
920+
OptimizerLastEPCallbacks.push_back(
921+
[SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
922+
BorrowSanitizerOptions opts;
923+
MPM.addPass(BorrowSanitizerPass(opts));
924+
});
925+
}
917926
}
918927

919928
ModulePassManager MPM;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
302302
return Attribute::Writable;
303303
case DeadOnUnwind:
304304
return Attribute::DeadOnUnwind;
305+
case SanitizeBorrow:
306+
return Attribute::SanitizeBorrow;
305307
}
308+
306309
report_fatal_error("bad AttributeKind");
307310
}
308311

compiler/rustc_mir_transform/src/add_retag.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use rustc_hir::LangItem;
88
use rustc_middle::mir::*;
99
use rustc_middle::ty::{self, Ty, TyCtxt};
10-
1110
pub(super) struct AddRetag;
1211

1312
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
@@ -50,7 +49,7 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b
5049

5150
impl<'tcx> crate::MirPass<'tcx> for AddRetag {
5251
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
53-
sess.opts.unstable_opts.mir_emit_retag
52+
sess.emit_retags()
5453
}
5554

5655
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {

compiler/rustc_mir_transform/src/shim.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
245245

246246
// The first argument (index 0), but add 1 for the return value.
247247
let mut dropee_ptr = Place::from(Local::new(1 + 0));
248-
if tcx.sess.opts.unstable_opts.mir_emit_retag {
248+
if tcx.sess.emit_retags() {
249249
// We want to treat the function argument as if it was passed by `&mut`. As such, we
250250
// generate
251251
// ```

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ mod desc {
384384
pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
385385
pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`";
386386
pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
387-
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`";
387+
pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `borrow`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`";
388388
pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
389389
pub(crate) const parse_cfguard: &str =
390390
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -823,6 +823,7 @@ pub mod parse {
823823
"thread" => SanitizerSet::THREAD,
824824
"hwaddress" => SanitizerSet::HWADDRESS,
825825
"safestack" => SanitizerSet::SAFESTACK,
826+
"borrow" => SanitizerSet::BORROW,
826827
_ => return false,
827828
}
828829
}

compiler/rustc_session/src/session.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::any::Any;
22
use std::ops::{Div, Mul};
33
use std::path::{Path, PathBuf};
44
use std::str::FromStr;
5-
use std::sync::Arc;
65
use std::sync::atomic::AtomicBool;
76
use std::sync::atomic::Ordering::SeqCst;
7+
use std::sync::Arc;
88
use std::{env, fmt, io};
99

1010
use rustc_data_structures::flock;
@@ -16,12 +16,12 @@ use rustc_data_structures::sync::{
1616
};
1717
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
1818
use rustc_errors::codes::*;
19-
use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType, stderr_destination};
19+
use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter, HumanReadableErrorType};
2020
use rustc_errors::json::JsonEmitter;
2121
use rustc_errors::registry::Registry;
2222
use rustc_errors::{
23-
Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
24-
FluentBundle, LazyFallbackBundle, TerminalUrl, fallback_fluent_bundle,
23+
fallback_fluent_bundle, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic,
24+
ErrorGuaranteed, FatalAbort, FluentBundle, LazyFallbackBundle, TerminalUrl,
2525
};
2626
use rustc_macros::HashStable_Generic;
2727
pub use rustc_span::def_id::StableCrateId;
@@ -42,7 +42,7 @@ use crate::config::{
4242
InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents,
4343
SwitchWithOptPath,
4444
};
45-
use crate::parse::{ParseSess, add_feature_diagnostics};
45+
use crate::parse::{add_feature_diagnostics, ParseSess};
4646
use crate::search_paths::{PathKind, SearchPath};
4747
use crate::{errors, filesearch, lint};
4848

@@ -606,7 +606,13 @@ impl Session {
606606
// AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
607607
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
608608
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
609-
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
609+
// BorrowSanitizer will eventually use lifetimes as well.
610+
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::BORROW | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
611+
}
612+
613+
pub fn emit_retags(&self) -> bool {
614+
self.opts.unstable_opts.mir_emit_retag
615+
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::BORROW)
610616
}
611617

612618
pub fn diagnostic_width(&self) -> usize {
@@ -650,10 +656,13 @@ impl Session {
650656
}
651657

652658
pub fn mir_opt_level(&self) -> usize {
653-
self.opts
654-
.unstable_opts
655-
.mir_opt_level
656-
.unwrap_or_else(|| if self.opts.optimize != OptLevel::No { 2 } else { 1 })
659+
self.opts.unstable_opts.mir_opt_level.unwrap_or_else(|| {
660+
if self.opts.optimize != OptLevel::No {
661+
2
662+
} else {
663+
1
664+
}
665+
})
657666
}
658667

659668
/// Calculates the flavor of LTO to use for this compilation.
@@ -734,7 +743,8 @@ impl Session {
734743
let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
735744
|| self.opts.output_types.contains_key(&OutputType::Bitcode)
736745
// AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
737-
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
746+
// BorrowSanitizer should also have this information.
747+
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::BORROW | SanitizerSet::MEMORY);
738748
!more_names
739749
}
740750
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ symbols! {
500500
block,
501501
bool,
502502
bool_then,
503+
borrow,
503504
borrowck_graphviz_format,
504505
borrowck_graphviz_postflow,
505506
box_new,

0 commit comments

Comments
 (0)