diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 01a12dcf5a2af..b8f43caec32a3 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)