]> git.lizzy.rs Git - rust.git/commitdiff
Enable stack-overflow detection on musl for non-main threads
authorTomasz Miąsko <tomasz.miasko@gmail.com>
Wed, 19 Aug 2020 00:00:00 +0000 (00:00 +0000)
committerTomasz Miąsko <tomasz.miasko@gmail.com>
Wed, 19 Aug 2020 00:00:00 +0000 (00:00 +0000)
library/std/src/sys/unix/thread.rs
src/test/ui/abi/stack-probes.rs
src/test/ui/out-of-stack.rs

index c1bda6b430e13d6fcf4c8212d0be386ad5ea4ff4..04da9812ddc45f7ede86e500816855873cf7d679 100644 (file)
@@ -213,7 +213,7 @@ fn drop(&mut self) {
 }
 
 #[cfg(all(
-    not(all(target_os = "linux", not(target_env = "musl"))),
+    not(target_os = "linux"),
     not(target_os = "freebsd"),
     not(target_os = "macos"),
     not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
@@ -233,7 +233,7 @@ pub unsafe fn init() -> Option<Guard> {
 }
 
 #[cfg(any(
-    all(target_os = "linux", not(target_env = "musl")),
+    target_os = "linux",
     target_os = "freebsd",
     target_os = "macos",
     all(target_os = "netbsd", not(target_vendor = "rumprun")),
@@ -333,9 +333,7 @@ pub unsafe fn init() -> Option<Guard> {
         let page_size = os::page_size();
         PAGE_SIZE.store(page_size, Ordering::Relaxed);
 
-        let stackaddr = get_stack_start_aligned()?;
-
-        if cfg!(target_os = "linux") {
+        if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
             // 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
@@ -346,8 +344,15 @@ pub unsafe fn init() -> Option<Guard> {
             // Instead, we'll just note where we expect rlimit to start
             // faulting, so our handler can report "stack overflow", and
             // trust that the kernel's own stack guard will work.
+            let stackaddr = get_stack_start_aligned()?;
             let stackaddr = stackaddr as usize;
             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 {
             // Reallocate the last page of the stack.
             // This ensures SIGBUS will be raised on
@@ -357,6 +362,7 @@ pub unsafe fn init() -> Option<Guard> {
             // than the initial mmap() used, so we mmap() here with
             // read/write permissions and only then mprotect() it to
             // no permissions at all. See issue #50313.
+            let stackaddr = get_stack_start_aligned()?;
             let result = mmap(
                 stackaddr,
                 page_size,
@@ -406,7 +412,14 @@ pub unsafe fn current() -> Option<Guard> {
             let mut guardsize = 0;
             assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut 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 size = 0;
@@ -419,6 +432,8 @@ pub unsafe fn current() -> Option<Guard> {
                 Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
             } else if cfg!(target_os = "netbsd") {
                 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")) {
                 // 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
index 1d5b362e29dfe9e276b36e96b0243b0bb32c1f3e..a52c285f9f0b4279f65a37448937b88a33f3ff28 100644 (file)
@@ -11,7 +11,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes
-// ignore-musl FIXME #31506
 
 use std::mem::MaybeUninit;
 use std::process::Command;
index d04b0c1a6303e966adecf4cbdb52bdbb089bffca..6beafc0732ba3174774ea77af304818508b213c8 100644 (file)
@@ -3,7 +3,6 @@
 #![allow(unused_must_use)]
 #![allow(unconditional_recursion)]
 // ignore-android: FIXME (#20004)
-// ignore-musl
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-sgx no processes