Use a range to identify SIGSEGV in stack guards
Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range<usize>` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option<!>`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes #47863.
This commit is contained in:
@@ -57,9 +57,6 @@ mod imp {
|
||||
use sys_common::thread_info;
|
||||
|
||||
|
||||
// This is initialized in init() and only read from after
|
||||
static mut PAGE_SIZE: usize = 0;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
|
||||
#[repr(C)]
|
||||
@@ -102,12 +99,12 @@ mod imp {
|
||||
_data: *mut libc::c_void) {
|
||||
use sys_common::util::report_overflow;
|
||||
|
||||
let guard = thread_info::stack_guard().unwrap_or(0);
|
||||
let guard = thread_info::stack_guard().unwrap_or(0..0);
|
||||
let addr = siginfo_si_addr(info);
|
||||
|
||||
// If the faulting address is within the guard page, then we print a
|
||||
// message saying so and abort.
|
||||
if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard {
|
||||
if guard.start <= addr && addr < guard.end {
|
||||
report_overflow();
|
||||
rtabort!("stack overflow");
|
||||
} else {
|
||||
@@ -123,8 +120,6 @@ mod imp {
|
||||
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
|
||||
|
||||
pub unsafe fn init() {
|
||||
PAGE_SIZE = ::sys::os::page_size();
|
||||
|
||||
let mut action: sigaction = mem::zeroed();
|
||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
action.sa_sigaction = signal_handler as sighandler_t;
|
||||
|
||||
Reference in New Issue
Block a user