about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sys/unix/thread.rs23
1 files changed, 16 insertions, 7 deletions
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 01a12dcf5a2..b8f43caec32 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -343,6 +343,20 @@ pub mod guard {
             // it can eventually grow to. It cannot be used to determine
             // the position of kernel's stack guard.
             None
+        } else if cfg!(target_os = "freebsd") {
+            // FreeBSD's stack autogrows, and optionally includes a guard page
+            // at the bottom.  If we try to remap the bottom of the stack
+            // ourselves, FreeBSD's guard page moves upwards.  So we'll just use
+            // the builtin guard page.
+            let stackaddr = get_stack_start_aligned()?;
+            let guardaddr = stackaddr as usize;
+            // Technically the number of guard pages is tunable and controlled
+            // by the security.bsd.stack_guard_page sysctl, but there are
+            // few reasons to change it from the default.  The default value has
+            // been 1 ever since FreeBSD 11.1 and 10.4.
+            const GUARD_PAGES: usize = 1;
+            let guard = guardaddr..guardaddr + GUARD_PAGES * page_size;
+            Some(guard)
         } else {
             // Reallocate the last page of the stack.
             // This ensures SIGBUS will be raised on
@@ -371,9 +385,8 @@ pub mod guard {
             }
 
             let guardaddr = stackaddr as usize;
-            let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 };
 
-            Some(guardaddr..guardaddr + offset * page_size)
+            Some(guardaddr..guardaddr + page_size)
         }
     }
 
@@ -417,11 +430,7 @@ pub mod guard {
             assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
 
             let stackaddr = stackaddr as usize;
-            ret = if cfg!(target_os = "freebsd") {
-                // FIXME does freebsd really fault *below* the guard addr?
-                let guardaddr = stackaddr - guardsize;
-                Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
-            } else if cfg!(target_os = "netbsd") {
+            ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd")) {
                 Some(stackaddr - guardsize..stackaddr)
             } else if cfg!(all(target_os = "linux", target_env = "musl")) {
                 Some(stackaddr - guardsize..stackaddr)