Description
We have found the stack guard logic present in rust 1.27 conflicts with the OS-provided mitigation present in illumos distributions. This became clear on SmartOS when the 2018Q2 pkgsrc update moved from rust 1.24 to 1.27. Those binaries, compiled on an old platform without the mitigation, bail immediately on machines that do possess it
# rustc
thread 'main' panicked at 'failed to allocate a guard page', libstd/sys/unix/thread.rs:337:17
note: Run with `RUST_BACKTRACE=1` for a backtrace.
# RUST_BACKTRACE=full rustc
thread 'main' panicked at 'failed to allocate a guard page', libstd/sys/unix/thread.rs:337:17
stack backtrace:
0: 0xfffffd7fde402f3e - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::ha22b267de1618f10
1: 0xfffffd7fde3cdee6 - std::sys_common::backtrace::print::h9be6459ca953ea86
2: 0xfffffd7fde410a1b - std::panicking::default_hook::{{closure}}::h11d519068135b02a
3: 0xfffffd7fde4106e1 - std::panicking::default_hook::he7d6fa94ad994305
4: 0xfffffd7fde41110c - std::panicking::rust_panic_with_hook::hef4aa8f9edd49f7f
5: 0xfffffd7fde410ef6 - std::panicking::begin_panic::h350ed1a97f2676c6
6: 0xfffffd7fde3e7b24 - std::sys::unix::thread::guard::init::h66e847be7b85328f
7: 0xfffffd7fde3e44fd - std::rt::update_stack_guard::h3749f1240dd6decc
8: 0xfffffd7fde786185 - rustc_driver::run::hf99f9e1bb314cfb8
9: 0xfffffd7fde7954da - rustc_driver::main::he45a01066d380276
10: 0x401842 - std::rt::lang_start::{{closure}}::h50ce2fc38c241613
11: 0xfffffd7fde410be2 - std::panicking::try::do_call::h260c23fa696aee03
12: 0xfffffd7fde417919 - __rust_maybe_catch_panic
13: 0xfffffd7fde3e4325 - std::rt::lang_start_internal::hef1606e7d03cbe2a
14: 0x4018a3 - main
15: 0x40167b - _start
The details of how the two guards are conflicting can be found written up in OS-7059. The stack-clash mitigation was added to SmartOS and OmniOS back in October 2017. It was merged into illumos-gate this past week, marking its availability for any remaining downstream distributions.
Our temporary mitigation has been to float a patch in pkgsrc to treat the 'solaris' platform like 'linux', disabling the stack-guard mapping:
--- src/libstd/sys/unix/thread.rs.orig 2018-06-24 22:42:29.203295357 +0000
+++ src/libstd/sys/unix/thread.rs
@@ -309,7 +309,7 @@ pub mod guard {
let stackaddr = get_stack_start_aligned()?;
- if cfg!(target_os = "linux") {
+ if cfg!(any(target_os = "linux", target_os = "solaris")) {
// Linux doesn't allocate the whole stack right away, and
// the kernel has its own stack-guard mechanism to fault
// when growing too close to an existing mapping. If we map
@@ -345,7 +354,7 @@ pub mod guard {
}
pub unsafe fn deinit() {
- if !cfg!(target_os = "linux") {
+ if cfg!(not(any(target_os = "linux", target_os = "solaris"))) {
if let Some(stackaddr) = get_stack_start_aligned() {
// Remove the protection on the guard page.
// FIXME: we cannot unmap the page, because when we mmap()
Considering the rest of the illumos ecosystem is (or soon will be) effected by this issue, it would be nice to get that stack-guard exclusion moved into upstream rust.