Skip to content

Commit

Permalink
sess: stabilize -C stack-protector=all
Browse files Browse the repository at this point in the history
Signed-off-by: David Wood <[email protected]>
  • Loading branch information
davidtwco committed Aug 6, 2024
1 parent 60d1465 commit 7984036
Show file tree
Hide file tree
Showing 20 changed files with 105 additions and 34 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,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 @@ -844,7 +845,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
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 @@ -109,7 +109,7 @@ session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clt
session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
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 @@ -24,7 +24,8 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_ST
use rustc_span::source_map::FilePathMapping;
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
use rustc_target::spec::{
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTriple,
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, StackProtector,
Target, TargetTriple,
};
use tracing::debug;

Expand Down Expand Up @@ -2480,6 +2481,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 @@ -1602,6 +1602,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 @@ -2014,9 +2017,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 @@ -787,7 +787,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
//@ min-llvm-version: 17.0.2

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

0 comments on commit 7984036

Please sign in to comment.