Skip to content

Commit b1dff99

Browse files
authored
Rollup merge of rust-lang#127483 - BertalanD:no_sanitize-global-var, r=rcvalle
Allow disabling ASan instrumentation for globals AddressSanitizer adds instrumentation to global variables unless the [`no_sanitize_address`](https://llvm.org/docs/LangRef.html#global-attributes) attribute is set on them. This commit extends the existing `#[no_sanitize(address)]` attribute to set this; previously it only had the desired effect on functions. (cc rust-lang#39699)
2 parents c49a687 + 204b228 commit b1dff99

File tree

10 files changed

+137
-34
lines changed

10 files changed

+137
-34
lines changed

compiler/rustc_codegen_llvm/src/base.rs

+9
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,12 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
172172
Visibility::Protected => llvm::Visibility::Protected,
173173
}
174174
}
175+
176+
pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) {
177+
if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) {
178+
unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) };
179+
}
180+
if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) {
181+
unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) };
182+
}
183+
}

compiler/rustc_codegen_llvm/src/consts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ impl<'ll> CodegenCx<'ll, '_> {
470470
base::set_link_section(g, attrs);
471471
}
472472

473+
base::set_variable_sanitizer_attrs(g, attrs);
474+
473475
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
474476
// `USED` and `USED_LINKER` can't be used together.
475477
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2460,4 +2460,7 @@ unsafe extern "C" {
24602460
pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
24612461

24622462
pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
2463+
2464+
pub fn LLVMRustSetNoSanitizeAddress(Global: &Value);
2465+
pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
24632466
}

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
20512051
return llvm::compression::zstd::isAvailable();
20522052
}
20532053

2054+
extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) {
2055+
GlobalValue &GV = *unwrap<GlobalValue>(Global);
2056+
GlobalValue::SanitizerMetadata MD;
2057+
if (GV.hasSanitizerMetadata())
2058+
MD = GV.getSanitizerMetadata();
2059+
MD.NoAddress = true;
2060+
MD.IsDynInit = false;
2061+
GV.setSanitizerMetadata(MD);
2062+
}
2063+
2064+
extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
2065+
GlobalValue &GV = *unwrap<GlobalValue>(Global);
2066+
GlobalValue::SanitizerMetadata MD;
2067+
if (GV.hasSanitizerMetadata())
2068+
MD = GV.getSanitizerMetadata();
2069+
MD.NoHWAddress = true;
2070+
GV.setSanitizerMetadata(MD);
2071+
}
2072+
20542073
// Operations on composite constants.
20552074
// These are clones of LLVM api functions that will become available in future
20562075
// releases. They can be removed once Rust's minimum supported LLVM version

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,10 @@ passes_no_mangle_foreign =
558558
passes_no_patterns =
559559
patterns not allowed in naked function parameters
560560
561+
passes_no_sanitize =
562+
`#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
563+
.label = not {$accepted_kind}
564+
561565
passes_non_exported_macro_invalid_attrs =
562566
attribute should be applied to function or closure
563567
.label = not a function or closure

compiler/rustc_passes/src/check_attr.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
126126
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
127127
[sym::coverage, ..] => self.check_coverage(attr, span, target),
128128
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
129-
[sym::no_sanitize, ..] => {
130-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
131-
}
129+
[sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target),
132130
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
133131
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
134132
[sym::target_feature, ..] => {
@@ -450,6 +448,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
450448
}
451449
}
452450

451+
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
452+
if let Some(list) = attr.meta_item_list() {
453+
for item in list.iter() {
454+
let sym = item.name_or_empty();
455+
match sym {
456+
sym::address | sym::hwaddress => {
457+
let is_valid =
458+
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
459+
if !is_valid {
460+
self.dcx().emit_err(errors::NoSanitize {
461+
attr_span: item.span(),
462+
defn_span: span,
463+
accepted_kind: "a function or static",
464+
attr_str: sym.as_str(),
465+
});
466+
}
467+
}
468+
_ => {
469+
let is_valid = matches!(target, Target::Fn | Target::Method(..));
470+
if !is_valid {
471+
self.dcx().emit_err(errors::NoSanitize {
472+
attr_span: item.span(),
473+
defn_span: span,
474+
accepted_kind: "a function",
475+
attr_str: sym.as_str(),
476+
});
477+
}
478+
}
479+
}
480+
}
481+
}
482+
}
483+
453484
fn check_generic_attr(
454485
&self,
455486
hir_id: HirId,

compiler/rustc_passes/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1846,3 +1846,14 @@ pub(crate) struct AttrCrateLevelOnlySugg {
18461846
#[primary_span]
18471847
pub attr: Span,
18481848
}
1849+
1850+
#[derive(Diagnostic)]
1851+
#[diag(passes_no_sanitize)]
1852+
pub(crate) struct NoSanitize<'a> {
1853+
#[primary_span]
1854+
pub attr_span: Span,
1855+
#[label]
1856+
pub defn_span: Span,
1857+
pub accepted_kind: &'a str,
1858+
pub attr_str: &'a str,
1859+
}

tests/codegen/sanitizer/no-sanitize.rs

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
#![crate_type = "lib"]
88
#![feature(no_sanitize)]
99

10+
// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address
11+
// CHECK-NOT: @__asan_global_UNSANITIZED
12+
#[no_mangle]
13+
#[no_sanitize(address)]
14+
pub static UNSANITIZED: u32 = 0;
15+
16+
// CHECK: @__asan_global_SANITIZED
17+
#[no_mangle]
18+
pub static SANITIZED: u32 = 0;
19+
1020
// CHECK-LABEL: ; no_sanitize::unsanitized
1121
// CHECK-NEXT: ; Function Attrs:
1222
// CHECK-NOT: sanitize_address

tests/ui/attributes/no-sanitize.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,37 @@
44
#![allow(dead_code)]
55

66
fn invalid() {
7-
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
7+
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
88
{
99
1
1010
};
1111
}
1212

13-
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
13+
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
1414
type InvalidTy = ();
1515

16-
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
16+
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
1717
mod invalid_module {}
1818

1919
fn main() {
20-
let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
20+
let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
2121
(|| 1);
2222
}
2323

24-
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
24+
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
2525
struct F;
2626

27-
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
27+
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
2828
impl F {
2929
#[no_sanitize(memory)]
3030
fn valid(&self) {}
3131
}
3232

33+
#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
34+
static INVALID : i32 = 0;
35+
3336
#[no_sanitize(memory)]
3437
fn valid() {}
38+
39+
#[no_sanitize(address)]
40+
static VALID : i32 = 0;
+33-25
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,63 @@
1-
error: attribute should be applied to a function definition
2-
--> $DIR/no-sanitize.rs:7:5
1+
error: `#[no_sanitize(memory)]` should be applied to a function
2+
--> $DIR/no-sanitize.rs:7:19
33
|
44
LL | #[no_sanitize(memory)]
5-
| ^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^
66
LL | / {
77
LL | | 1
88
LL | | };
9-
| |_____- not a function definition
9+
| |_____- not a function
1010

