Skip to content

Commit 33a32f2

Browse files
unix: lift init of sigaltstack before sigaction
This is technically "not necessary", as we will "just" segfault instead if we e.g. arrive inside the handler fn with the null altstack. However, it seems incorrect to go about this hoping that segfaulting is okay, seeing as how our purpose here is to mitigate stack overflow problems. Make sure NEED_ALTSTACK syncs with PAGE_SIZE when we do. Co-authored-by: Jonas Böttiger <[email protected]>
1 parent 9fb6e49 commit 33a32f2

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

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

+17-9
Original file line numberDiff line numberDiff line change
@@ -123,28 +123,36 @@ mod imp {
123123
static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
124124
static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
125125

126+
/// # Safety
127+
/// Must be called only once
128+
#[forbid(unsafe_op_in_unsafe_fn)]
126129
pub unsafe fn init() {
127130
PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
128131

129132
// Always write to GUARD to ensure the TLS variable is allocated.
130-
let guard = install_main_guard().unwrap_or(0..0);
133+
let guard = unsafe { install_main_guard().unwrap_or(0..0) };
131134
GUARD.set((guard.start, guard.end));
132135

133-
let mut action: sigaction = mem::zeroed();
136+
// SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
137+
let mut action: sigaction = unsafe { mem::zeroed() };
134138
for &signal in &[SIGSEGV, SIGBUS] {
135-
sigaction(signal, ptr::null_mut(), &mut action);
139+
// SAFETY: just fetches the current signal handler into action
140+
unsafe { sigaction(signal, ptr::null_mut(), &mut action) };
136141
// Configure our signal handler if one is not already set.
137142
if action.sa_sigaction == SIG_DFL {
143+
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
144+
// haven't set up our sigaltstack yet
145+
NEED_ALTSTACK.store(true, Ordering::Release);
146+
let handler = unsafe { make_handler(true) };
147+
MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
148+
mem::forget(handler);
149+
}
138150
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
139151
action.sa_sigaction = signal_handler as sighandler_t;
140-
sigaction(signal, &action, ptr::null_mut());
141-
NEED_ALTSTACK.store(true, Ordering::Relaxed);
152+
// SAFETY: only overriding signals if the default is set
153+
unsafe { sigaction(signal, &action, ptr::null_mut()) };
142154
}
143155
}
144-
145-
let handler = make_handler(true);
146-
MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
147-
mem::forget(handler);
148156
}
149157

150158
pub unsafe fn cleanup() {

0 commit comments

Comments
 (0)