Enable stack-overflow detection on musl for non-main threads

This commit is contained in:
Tomasz Miąsko
2020-08-19 00:00:00 +00:00
parent 5b04bbfcbb
commit 6a80b1387f
3 changed files with 21 additions and 8 deletions

View File

@@ -213,7 +213,7 @@ impl Drop for Thread {
} }
#[cfg(all( #[cfg(all(
not(all(target_os = "linux", not(target_env = "musl"))), not(target_os = "linux"),
not(target_os = "freebsd"), not(target_os = "freebsd"),
not(target_os = "macos"), not(target_os = "macos"),
not(all(target_os = "netbsd", not(target_vendor = "rumprun"))), not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
@@ -233,7 +233,7 @@ pub mod guard {
} }
#[cfg(any( #[cfg(any(
all(target_os = "linux", not(target_env = "musl")), target_os = "linux",
target_os = "freebsd", target_os = "freebsd",
target_os = "macos", target_os = "macos",
all(target_os = "netbsd", not(target_vendor = "rumprun")), all(target_os = "netbsd", not(target_vendor = "rumprun")),
@@ -333,9 +333,7 @@ pub mod guard {
let page_size = os::page_size(); let page_size = os::page_size();
PAGE_SIZE.store(page_size, Ordering::Relaxed); PAGE_SIZE.store(page_size, Ordering::Relaxed);
let stackaddr = get_stack_start_aligned()?; if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
if cfg!(target_os = "linux") {
// Linux doesn't allocate the whole stack right away, and // Linux doesn't allocate the whole stack right away, and
// the kernel has its own stack-guard mechanism to fault // the kernel has its own stack-guard mechanism to fault
// when growing too close to an existing mapping. If we map // when growing too close to an existing mapping. If we map
@@ -346,8 +344,15 @@ pub mod guard {
// Instead, we'll just note where we expect rlimit to start // Instead, we'll just note where we expect rlimit to start
// faulting, so our handler can report "stack overflow", and // faulting, so our handler can report "stack overflow", and
// trust that the kernel's own stack guard will work. // trust that the kernel's own stack guard will work.
let stackaddr = get_stack_start_aligned()?;
let stackaddr = stackaddr as usize; let stackaddr = stackaddr as usize;
Some(stackaddr - page_size..stackaddr) Some(stackaddr - page_size..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
// For the main thread, the musl's pthread_attr_getstack
// returns the current stack size, rather than maximum size
// it can eventually grow to. It cannot be used to determine
// the position of kernel's stack guard.
None
} else { } else {
// Reallocate the last page of the stack. // Reallocate the last page of the stack.
// This ensures SIGBUS will be raised on // This ensures SIGBUS will be raised on
@@ -357,6 +362,7 @@ pub mod guard {
// than the initial mmap() used, so we mmap() here with // than the initial mmap() used, so we mmap() here with
// read/write permissions and only then mprotect() it to // read/write permissions and only then mprotect() it to
// no permissions at all. See issue #50313. // no permissions at all. See issue #50313.
let stackaddr = get_stack_start_aligned()?;
let result = mmap( let result = mmap(
stackaddr, stackaddr,
page_size, page_size,
@@ -406,7 +412,14 @@ pub mod guard {
let mut guardsize = 0; let mut guardsize = 0;
assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0); assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0);
if guardsize == 0 { if guardsize == 0 {
panic!("there is no guard page"); if cfg!(all(target_os = "linux", target_env = "musl")) {
// musl versions before 1.1.19 always reported guard
// size obtained from pthread_attr_get_np as zero.
// Use page size as a fallback.
guardsize = PAGE_SIZE.load(Ordering::Relaxed);
} else {
panic!("there is no guard page");
}
} }
let mut stackaddr = crate::ptr::null_mut(); let mut stackaddr = crate::ptr::null_mut();
let mut size = 0; let mut size = 0;
@@ -419,6 +432,8 @@ pub mod guard {
Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr) Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
} else if cfg!(target_os = "netbsd") { } else if cfg!(target_os = "netbsd") {
Some(stackaddr - guardsize..stackaddr) Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "gnu")) { } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
// glibc used to include the guard area within the stack, as noted in the BUGS // glibc used to include the guard area within the stack, as noted in the BUGS
// section of `man pthread_attr_getguardsize`. This has been corrected starting // section of `man pthread_attr_getguardsize`. This has been corrected starting

View File

@@ -11,7 +11,6 @@
// ignore-cloudabi no processes // ignore-cloudabi no processes
// ignore-emscripten no processes // ignore-emscripten no processes
// ignore-sgx no processes // ignore-sgx no processes
// ignore-musl FIXME #31506
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::process::Command; use std::process::Command;

View File

@@ -3,7 +3,6 @@
#![allow(unused_must_use)] #![allow(unused_must_use)]
#![allow(unconditional_recursion)] #![allow(unconditional_recursion)]
// ignore-android: FIXME (#20004) // ignore-android: FIXME (#20004)
// ignore-musl
// ignore-cloudabi no processes // ignore-cloudabi no processes
// ignore-emscripten no processes // ignore-emscripten no processes
// ignore-sgx no processes // ignore-sgx no processes