Rollup merge of #83771 - asomers:stack_overflow_freebsd, r=dtolnay
Fix stack overflow detection on FreeBSD 11.1+ Beginning with FreeBSD 10.4 and 11.1, there is one guard page by default. And the stack autoresizes, so if Rust allocates its own guard page, then FreeBSD's will simply move up one page. The best solution is to just use the OS's guard page.
This commit is contained in:
commit
cb7133f693
@ -343,6 +343,20 @@ pub unsafe fn init() -> Option<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 unsafe fn init() -> Option<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 unsafe fn current() -> Option<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)
|
||||
|
Loading…
Reference in New Issue
Block a user