From 041d97f4fdd625ca193e29f389f754904441aa04 Mon Sep 17 00:00:00 2001 From: iximeow Date: Thu, 12 Mar 2020 19:53:13 -0700 Subject: [PATCH 1/3] unix: Set a guard page at the end of signal stacks This mitigates possible issues when signal stacks overflow, which could manifest as segfaults or in unlucky circumstances possible clobbering of other memory values as stack overflows tend to enable. --- src/libstd/sys/unix/stack_overflow.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 9e8be55075578..db42e11683ad8 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -45,7 +45,7 @@ mod imp { use libc::{mmap, munmap}; use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL}; use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; - use libc::{MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE, SIGSEGV}; + use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV}; use crate::sys_common::thread_info; @@ -137,11 +137,16 @@ mod imp { } unsafe fn get_stackp() -> *mut libc::c_void { + let page_size = crate::sys::unix::os::page_size(); let stackp = - mmap(ptr::null_mut(), SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + mmap(ptr::null_mut(), SIGSTKSZ + page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack"); } + let guard_result = libc::mprotect(stackp, page_size, PROT_NONE); + if guard_result != 0 { + panic!("failed to set up alternative stack guard page"); + } stackp } From 0ca2ed364662351da9e8a1f4ba54e027e1f420df Mon Sep 17 00:00:00 2001 From: iximeow Date: Thu, 12 Mar 2020 21:17:10 -0700 Subject: [PATCH 2/3] return a pointer to the end of the valid part of the sigstack, no further also unmap the whole thing when cleaning up, rather than leaving a spare page floating around. --- src/libstd/sys/unix/stack_overflow.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index db42e11683ad8..c4d771d75d967 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -47,6 +47,7 @@ mod imp { use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV}; + use crate::sys::unix::os::page_size; use crate::sys_common::thread_info; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -137,17 +138,16 @@ mod imp { } unsafe fn get_stackp() -> *mut libc::c_void { - let page_size = crate::sys::unix::os::page_size(); let stackp = - mmap(ptr::null_mut(), SIGSTKSZ + page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack"); } - let guard_result = libc::mprotect(stackp, page_size, PROT_NONE); + let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE); if guard_result != 0 { panic!("failed to set up alternative stack guard page"); } - stackp + stackp.add(page_size()) } #[cfg(any( @@ -195,7 +195,9 @@ mod imp { ss_size: SIGSTKSZ, }; sigaltstack(&stack, ptr::null_mut()); - munmap(handler._data, SIGSTKSZ); + // We know from `get_stackp` that the alternate stack we installed is part of a mapping + // that started one page earlier, so walk back a page and unmap from there. + munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size()); } } } From 28eeea630faf1e7514da96c5eedd67e330fe8571 Mon Sep 17 00:00:00 2001 From: iximeow Date: Thu, 12 Mar 2020 22:21:36 -0700 Subject: [PATCH 3/3] fix formatting --- src/libstd/sys/unix/stack_overflow.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index c4d771d75d967..2626ca37cf8b8 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -138,8 +138,14 @@ mod imp { } unsafe fn get_stackp() -> *mut libc::c_void { - let stackp = - mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + let stackp = mmap( + ptr::null_mut(), + SIGSTKSZ + page_size(), + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + -1, + 0, + ); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack"); }