Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sanitizers: Stabilize AddressSanitizer and LeakSanitizer for the Tier 1 targets #123617

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

rcvalle
Copy link
Member

@rcvalle rcvalle commented Apr 8, 2024

Add support for specifying stable sanitizers in addition to the existing supported sanitizers, remove the -Zsanitizer unstable option and have only the -Csanitize codegen option, requiring the -Zunstable-options to be passed for using unstable sanitizers, add AddressSanitizer and LeakSanitizer for the Tier 1 targets that support them, and also stabilize the no_sanitize attribute so stable sanitizers can also be selectively disabled for annotated functions.. The tracking issue for stabilizing the sanitizers is #123615. This is part of our work to stabilize support for sanitizers in the Rust compiler. (See our roadmap at https://hackmd.io/@rcvalle/S1Ou9K6H6.)

Stabilization Report

Summary

We would like to propose stabilizing AddressSanitizer and LeakSanitizer for the Tier 1 targets that support them, and stabilize the no_sanitize attribute so stable sanitizers can also be selectively disabled for annotated functions.. This will be done by

  • Add support for specifying stable sanitizers in addition to the existing supported sanitizers.
  • Removing the -Zsanitizer unstable option and having only the -Csanitize codegen option, and requiring the -Zunstable-options to be passed for using unstable sanitizers.
  • Adding these sanitizers to the stable sanitizers.
  • Stabilize the no_sanitize attribute.

After stabilizing these sanitizers, the supported sanitizers will look like this:

Target Supported Sanitizers (Stable) Supported Sanitizers (Unstable)
aarch64-apple-darwin address, cfi, thread
aarch64-apple-ios address, thread
aarch64-apple-ios-macabi address, leak, thread
aarch64-apple-ios-sim address, thread
aarch64-apple-visionos address, thread
aarch64-apple-visionos-sim address, thread
aarch64-fuchsia address, cfi, shadow-call-stack
aarch64-linux-android address, cfi, hwaddress, memtag, shadow-call-stack
aarch64-unknown-freebsd address, cfi, memory, thread
aarch64-unknown-fuchsia address, cfi, shadow-call-stack
aarch64-unknown-illumos address, cfi
aarch64-unknown-linux-gnu address, leak cfi, hwaddress, kcfi, memory, memtag, thread
aarch64-unknown-linux-musl address, cfi, leak, memory, thread
aarch64-unknown-linux-ohos address, cfi, hwaddress, leak, memory, memtag, thread
aarch64-unknown-none kcfi, kernel-address
arm-linux-androideabi address
arm64e-apple-darwin address, cfi, thread
arm64e-apple-ios address, thread
armv7-linux-androideabi address
i586-pc-windows-msvc address
i586-unknown-linux-gnu address
i686-linux-android address
i686-pc-windows-msvc address
i686-unknown-linux-gnu address
riscv64-linux-android address
riscv64gc-unknown-fuchsia shadow-call-stack
riscv64gc-unknown-none-elf kernel-address
riscv64imac-unknown-none-elf kernel-address
s390x-unknown-linux-gnu address, leak, memory, thread
s390x-unknown-linux-musl address, leak, memory, thread
thumbv7neon-linux-androideabi address
x86_64-apple-darwin address, leak cfi, thread
x86_64-apple-ios address, thread
x86_64-apple-ios-macabi address, leak, thread
x86_64-fuchsia address, cfi, leak
x86_64-linux-android address
x86_64-pc-solaris address, cfi, thread
x86_64-pc-windows-msvc address
x86_64-unknown-freebsd address, cfi, memory, thread
x86_64-unknown-fuchsia address, cfi, leak
x86_64-unknown-illumos address, cfi, thread
x86_64-unknown-linux-gnu address, leak cfi, dataflow, kcfi, memory, safestack, thread
x86_64-unknown-linux-musl address, cfi, leak, memory, thread
x86_64-unknown-linux-ohos address, cfi, leak, memory, thread
x86_64-unknown-netbsd address, cfi, leak, memory, thread
x86_64-unknown-none kcfi, kernel-address
x86_64h-apple-darwin address, cfi, leak, thread

