Skip to content

Commit a17ad3b

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

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

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

+22-10
Original file line numberDiff line numberDiff line change
@@ -206,34 +206,45 @@ 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 only be called with our handler or nullptr, and only when done with our altstack
242+
#[forbid(unsafe_op_in_unsafe_fn)]
232243
pub unsafe fn drop_handler(data: *mut libc::c_void) {
233244
if !data.is_null() {
234245
let sigstack_size = sigstack_size();
235246
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
236-
let stack = libc::stack_t {
247+
let disabling_stack = libc::stack_t {
237248
ss_sp: ptr::null_mut(),
238249
ss_flags: SS_DISABLE,
239250
// Workaround for bug in macOS implementation of sigaltstack
@@ -242,10 +253,11 @@ mod imp {
242253
// both ss_sp and ss_size should be ignored in this case.
243254
ss_size: sigstack_size,
244255
};
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);
256+
// SAFETY: we warned the caller this disables the alternate signal stack!
257+
unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
258+
// SAFETY: We know from `get_stackp` that the alternate stack we installed is part of
259+
// a mapping that started one page earlier, so walk back a page and unmap from there.
260+
unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
249261
}
250262
}
251263

0 commit comments

Comments
 (0)