Skip to content

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Sep 25, 2025

Some sanitizers are part of a system's ABI, like the shadow call stack on Aarch64 and RISC-V Fuchsia. Typically ABI options have other spellings, but LLVM has, for historical reasons, marked this as a sanitizer instead of an alternate ABI option. As a result, Fuchsia targets may not be compiled against the correct ABI unless this option is set. This hasn't caused correctness problems, since the backend reserves the SCS register, and thus preserves its value. But this is an issue for unwinding, as the SCS will not be an array of PCs describing the call complete call chain, and will have gaps from callers that don't use the correct ABI.

In the long term, I'd like to see all the sanitizer configs that all frontends copy from clang moved into llvm's libFrontend, and exposed so that frontend consumers can use a small set of simple APIs to use sanitizers in a consistent way across the LLVM ecosystem, but that work is not yet ready today.

@rustbot
Copy link
Collaborator

rustbot commented Sep 25, 2025

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

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 25, 2025
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 25, 2025
@rustbot
Copy link
Collaborator

rustbot commented Sep 25, 2025

r? @petrochenkov

rustbot has assigned @petrochenkov.
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

This comment has been minimized.

@rustbot
Copy link
Collaborator

rustbot commented Sep 25, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@ilovepi
Copy link
Contributor Author

ilovepi commented Sep 25, 2025

Note: Some targets, like Android, may also want to set this option, but I'm not sure who's handling rustc integration for them ATM.

) -> SmallVec<[&'ll Attribute; 4]> {
let mut attrs = SmallVec::new();
let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
let enabled = (cx.sess().target.default_sanitizers | cx.tcx.sess.opts.unstable_opts.sanitizer)
Copy link
Contributor

Choose a reason for hiding this comment

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

There are many places in the compiler in which unstable_opts.sanitizer is used, but only here that list is extended with default_sanitizers.

If the intent for default_sanitizers to work as if one more -C sanitizer was passed implicitly, then the sanitizer list should always be extended.
If for Fuchsia the sanitizers actually only need to be added here in codegen, and not e.g. on linker command line or for #[cfg(sanitize)], then it's probably better to just make a special case for Fuchsia targets here in sanitize_attrs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For SCS, the only thing that happens is to add an attribute during code generation, and the backend handles the rest when doing frame lowering. But yeah, that's not quite right for other sanitizers. Clang has the notion of default sanitizers and IIRC a few targets set them. My understanding is that's mostly for SCS, but I think some may set particular flavors of UBSAN to always be on, e.g. for overflows, etc.

Probably adding them in rustc_session is more preferable. I have a vague memory that's what I initially tried but let me try that again, since you're right it should just affect the list from the start.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me know about the new approach. I worked out what blocked my last time. I had misunderstood something about the way options were plumbed into session. Thanks for making me take a second look.

Copy link
Contributor

Choose a reason for hiding this comment

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

Usually this is done by having a method on Session like fn sanitizers that would return sess.unstable_opts.sanitizer | sess.target.options.default_sanitizers.
Then #[rustc_lint_opt_deny_field_access] can be used to ensure that the unstable_opts.sanitizer field cannot be accessed directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Usually this is done by having a method on Session like fn sanitizers that would return sess.unstable_opts.sanitizer | sess.target.options.default_sanitizers. Then #[rustc_lint_opt_deny_field_access] can be used to ensure that the unstable_opts.sanitizer field cannot be accessed directly.

OK. I got that mostly working, but I'm stumped on how to handle the access in options.rs at

if opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) {

The issue is that once I slap #[rustc_lint_opt_deny_field_access] on the field, that access is an error, but we don't have access to session from there.

I think the only caller is from consistent(), so ... I guess I could move TargetModifier into session.rs? seems less than desirable, though. I also thought about making the API access be on the options(), but then I don't think you'd get the enforcement you're after...

Any thoughts/preferences? I'm just really not sure what the right tradeoff/convention would be.

Copy link
Contributor

Choose a reason for hiding this comment

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

#[allow(rustc::bad_opt_access)] can be used to suppress the lint.

But in the case of fn consistent it looks like it can just accept &Session instead of &Options.

@petrochenkov petrochenkov 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 Sep 26, 2025
Some sanitizers are part of a system's ABI, like the shadow call stack
on Aarch64 and RISC-V Fuchsia. Typically ABI options have other
spellings, but LLVM has, for historical reasons, marked this as a
sanitizer instead of an alternate ABI option. As a result, Fuchsia
targets may not be compiled against the correct ABI unless this option
is set. This hasn't caused correctness problems, since the backend
reserves the SCS register, and thus preserves its value. But this is an
issue for unwinding, as the SCS will not be an array of PCs describing
the call complete call chain, and will have gaps from callers that don't
use the correct ABI.

In the long term, I'd like to see all the sanitizer configs that all
frontends copy from clang moved into llvm's libFrontend, and exposed so
that frontend consumers can use a small set of simple APIs to use
sanitizers in a consistent way across the LLVM ecosystem, but that work
is not yet ready today.
@petrochenkov petrochenkov added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants