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

sess: stabilize -C stack-protector=all #121742

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(soft_float, true);
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
tracked!(stack_protector, StackProtector::All);
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(target_cpu, Some(String::from("abc")));
tracked!(target_feature, String::from("all the features, all of them"));
Expand Down Expand Up @@ -851,7 +852,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(small_data_threshold, Some(16));
tracked!(split_lto_unit, Some(true));
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
tracked!(stack_protector, StackProtector::All);
tracked!(teach, true);
tracked!(thinlto, Some(true));
tracked!(tiny_const_eval_limit, true);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ session_target_requires_unwind_tables = target requires unwind tables, they cann

session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored

session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
session_target_stack_protector_not_supported = `-C stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored

session_unleashed_feature_help_named = skipping check for `{$gate}` feature
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ use rustc_span::{
FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol, sym,
};
use rustc_target::spec::{
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple,
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, StackProtector,
Target, TargetTuple,
};
use tracing::debug;

Expand Down Expand Up @@ -2505,6 +2506,22 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
}
}

// Check for unstable values of `-C stack-protector`.
// This is what prevents them from being used on stable compilers.
match cg.stack_protector {
// Stable values:
StackProtector::All | StackProtector::None => {}
// Unstable values:
StackProtector::Basic | StackProtector::Strong => {
if !unstable_opts.unstable_options {
early_dcx.early_fatal(
"`-C stack-protector=basic` and `-C stack-protector=strong` \
require `-Z unstable-options`",
);
}
}
}

if cg.instrument_coverage != InstrumentCoverage::No {
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
early_dcx.early_fatal(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,9 @@ options! {
#[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")]
split_debuginfo: Option<SplitDebuginfo> = (None, parse_split_debuginfo, [TRACKED],
"how to handle split-debuginfo, a platform-specific option"),
#[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")]
stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED],
"control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"),
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
Expand Down Expand Up @@ -2080,9 +2083,6 @@ written to standard error output)"),
"enable LTO unit splitting (default: no)"),
src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
"hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
#[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")]
stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED],
"control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"),
staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED],
"allow staticlibs to have rust dylib dependencies"),
staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED],
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ impl Session {

pub fn stack_protector(&self) -> StackProtector {
if self.target.options.supports_stack_protector {
self.opts.unstable_opts.stack_protector
self.opts.cg.stack_protector
} else {
StackProtector::None
}
Expand Down Expand Up @@ -1274,10 +1274,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
}

if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if sess.opts.cg.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
sess.dcx().emit_warn(errors::StackProtectorNotSupportedForTarget {
stack_protector: sess.opts.unstable_opts.stack_protector,
stack_protector: sess.opts.cg.stack_protector,
target_triple: &sess.opts.target_triple,
});
}
Expand Down
21 changes: 21 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,26 @@ Note that all three options are supported on Linux and Apple platforms,
Attempting to use an unsupported option requires using the nightly channel
with the `-Z unstable-options` flag.

## stack-protector

The option `-C stack-protector=val` controls stack smashing protection. See [Stack smashing
protection][stack-smashing] for more details.

Supported values for this option are:

- `none` - no stack protectors
- `all` - force use of stack protectors for all functions

Unstable options for this value are:

- `basic` - enable stack protectors for functions potentially vulnerable to stack smashing (basic
heuristic)
- `strong` - enable stack protectors for functions potentially vulnerable to stack smashing (strong
heuristic)

`basic` and `strong` values for `-C stack-protector` require using the nightly channel with the
`-Z unstable-options` flag.

## strip

The option `-C strip=val` controls stripping of debuginfo and similar auxiliary
Expand Down Expand Up @@ -667,3 +687,4 @@ effective only for x86 targets.
[instrumentation-based code coverage]: ../instrument-coverage.md
[profile-guided optimization]: ../profile-guided-optimization.md
[option-g-debug]: ../command-line-arguments.md#option-g-debug
[stack-smashing]: ../exploit-mitigations.md#stack-smashing-protection
8 changes: 6 additions & 2 deletions src/doc/rustc/src/exploit-mitigations.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ equivalent.
| Stack clashing protection | Yes | 1.20.0 (2017-08-31) |
| Read-only relocations and immediate binding | Yes | 1.21.0 (2017-10-12) |
| Heap corruption protection | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) |
| Stack smashing protection | Yes | Nightly |
| Stack smashing protection | Yes | 1.78.0 (2024-05-02) |
| Forward-edge control flow protection | Yes | Nightly |
| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | Nightly |

Expand Down Expand Up @@ -357,7 +357,8 @@ instruction pointer, and checking if this value has changed when returning from
a function. This is also known as “Stack Protector” or “Stack Smashing
Protector (SSP)”.

The Rust compiler supports stack smashing protection on nightly builds[40].
The Rust compiler supports stack smashing protection with the `-C stack-protector=all`
flag since version 1.78.0 (2024-05-02)[40], [47].

![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust.
Expand Down Expand Up @@ -627,3 +628,6 @@ to `READ_IMPLIES_EXEC`).

46. “SafeStack.” The Rust Unstable Book.
[https://doc.rust-lang/org/unstable-book/compiler-flags/sanitizer.html#safestack](../unstable-book/compiler-flags/sanitizer.html#safestack).

47. D. Wood. “sess: stabilize stack-protector=all #121742” GitHub.
<https://github.com/rust-lang/rust/pull/121742>
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
//@ only-windows
//@ only-msvc
//@ ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH
//@ [all] compile-flags: -Z stack-protector=all
//@ [strong] compile-flags: -Z stack-protector=strong
//@ [basic] compile-flags: -Z stack-protector=basic
//@ [none] compile-flags: -Z stack-protector=none
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] compile-flags: -C stack-protector=basic -Z unstable-options
//@ [none] compile-flags: -C stack-protector=none
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled

#![crate_type = "lib"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
//@ only-windows
//@ only-msvc
//@ ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH
//@ [all] compile-flags: -Z stack-protector=all
//@ [strong] compile-flags: -Z stack-protector=strong
//@ [basic] compile-flags: -Z stack-protector=basic
//@ [none] compile-flags: -Z stack-protector=none
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] compile-flags: -C stack-protector=basic -Z unstable-options
//@ [none] compile-flags: -C stack-protector=none
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled

#![crate_type = "lib"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
//@ ignore-msvc stack check code uses different function names
//@ ignore-nvptx64 stack protector is not supported
//@ ignore-wasm32-bare
//@ [all] compile-flags: -Z stack-protector=all
//@ [strong] compile-flags: -Z stack-protector=strong
//@ [basic] compile-flags: -Z stack-protector=basic
//@ [none] compile-flags: -Z stack-protector=none
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] compile-flags: -C stack-protector=basic -Z unstable-options
//@ [none] compile-flags: -C stack-protector=none
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled

// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
//@ [r84] needs-llvm-components: x86
//@ [r85] compile-flags: --target x86_64-unknown-redox
//@ [r85] needs-llvm-components: x86
//@ compile-flags: -Z stack-protector=all
//@ compile-flags: -C stack-protector=all
//@ compile-flags: -C opt-level=2

#![crate_type = "lib"]
Expand Down
6 changes: 3 additions & 3 deletions tests/codegen/stack-protector.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//@ revisions: all strong basic none
//@ ignore-nvptx64 stack protector not supported
//@ [all] compile-flags: -Z stack-protector=all
//@ [strong] compile-flags: -Z stack-protector=strong
//@ [basic] compile-flags: -Z stack-protector=basic
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] compile-flags: -C stack-protector=basic -Z unstable-options

#![crate_type = "lib"]

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/abi/stack-protector.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ run-pass
//@ only-x86_64-unknown-linux-gnu
//@ revisions: ssp no-ssp
//@ [ssp] compile-flags: -Z stack-protector=all
//@ [ssp] compile-flags: -C stack-protector=all
//@ compile-flags: -C opt-level=2
//@ compile-flags: -g

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
error: `-C stack-protector=basic` and `-C stack-protector=strong` require `-Z unstable-options`

25 changes: 25 additions & 0 deletions tests/ui/stack-protector/stack-protector-unstable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//@ revisions: all strong strong-ok basic basic-ok
//@ compile-flags: --target x86_64-unknown-linux-gnu
//@ needs-llvm-components: x86
//@ [all] check-pass
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] check-fail
//@ [strong] compile-flags: -C stack-protector=strong
//@ [strong-ok] check-pass
//@ [strong-ok] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] check-fail
//@ [basic] compile-flags: -C stack-protector=basic
//@ [basic-ok] check-pass
//@ [basic-ok] compile-flags: -C stack-protector=basic -Z unstable-options

#![crate_type = "lib"]
#![feature(no_core, lang_items)]
#![no_std]
#![no_core]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

pub fn main(){}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
error: `-C stack-protector=basic` and `-C stack-protector=strong` require `-Z unstable-options`

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
warning: `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored
warning: `-C stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored

warning: 1 warning emitted

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
warning: `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored
warning: `-C stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored

warning: 1 warning emitted

6 changes: 3 additions & 3 deletions tests/ui/stack-protector/warn-stack-protector-unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
//@ revisions: all strong basic
//@ compile-flags: --target nvptx64-nvidia-cuda
//@ needs-llvm-components: nvptx
//@ [all] compile-flags: -Z stack-protector=all
//@ [strong] compile-flags: -Z stack-protector=strong
//@ [basic] compile-flags: -Z stack-protector=basic
//@ [all] compile-flags: -C stack-protector=all
//@ [strong] compile-flags: -C stack-protector=strong -Z unstable-options
//@ [basic] compile-flags: -C stack-protector=basic -Z unstable-options

#![crate_type = "lib"]
#![feature(no_core, lang_items)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
warning: `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored
warning: `-C stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored

warning: 1 warning emitted

Loading