The tracking issue for stabilizing the sanitizers is #123615. This is part of our work to stabilize support for sanitizers in the Rust compiler. (See our roadmap at https://hackmd.io/@rcvalle/S1Ou9K6H6.)

Documentation

Documentation will be updated by adding documentation for the -Csanitizer codegen option to the Codegen Options in the The rustc book.

Tests

You may find current and will find additional test cases for the sanitizers in:

Unresolved questions

  • Doesn't the sanitizers require rebuilding the Rust Standard Library (i.e., Cargo build-std feature)?
    We will prioritize stabilizing sanitizers that provide incremental value without requiring rebuilding the Rust Standard Library (i.e., Cargo build-std feature). We're also working on Partial compilation using MIR-only rlibs compiler-team#738, which should help with -Zbuild-std.

@rustbot
Copy link
Collaborator

rustbot commented Apr 8, 2024

r? @compiler-errors

rustbot has assigned @compiler-errors.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 8, 2024
@rustbot
Copy link
Collaborator

rustbot commented Apr 8, 2024

Some changes occurred in src/tools/compiletest

cc @jieyouxu

These commits modify compiler targets.
(See the Target Tier Policy.)

@rcvalle
Copy link
Member Author

rcvalle commented Apr 8, 2024

r? @davidtwco

@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see tests that exercise things like -Csanitizer=non-existent and -Zsanitizer=non-existent, and also -Zsanitizer=stable-sanitizer1 (e.g. an x86_64-unknown-linux-gnu test for a stable sanitizer) and -Csanitizer=unstable-sanitizer (I believe you can add a run-make test with a custom target that has no sanitizers enabled for it?)

Footnotes

  1. What do we do if we pass -Zsanitizer with a stable sanitizer? Should we error? Presumably not, but I would assume we'd want to at least warn the users that the sanitizer has been stabilized and they should be using -C, just like we do for feature gates.

compiler/rustc_session/src/options.rs Outdated Show resolved Hide resolved
compiler/rustc_target/src/spec/mod.rs Outdated Show resolved Hide resolved
compiler/rustc_target/src/spec/mod.rs Outdated Show resolved Hide resolved
compiler/rustc_target/src/spec/mod.rs Outdated Show resolved Hide resolved
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 8, 2024
@tgross35
Copy link
Contributor

tgross35 commented Apr 8, 2024

Documentation will need an update. Is something like -Csanitizer=address,memory expected to work (like LLVM) ordoes it need to be -Csanitizer=address -Dsanitizer=memory?

@Noratrieb
Copy link
Member

This is unusable to most stable Rust users, right? It requires either -Zbuild-std or a custom toolchain with an instrumented standard library. The documentation in the rustc book and the stabilization report/description (which you need to add) should mention this very clearly.

@rust-log-analyzer

This comment has been minimized.

@bors

This comment was marked as resolved.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from cec660e to 17eff53 Compare April 17, 2024 18:15
@rust-log-analyzer

This comment has been minimized.

@bors

This comment was marked as resolved.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from 17eff53 to f81f25d Compare April 23, 2024 02:49
@rustbot rustbot added the T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. label Apr 23, 2024
@rustbot
Copy link
Collaborator

rustbot commented Apr 23, 2024

Some changes occurred in cfg and check-cfg configuration

cc @Urgau

Some changes occurred in tests/ui/sanitizer

cc @rust-lang/project-exploit-mitigations, @rcvalle

Some changes occurred in tests/codegen/sanitizer

cc @rust-lang/project-exploit-mitigations, @rcvalle

@rust-log-analyzer

This comment has been minimized.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from f81f25d to 2cfed6e Compare April 24, 2024 01:28
@bors
Copy link
Contributor

bors commented Jul 1, 2024

☔ The latest upstream changes (presumably #127216) made this pull request unmergeable. Please resolve the merge conflicts.

@workingjubilee
Copy link
Member

Regarding the prior issues, #121028 will be fixed by #127168 (PR is enqueued).

@apiraino apiraino removed the S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). label Jul 4, 2024
@tmiasko
Copy link
Contributor

tmiasko commented Jul 11, 2024

