about summary refs log tree commit diff
path: root/src/libstd/sys_common
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2018-01-31 11:41:29 -0800
committerJosh Stone <jistone@redhat.com>2018-01-31 11:41:29 -0800
commit55b54a999bcdb0b1c1f42b6e1ae670beb0717086 (patch)
tree8aa51f05325480fb09568a50431cc48750d1c27f /src/libstd/sys_common
parente2de8deb0927eb68dbc5986e1fbbd0a1359f8a74 (diff)
downloadrust-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.rs9
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,