diff options
| author | Josh Stone <jistone@redhat.com> | 2018-01-31 11:41:29 -0800 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2018-01-31 11:41:29 -0800 |
| commit | 55b54a999bcdb0b1c1f42b6e1ae670beb0717086 (patch) | |
| tree | 8aa51f05325480fb09568a50431cc48750d1c27f /src/libstd/sys_common | |
| parent | e2de8deb0927eb68dbc5986e1fbbd0a1359f8a74 (diff) | |
| download | rust-55b54a999bcdb0b1c1f42b6e1ae670beb0717086.tar.gz rust-55b54a999bcdb0b1c1f42b6e1ae670beb0717086.zip | |
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.
Diffstat (limited to 'src/libstd/sys_common')
| -rw-r--r-- | src/libstd/sys_common/thread_info.rs | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 7970042b1d6..6a2b6742367 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -11,10 +11,11 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use cell::RefCell; +use sys::thread::guard::Guard; use thread::Thread; struct ThreadInfo { - stack_guard: Option<usize>, + stack_guard: Option<Guard>, thread: Thread, } @@ -38,11 +39,11 @@ pub fn current_thread() -> Option<Thread> { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> Option<usize> { - ThreadInfo::with(|info| info.stack_guard).and_then(|o| o) +pub fn stack_guard() -> Option<Guard> { + ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) } -pub fn set(stack_guard: Option<usize>, thread: Thread) { +pub fn set(stack_guard: Option<Guard>, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_guard, |