As far existing bug reports are concerned, for LeakSanitizer we also have #111073. Without replicating clang --export-dynamic link flag, LeakSanitizer fails to initialize on my system as well, although I didn't investigate this further.

I expected we would stabilize this under -C sanitize, so cfg predicate is named sanitize (as opposed to sanitizer). Mentioning in case you would like to synchronize this in one direction or the other before it is stabilized here or in #126158.

@Shnatsel
Copy link
Member

Shnatsel commented Jul 11, 2024

The proposed removal of -Zsanitizer could be a problem for tooling that enables sanitizers, chiefly cargo-fuzz and other fuzzers.

It is infeasible for the tooling to keep track of which sanitizers are stabilized for which target in which compiler version, so the new CLI must avoid requiring that.

I understand that the following algorithm would be sufficient for enabling sanitizers across both previous and future compiler versions:

Parse the output of rustc -vV. If the rustc version is greater or equal to the version that stabilized this PR, use -Csanitizer instead of -Zsanitizer. If the rustc version string is greater or equal to the version that stabilized this PR, and either contains nightly or the RUSTC_BOOTSTRAP environment variable is set, append -Zunstable-options.

@rcvalle is that correct? If so, I'll make a draft PR for cargo fuzz so this CLI could be tested out before stabilization.

@Shnatsel
Copy link
Member

Shnatsel commented Jul 12, 2024

I've implemented support for the proposed new CLI in cargo fuzz: rust-fuzz/cargo-fuzz#376

It took about ~100 LoC, not counting tests.

This will not support a range of nightly rustc versions on which the version number is set to the one in which the sanitizers are set to stabilize, but this PR is not yet merged. Allowing both -Zsanitizer and -Csanitizer flags, at least for a while, would mitigate that.

@cuviper
Copy link
Member

cuviper commented Jul 12, 2024

Allowing both -Zsanitizer and -Csanitizer flags, at least for a while, would mitigate that.

It's up to the compiler team to decide, but I think this would be rather atypical for an unstable flag.

@cuviper
Copy link
Member

cuviper commented Jul 12, 2024

I'm not sure if formal FCP concerns are still open, but I want to raise #127483 regarding global variables. That PR is now adding instrumentation to globals unless they opt out with #[no_sanitize], but that attribute is unstable. So from #127483 (comment), it sounds like stable sanitizers could break ctor and linkme without any stable way to fix those.

@ojeda
Copy link
Contributor

ojeda commented Jul 13, 2024

Regarding what @Shnatsel mentioned: for the Linux kernel, we also have to decide which flag(s) to use depending on the version/architecture/configuration, so it would be nice to make it as simple as possible.

Relatedly, one thing we do in the C side (and for other tools too) is to try to compile a dummy file to see if a given compiler supports an option -- it would be nice to have a convenient/proper way to test for that instead. (We also do version testing, e.g. >= 1.79.0).

@BertalanD
Copy link

So from #127483 (comment), it sounds like stable sanitizers could break ctor and linkme without any stable way to fix those.

As a dumb little stopgap, I could imagine rustc implicitly treating any variables with a custom link_section specified as having the sanitizers disabled. If people need low-level control over where the linker will place a specific global variable, its size/alignment not matching what's written in the code is probably undesired, so they likely also want #[no_sanitize(address)].

And it wouldn't be too difficult to eventually remove this hack once the attribute is stable. It's just a few crates that have to be changed, link_section is not used much outside the aforementioned ones.

@rcvalle
Copy link
Member Author

rcvalle commented Jul 18, 2024

Thank you everyone for the patience and the time while I go through all the issues listed here.

