Skip to content

Commit eea90e8

Browse files
unix: Unsafe-wrap stack_overflow::{drop,make}_handler
1 parent c496f05 commit eea90e8

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

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

+25-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

0 commit comments

Comments
 (0)