Skip to content

Commit 3050ff8

Browse files
committed
Fix bugs with signal handling
* Fix signature of signal handler function (takes pointer to siginfo_t instead of value) * Allocate a bigger stack size to make sure to avoid stack overflows * Fix memory leak of the stack that was set up for the handler
1 parent d9b66e0 commit 3050ff8

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

fuzzcheck/src/fuzzer.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,19 @@ struct FuzzerState<T: Clone + 'static, M: Mutator<T>> {
163163
/// The world handles effects
164164
world: World,
165165
rng: fastrand::Rng,
166+
167+
signal_handler_alt_stack: Option<(*mut u8, std::alloc::Layout)>,
166168
}
167169

168170
impl<T: Clone + 'static, M: Mutator<T>> Drop for FuzzerState<T, M> {
169171
#[no_coverage]
170172
fn drop(&mut self) {
171-
unsafe { crate::signals_handler::reset_signal_handlers() };
173+
unsafe {
174+
crate::signals_handler::reset_signal_handlers();
175+
if let Some((stack_ptr, stack_layout)) = self.signal_handler_alt_stack {
176+
std::alloc::dealloc(stack_ptr, stack_layout);
177+
}
178+
}
172179
}
173180
}
174181

@@ -268,10 +275,11 @@ where
268275
#[no_coverage]
269276
unsafe fn set_up_signal_handler(&mut self) {
270277
let ptr = self as *mut Self;
271-
set_signal_handlers(
278+
let (stack_ptr, stack_size) = set_signal_handlers(
272279
#[no_coverage]
273280
move |sig| (*ptr).receive_signal(sig),
274281
);
282+
self.signal_handler_alt_stack = Some((stack_ptr, stack_size));
275283
}
276284
}
277285

@@ -313,6 +321,7 @@ where
313321
serializer,
314322
world,
315323
rng: fastrand::Rng::new(),
324+
signal_handler_alt_stack: None,
316325
},
317326
test,
318327
}

fuzzcheck/src/signals_handler.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use libc::{
1111
static mut SIGNAL_HANDLER: Option<Box<dyn Fn(libc::c_int) -> !>> = None;
1212

1313
#[no_coverage]
14-
extern "C" fn os_handler(signal: libc::c_int, _: libc::siginfo_t, _: *mut libc::c_void) {
14+
extern "C" fn os_handler(signal: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {
1515
// Assuming this always succeeds. Can't really handle errors in any meaningful way.
1616
unsafe {
1717
reset_signal_handlers();
@@ -23,26 +23,28 @@ extern "C" fn os_handler(signal: libc::c_int, _: libc::siginfo_t, _: *mut libc::
2323
}
2424
}
2525

26+
/// Set signal handlers to the given function and return the pointer and layout
27+
/// of the alternative stack used by the signal handlers.
2628
#[no_coverage]
27-
pub unsafe fn set_signal_handlers<F: 'static>(f: F)
29+
pub unsafe fn set_signal_handlers<F: 'static>(f: F) -> (*mut u8, std::alloc::Layout)
2830
where
2931
F: Fn(libc::c_int) -> !,
3032
{
3133
SIGNAL_HANDLER = Some(Box::new(f));
3234

33-
let stack_size = libc::SIGSTKSZ;
34-
35-
let stack_pointer = std::alloc::alloc_zeroed(std::alloc::Layout::array::<std::ffi::c_void>(stack_size).unwrap())
36-
as *mut std::ffi::c_void;
35+
// Make sure the alternative stack is big enough. ~65_000 bytes should be okay.
36+
let stack_size = std::cmp::max(libc::SIGSTKSZ, 0b1 << 16);
37+
let stack_layout = std::alloc::Layout::array::<u8>(stack_size).unwrap();
38+
let stack_pointer = std::alloc::alloc_zeroed(stack_layout);
3739

3840
let signal_stack = libc::stack_t {
39-
ss_sp: stack_pointer,
41+
ss_sp: stack_pointer as *mut std::ffi::c_void,
4042
ss_size: stack_size,
4143
ss_flags: 0,
4244
};
4345

4446
let stack = libc::sigaltstack(&signal_stack, std::ptr::null_mut());
45-
if stack == -1 {
47+
if stack < 0 {
4648
panic!("could not set alternate stack for handling signals");
4749
}
4850

@@ -60,6 +62,8 @@ where
6062
panic!("Could not set up signal handler");
6163
}
6264
}
65+
66+
(stack_pointer, stack_layout)
6367
}
6468

6569
#[no_coverage]

0 commit comments

Comments
 (0)