One of the things that has been mentioned on the tracking issue for stabilizing the sanitizers (#123615) is the absence of Rust interfaces and FFI bindings for the sanitizers (user) interfaces, so I've been working on this for the past few days and have an early/draft implementation of a create that provides (safe) interfaces and FFI bindings for the sanitizers (user) interfaces (see https://crates.io/crates/sanitizers and https://github.com/rcvalle/rust-crate-sanitizers).

It currently reflects the current state of the sanitizers interfaces API and documentation, and I think the crate and the sanitizers interfaces themselves in LLVM would benefit from some standardization of their API and documentation, and is something I'd like to improve in the future. Any contributions are greatly appreciated!

Regarding stabilizing the sanitizers under -Csanitize instead of -Csanitizer, even though I personally prefer the later (but this is subjective), I think consistency not only between attributes and options, but also between compilers, particularly when there are security implications (i.e., making sure a mitigation is applied throughout across compilers for "mixed binaries"), is very important, and if we want to do it, the right time seems to be when stabilizing it (as we don't provide any guarantees about unstable options). Thus, if nobody opposes I'd like to stabilize the sanitizers under -Csanitize instead of -Csanitizer then.

Regarding the removal of -Zsanitizer, we could keep it both, but as @cuviper said, it's up to the compiler team to decide, and I'd like to hear their thoughts on this. I've a question though, would it be possible to make the cut of whether to use -Zsanitizer or the stable option at the version this PR is first merged, and for this version onwards always include the -Zunstable-options along with the stable option? This would reduce the logic for supporting both unstable and stable sanitizers a lot. What do you think?

@rcvalle
Copy link
Member Author

rcvalle commented Jul 18, 2024

So from #127483 (comment), it sounds like stable sanitizers could break ctor and linkme without any stable way to fix those.

As a dumb little stopgap, I could imagine rustc implicitly treating any variables with a custom link_section specified as having the sanitizers disabled. If people need low-level control over where the linker will place a specific global variable, its size/alignment not matching what's written in the code is probably undesired, so they likely also want #[no_sanitize(address)].

And it wouldn't be too difficult to eventually remove this hack once the attribute is stable. It's just a few crates that have to be changed, link_section is not used much outside the aforementioned ones.

I think it also makes sense to include the stabilization of the no_sanitize attribute as part of this proposal as well. What do you think?

@davidtwco
Copy link
Member

Regarding the removal of -Zsanitizer, we could keep it both, but as @cuviper said, it's up to the compiler team to decide, and I'd like to hear their thoughts on this. I've a question though, would it be possible to make the cut of whether to use -Zsanitizer or the stable option at the version this PR is first merged, and for this version onwards always include the -Zunstable-options along with the stable option? This would reduce the logic for supporting both unstable and stable sanitizers a lot. What do you think?

Keeping only a -C option and using -Zunstable-options for the unstable sanitizers is more consistent with what we do for other options, so I prefer that.

I think it also makes sense to include the stabilization of the no_sanitize attribute as part of this proposal as well. What do you think?

I'm open to this, it's just that there seemed to be more open design questions about the attribute.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from 8ea55cc to e556716 Compare August 5, 2024 21:54
@rust-log-analyzer

This comment has been minimized.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from e556716 to b94f5bc Compare August 5, 2024 23:03
@rust-log-analyzer

This comment has been minimized.

@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from b94f5bc to 6e56e6b Compare August 5, 2024 23:48
@rustbot
Copy link
Collaborator

rustbot commented Aug 6, 2024

Some changes occurred in src/doc/unstable-book/src/language-features/no-sanitize.md

cc @rust-lang/project-exploit-mitigations, @rcvalle

@rust-log-analyzer

This comment has been minimized.

Add suppport for specifying stable sanitizers in addition to the
existing supported sanitizers.
Stabilize AddressSanitizer and LeakSanitizer for the Tier 1 targets that
support them.
Stabilize the `no_sanitize` attribute so stable sanitizers can also be
selectively disabled for annotated functions.
@rcvalle rcvalle force-pushed the rust-stabilize-core-sanitizers branch from 8b7530b to 8af3b93 Compare August 7, 2024 17:41
@bors
Copy link
Contributor

bors commented Aug 13, 2024

☔ The latest upstream changes (presumably #129046) made this pull request unmergeable. Please resolve the merge conflicts.

@rcvalle
Copy link
Member Author

rcvalle commented Aug 28, 2024

Thank you everyone again for the patience and the time while I go through all the issues listed here. Here are a few updates on the progress about these issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-run-make Area: port run-make Makefiles to rmake.rs A-testsuite Area: The testsuite used to check the correctness of rustc disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. PG-exploit-mitigations Project group: Exploit mitigations proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet