Rollup merge of #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 https://github.com/rust-lang/rust/issues/39699)
This commit is contained in:
commit
c6d36256a6
10 changed files with 137 additions and 34 deletions
|
@ -172,3 +172,12 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
|
|||
Visibility::Protected => llvm::Visibility::Protected,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) {
|
||||
if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) {
|
||||
unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) };
|
||||
}
|
||||
if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) {
|
||||
unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,6 +470,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
base::set_link_section(g, attrs);
|
||||
}
|
||||
|
||||
base::set_variable_sanitizer_attrs(g, attrs);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
|
|
|
@ -2460,4 +2460,7 @@ unsafe extern "C" {
|
|||
pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
|
||||
pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
|
||||
pub fn LLVMRustSetNoSanitizeAddress(Global: &Value);
|
||||
pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
|
||||
}
|
||||
|
|
|
@ -2051,6 +2051,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
|
|||
return llvm::compression::zstd::isAvailable();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) {
|
||||
GlobalValue &GV = *unwrap<GlobalValue>(Global);
|
||||
GlobalValue::SanitizerMetadata MD;
|
||||
if (GV.hasSanitizerMetadata())
|
||||
MD = GV.getSanitizerMetadata();
|
||||
MD.NoAddress = true;
|
||||
MD.IsDynInit = false;
|
||||
GV.setSanitizerMetadata(MD);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
|
||||
GlobalValue &GV = *unwrap<GlobalValue>(Global);
|
||||
GlobalValue::SanitizerMetadata MD;
|
||||
if (GV.hasSanitizerMetadata())
|
||||
MD = GV.getSanitizerMetadata();
|
||||
MD.NoHWAddress = true;
|
||||
GV.setSanitizerMetadata(MD);
|
||||
}
|
||||
|
||||
// Operations on composite constants.
|
||||
// These are clones of LLVM api functions that will become available in future
|
||||
// releases. They can be removed once Rust's minimum supported LLVM version
|
||||
|
|
|
@ -558,6 +558,10 @@ passes_no_mangle_foreign =
|
|||
passes_no_patterns =
|
||||
patterns not allowed in naked function parameters
|
||||
|
||||
passes_no_sanitize =
|
||||
`#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
|
||||
.label = not {$accepted_kind}
|
||||
|
||||
passes_non_exported_macro_invalid_attrs =
|
||||
attribute should be applied to function or closure
|
||||
.label = not a function or closure
|
||||
|
|
|
@ -126,9 +126,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
|
||||
[sym::coverage, ..] => self.check_coverage(attr, span, target),
|
||||
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
|
||||
[sym::no_sanitize, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||
}
|
||||
[sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target),
|
||||
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
|
||||
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
|
||||
[sym::target_feature, ..] => {
|
||||
|
@ -450,6 +448,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
let sym = item.name_or_empty();
|
||||
match sym {
|
||||
sym::address | sym::hwaddress => {
|
||||
let is_valid =
|
||||
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
|
||||
if !is_valid {
|
||||
self.dcx().emit_err(errors::NoSanitize {
|
||||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function or static",
|
||||
attr_str: sym.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let is_valid = matches!(target, Target::Fn | Target::Method(..));
|
||||
if !is_valid {
|
||||
self.dcx().emit_err(errors::NoSanitize {
|
||||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function",
|
||||
attr_str: sym.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_generic_attr(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
|
|
|
@ -1846,3 +1846,14 @@ pub(crate) struct AttrCrateLevelOnlySugg {
|
|||
#[primary_span]
|
||||
pub attr: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_no_sanitize)]
|
||||
pub(crate) struct NoSanitize<'a> {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub defn_span: Span,
|
||||
pub accepted_kind: &'a str,
|
||||
pub attr_str: &'a str,
|
||||
}
|
||||
|
|
|
@ -7,6 +7,16 @@
|
|||
#![crate_type = "lib"]
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address
|
||||
// CHECK-NOT: @__asan_global_UNSANITIZED
|
||||
#[no_mangle]
|
||||
#[no_sanitize(address)]
|
||||
pub static UNSANITIZED: u32 = 0;
|
||||
|
||||
// CHECK: @__asan_global_SANITIZED
|
||||
#[no_mangle]
|
||||
pub static SANITIZED: u32 = 0;
|
||||
|
||||
// CHECK-LABEL: ; no_sanitize::unsanitized
|
||||
// CHECK-NEXT: ; Function Attrs:
|
||||
// CHECK-NOT: sanitize_address
|
||||
|
|
|
@ -4,31 +4,37 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
fn invalid() {
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
{
|
||||
1
|
||||
};
|
||||
}
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
type InvalidTy = ();
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
mod invalid_module {}
|
||||
|
||||
fn main() {
|
||||
let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
(|| 1);
|
||||
}
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
struct F;
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
impl F {
|
||||
#[no_sanitize(memory)]
|
||||
fn valid(&self) {}
|
||||
}
|
||||
|
||||
#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
static INVALID : i32 = 0;
|
||||
|
||||
#[no_sanitize(memory)]
|
||||
fn valid() {}
|
||||
|
||||
#[no_sanitize(address)]
|
||||
static VALID : i32 = 0;
|
||||
|
|
|
@ -1,55 +1,63 @@
|
|||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:7:5
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:7:19
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | / {
|
||||
LL | | 1
|
||||
LL | | };
|
||||
| |_____- not a function definition
|
||||
| |_____- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:13:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:13:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | type InvalidTy = ();
|
||||
| -------------------- not a function definition
|
||||
| -------------------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:16:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:16:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | mod invalid_module {}
|
||||
| --------------------- not a function definition
|
||||
| --------------------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:20:13
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:20:27
|
||||
|
|
||||
LL | let _ = #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | (|| 1);
|
||||
| ------ not a function definition
|
||||
| ------ not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:24:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:24:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | struct F;
|
||||
| --------- not a function definition
|
||||
| --------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:27:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:27:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | / impl F {
|
||||
LL | | #[no_sanitize(memory)]
|
||||
LL | | fn valid(&self) {}
|
||||
LL | | }
|
||||
| |_- not a function definition
|
||||
| |_- not a function
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:33:24
|
||||
|
|
||||
LL | #[no_sanitize(address, memory)]
|
||||
| ^^^^^^
|
||||
LL | static INVALID : i32 = 0;
|
||||
| ------------------------- not a function
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue