unix: Unsafe-wrap stack_overflow::{drop,make}_handler
Note that current_guard is probably not unsafe for future work.
This commit is contained in:
parent
fa628ceaff
commit
c1740eee1e
1 changed files with 27 additions and 10 deletions
|
@ -206,6 +206,9 @@ mod imp {
|
||||||
libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
|
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 {
|
pub unsafe fn make_handler(main_thread: bool) -> Handler {
|
||||||
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
|
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
|
||||||
return Handler::null();
|
return Handler::null();
|
||||||
|
@ -213,27 +216,38 @@ mod imp {
|
||||||
|
|
||||||
if !main_thread {
|
if !main_thread {
|
||||||
// Always write to GUARD to ensure the TLS variable is allocated.
|
// 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));
|
GUARD.set((guard.start, guard.end));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stack = mem::zeroed();
|
// SAFETY: assuming stack_t is zero-initializable
|
||||||
sigaltstack(ptr::null(), &mut stack);
|
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.
|
// Configure alternate signal stack, if one is not already set.
|
||||||
if stack.ss_flags & SS_DISABLE != 0 {
|
if stack.ss_flags & SS_DISABLE != 0 {
|
||||||
stack = get_stack();
|
// SAFETY: We warned our caller this would happen!
|
||||||
sigaltstack(&stack, ptr::null_mut());
|
unsafe {
|
||||||
|
stack = get_stack();
|
||||||
|
sigaltstack(&stack, ptr::null_mut());
|
||||||
|
}
|
||||||
Handler { data: stack.ss_sp as *mut libc::c_void }
|
Handler { data: stack.ss_sp as *mut libc::c_void }
|
||||||
} else {
|
} else {
|
||||||
Handler::null()
|
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) {
|
pub unsafe fn drop_handler(data: *mut libc::c_void) {
|
||||||
if !data.is_null() {
|
if !data.is_null() {
|
||||||
let sigstack_size = sigstack_size();
|
let sigstack_size = sigstack_size();
|
||||||
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
|
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_sp: ptr::null_mut(),
|
||||||
ss_flags: SS_DISABLE,
|
ss_flags: SS_DISABLE,
|
||||||
// Workaround for bug in macOS implementation of sigaltstack
|
// Workaround for bug in macOS implementation of sigaltstack
|
||||||
|
@ -242,10 +256,11 @@ mod imp {
|
||||||
// both ss_sp and ss_size should be ignored in this case.
|
// both ss_sp and ss_size should be ignored in this case.
|
||||||
ss_size: sigstack_size,
|
ss_size: sigstack_size,
|
||||||
};
|
};
|
||||||
sigaltstack(&stack, ptr::null_mut());
|
// SAFETY: we warned the caller this disables the alternate signal stack!
|
||||||
// We know from `get_stackp` that the alternate stack we installed is part of a mapping
|
unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
|
||||||
// that started one page earlier, so walk back a page and unmap from there.
|
// SAFETY: We know from `get_stackp` that the alternate stack we installed is part of
|
||||||
munmap(data.sub(page_size), sigstack_size + page_size);
|
// 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) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,6 +461,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
|
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
|
||||||
|
// FIXME: I am probably not unsafe.
|
||||||
unsafe fn current_guard() -> Option<Range<usize>> {
|
unsafe fn current_guard() -> Option<Range<usize>> {
|
||||||
let stackptr = get_stack_start()?;
|
let stackptr = get_stack_start()?;
|
||||||
let stackaddr = stackptr.addr();
|
let stackaddr = stackptr.addr();
|
||||||
|
@ -460,6 +476,7 @@ mod imp {
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "l4re"
|
target_os = "l4re"
|
||||||
))]
|
))]
|
||||||
|
// FIXME: I am probably not unsafe.
|
||||||
unsafe fn current_guard() -> Option<Range<usize>> {
|
unsafe fn current_guard() -> Option<Range<usize>> {
|
||||||
let mut ret = None;
|
let mut ret = None;
|
||||||
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
|
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue