Skip to content

Commit

Permalink
unix: Unsafe-wrap stack_overflow::{drop,make}_handler
Browse files Browse the repository at this point in the history
Note that current_guard is probably not unsafe for future work.
  • Loading branch information
workingjubilee committed Jul 18, 2024
1 parent 72c7444 commit 9e11e01
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions std/src/sys/pal/unix/stack_overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,34 +206,48 @@ mod imp {
libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
}

/// # Safety
/// Mutates the alternate signal stack
#[forbid(unsafe_op_in_unsafe_fn)]
pub unsafe fn make_handler(main_thread: bool) -> Handler {
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
return Handler::null();
}

if !main_thread {
// Always write to GUARD to ensure the TLS variable is allocated.
let guard = current_guard().unwrap_or(0..0);
let guard = unsafe { current_guard() }.unwrap_or(0..0);
GUARD.set((guard.start, guard.end));
}

let mut stack = mem::zeroed();
sigaltstack(ptr::null(), &mut stack);
// SAFETY: assuming stack_t is zero-initializable
let mut stack = unsafe { mem::zeroed() };
// SAFETY: reads current stack_t into stack
unsafe { sigaltstack(ptr::null(), &mut stack) };
// Configure alternate signal stack, if one is not already set.
if stack.ss_flags & SS_DISABLE != 0 {
stack = get_stack();
sigaltstack(&stack, ptr::null_mut());
// SAFETY: We warned our caller this would happen!
unsafe {
stack = get_stack();
sigaltstack(&stack, ptr::null_mut());
}
Handler { data: stack.ss_sp as *mut libc::c_void }
} else {
Handler::null()
}
}

/// # Safety
/// Must be called
/// - only with our handler or nullptr
/// - only when done with our altstack
/// This disables the alternate signal stack!
#[forbid(unsafe_op_in_unsafe_fn)]
pub unsafe fn drop_handler(data: *mut libc::c_void) {
if !data.is_null() {
let sigstack_size = sigstack_size();
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
let stack = libc::stack_t {
let disabling_stack = libc::stack_t {
ss_sp: ptr::null_mut(),
ss_flags: SS_DISABLE,
// Workaround for bug in macOS implementation of sigaltstack
Expand All @@ -242,10 +256,11 @@ mod imp {
// both ss_sp and ss_size should be ignored in this case.
ss_size: sigstack_size,
};
sigaltstack(&stack, ptr::null_mut());
// 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(data.sub(page_size), sigstack_size + page_size);
// SAFETY: we warned the caller this disables the alternate signal stack!
unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
// SAFETY: 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.
unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
}
}

Expand Down Expand Up @@ -446,6 +461,7 @@ mod imp {
}

#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
// FIXME: I am probably not unsafe.
unsafe fn current_guard() -> Option<Range<usize>> {
let stackptr = get_stack_start()?;
let stackaddr = stackptr.addr();
Expand All @@ -460,6 +476,7 @@ mod imp {
target_os = "netbsd",
target_os = "l4re"
))]
// FIXME: I am probably not unsafe.
unsafe fn current_guard() -> Option<Range<usize>> {
let mut ret = None;
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
Expand Down

0 comments on commit 9e11e01

Please sign in to comment.