Skip to content

Commit 9e11e01

Browse files
unix: Unsafe-wrap stack_overflow::{drop,make}_handler
Note that current_guard is probably not unsafe for future work.
1 parent 72c7444 commit 9e11e01

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

std/src/sys/pal/unix/stack_overflow.rs

+27-10
Original file line numberDiff line numberDiff line change
@@ -206,34 +206,48 @@ mod imp {
206206
libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
207207
}
208208

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

214217
if !main_thread {
215218
// Always write to GUARD to ensure the TLS variable is allocated.
216-
let guard = current_guard().unwrap_or(0..0);
219+
let guard = unsafe { current_guard() }.unwrap_or(0..0);
217220
GUARD.set((guard.start, guard.end));
218221
}
219222

220-
let mut stack = mem::zeroed();
221-
sigaltstack(ptr::null(), &mut stack);
223+
// SAFETY: assuming stack_t is zero-initializable
224+
let mut stack = unsafe { mem::zeroed() };
225+
// SAFETY: reads current stack_t into stack
226+
unsafe { sigaltstack(ptr::null(), &mut stack) };
222227
// Configure alternate signal stack, if one is not already set.
223228
if stack.ss_flags & SS_DISABLE != 0 {
224-
stack = get_stack();
225-
sigaltstack(&stack, ptr::null_mut());
229+
// SAFETY: We warned our caller this would happen!
230+
unsafe {
231+
stack = get_stack();
232+
sigaltstack(&stack, ptr::null_mut());
233+
}
226234
Handler { data: stack.ss_sp as *mut libc::c_void }
227235
} else {
228236
Handler::null()
229237
}
230238
}
231239

240+
/// # Safety
241+
/// Must be called
242+
/// - only with our handler or nullptr
243+
/// - only when done with our altstack
244+
/// This disables the alternate signal stack!
245+
#[forbid(unsafe_op_in_unsafe_fn)]
232246
pub unsafe fn drop_handler(data: *mut libc::c_void) {
233247
if !data.is_null() {
234248
let sigstack_size = sigstack_size();
235249
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
236-
let stack = libc::stack_t {
250+
let disabling_stack = libc::stack_t {
237251
ss_sp: ptr::null_mut(),
238252
ss_flags: SS_DISABLE,
239253
// Workaround for bug in macOS implementation of sigaltstack
@@ -242,10 +256,11 @@ mod imp {
242256
// both ss_sp and ss_size should be ignored in this case.
243257
ss_size: sigstack_size,
244258
};
245-
sigaltstack(&stack, ptr::null_mut());
246-
// We know from `get_stackp` that the alternate stack we installed is part of a mapping
247-
// that started one page earlier, so walk back a page and unmap from there.
248-
munmap(data.sub(page_size), sigstack_size + page_size);
259+
// SAFETY: we warned the caller this disables the alternate signal stack!
260+
unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
261+
// SAFETY: We know from `get_stackp` that the alternate stack we installed is part of
262+
// a mapping that started one page earlier, so walk back a page and unmap from there.
263+
unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
249264
}
250265
}
251266

@@ -446,6 +461,7 @@ mod imp {
446461
}
447462

448463
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
464+
// FIXME: I am probably not unsafe.
449465
unsafe fn current_guard() -> Option<Range<usize>> {
450466
let stackptr = get_stack_start()?;
451467
let stackaddr = stackptr.addr();
@@ -460,6 +476,7 @@ mod imp {
460476
target_os = "netbsd",
461477
target_os = "l4re"
462478
))]
479+
// FIXME: I am probably not unsafe.
463480
unsafe fn current_guard() -> Option<Range<usize>> {
464481
let mut ret = None;
465482
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();

0 commit comments

Comments
 (0)