11-
error: attribute should be applied to a function definition
12-
--> $DIR/no-sanitize.rs:13:1
11+
error: `#[no_sanitize(memory)]` should be applied to a function
12+
--> $DIR/no-sanitize.rs:13:15
1313
|
1414
LL | #[no_sanitize(memory)]
15-
| ^^^^^^^^^^^^^^^^^^^^^^
15+
| ^^^^^^
1616
LL | type InvalidTy = ();
17-
| -------------------- not a function definition
17+
| -------------------- not a function
1818

19-
error: attribute should be applied to a function definition
20-
--> $DIR/no-sanitize.rs:16:1
19+
error: `#[no_sanitize(memory)]` should be applied to a function
20+
--> $DIR/no-sanitize.rs:16:15
2121
|
2222
LL | #[no_sanitize(memory)]
23-
| ^^^^^^^^^^^^^^^^^^^^^^
23+
| ^^^^^^
2424
LL | mod invalid_module {}
25-
| --------------------- not a function definition
25+
| --------------------- not a function
2626

27-
error: attribute should be applied to a function definition
28-
--> $DIR/no-sanitize.rs:20:13
27+
error: `#[no_sanitize(memory)]` should be applied to a function
28+
--> $DIR/no-sanitize.rs:20:27
2929
|
3030
LL | let _ = #[no_sanitize(memory)]
31-
| ^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^^^^
3232
LL | (|| 1);
33-
| ------ not a function definition
33+
| ------ not a function
3434

35-
error: attribute should be applied to a function definition
36-
--> $DIR/no-sanitize.rs:24:1
35+
error: `#[no_sanitize(memory)]` should be applied to a function
36+
--> $DIR/no-sanitize.rs:24:15
3737
|
3838
LL | #[no_sanitize(memory)]
39-
| ^^^^^^^^^^^^^^^^^^^^^^
39+
| ^^^^^^
4040
LL | struct F;
41-
| --------- not a function definition
41+
| --------- not a function
4242

43-
error: attribute should be applied to a function definition
44-
--> $DIR/no-sanitize.rs:27:1
43+
error: `#[no_sanitize(memory)]` should be applied to a function
44+
--> $DIR/no-sanitize.rs:27:15
4545
|
4646
LL | #[no_sanitize(memory)]
47-
| ^^^^^^^^^^^^^^^^^^^^^^
47+
| ^^^^^^
4848
LL | / impl F {
4949
LL | | #[no_sanitize(memory)]
5050
LL | | fn valid(&self) {}
5151
LL | | }
52-
| |_- not a function definition
52+
| |_- not a function
5353

54-
error: aborting due to 6 previous errors
54+
error: `#[no_sanitize(memory)]` should be applied to a function
55+
--> $DIR/no-sanitize.rs:33:24
56+
|
57+
LL | #[no_sanitize(address, memory)]
58+
| ^^^^^^
59+
LL | static INVALID : i32 = 0;
60+
| ------------------------- not a function
61+
62+
error: aborting due to 7 previous errors
5563

0 commit comments

Comments
 (0)