Skip to content

Commit 152798d

Browse files
authored
Rollup merge of rust-lang#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.
2 parents b87524b + a1689c9 commit 152798d

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

std/src/sys/unix/thread.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,20 @@ pub mod guard {
343343
// it can eventually grow to. It cannot be used to determine
344344
// the position of kernel's stack guard.
345345
None
346+
} else if cfg!(target_os = "freebsd") {
347+
// FreeBSD's stack autogrows, and optionally includes a guard page
348+
// at the bottom. If we try to remap the bottom of the stack
349+
// ourselves, FreeBSD's guard page moves upwards. So we'll just use
350+
// the builtin guard page.
351+
let stackaddr = get_stack_start_aligned()?;
352+
let guardaddr = stackaddr as usize;
353+
// Technically the number of guard pages is tunable and controlled
354+
// by the security.bsd.stack_guard_page sysctl, but there are
355+
// few reasons to change it from the default. The default value has
356+
// been 1 ever since FreeBSD 11.1 and 10.4.
357+
const GUARD_PAGES: usize = 1;
358+
let guard = guardaddr..guardaddr + GUARD_PAGES * page_size;
359+
Some(guard)
346360
} else {
347361
// Reallocate the last page of the stack.
348362
// This ensures SIGBUS will be raised on
@@ -371,9 +385,8 @@ pub mod guard {
371385
}
372386

373387
let guardaddr = stackaddr as usize;
374-
let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 };
375388

376-
Some(guardaddr..guardaddr + offset * page_size)
389+
Some(guardaddr..guardaddr + page_size)
377390
}
378391
}
379392

@@ -417,11 +430,7 @@ pub mod guard {
417430
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
418431

419432
let stackaddr = stackaddr as usize;
420-
ret = if cfg!(target_os = "freebsd") {
421-
// FIXME does freebsd really fault *below* the guard addr?
422-
let guardaddr = stackaddr - guardsize;
423-
Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
424-
} else if cfg!(target_os = "netbsd") {
433+
ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd")) {
425434
Some(stackaddr - guardsize..stackaddr)
426435
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
427436
Some(stackaddr - guardsize..stackaddr)

0 commit comments

Comments
 (0)