Merge pull request #241 from TroyNeubauer/handle-sigsev

This commit is contained in:
Matthew Leach
2026-03-02 06:17:23 +00:00
committed by GitHub
3 changed files with 72 additions and 2 deletions

View File

@@ -56,6 +56,9 @@ pub async fn do_signal(id: SigId, sa: UserspaceSigAction) -> Result<ExceptionSta
.align(PAGE_SIZE)
};
drop(signal);
drop(task);
copy_to_user(addr, frame).await?;
new_state.sp_el0 = addr.value() as _;

View File

@@ -17,6 +17,7 @@ per_cpu_private! {
pub(super) struct CurrentTaskPtr {
pub(super) ptr: Cell<*mut OwnedTask>,
pub(super) borrowed: Cell<bool>,
location: Cell<Option<core::panic::Location<'static>>>,
}
unsafe impl Send for CurrentTaskPtr {}
@@ -42,7 +43,9 @@ impl DerefMut for CurrentTaskGuard<'_> {
impl<'a> Drop for CurrentTaskGuard<'a> {
fn drop(&mut self) {
CUR_TASK_PTR.borrow().borrowed.set(false);
let current = CUR_TASK_PTR.borrow();
current.borrowed.set(false);
current.location.set(None);
}
}
@@ -51,15 +54,19 @@ impl CurrentTaskPtr {
Self {
ptr: Cell::new(ptr::null_mut()),
borrowed: Cell::new(false),
location: Cell::new(None),
}
}
#[track_caller]
pub fn current(&self) -> CurrentTaskGuard<'static> {
if self.borrowed.get() {
panic!("Double mutable borrow of current task!");
let other = self.location.take();
panic!("Double mutable borrow of current task! Borrowed from: {other:?}");
}
self.borrowed.set(true);
self.location.set(Some(*core::panic::Location::caller()));
unsafe {
let ptr = self.ptr.get();

View File

@@ -157,3 +157,63 @@ fn test_interruptible_waitpid() {
}
register_test!(test_interruptible_waitpid);
fn segfault_child(inner: impl FnOnce()) {
unsafe {
let pid = libc::fork();
if pid < 0 {
panic!("fork failed");
} else if pid == 0 {
// Child process
inner()
} else {
// Parent process
let mut status = 0;
let rusage = std::ptr::null_mut();
libc::wait4(pid, &mut status, 0, rusage);
assert!(libc::WIFSIGNALED(status));
assert_eq!(libc::WTERMSIG(status), libc::SIGSEGV);
}
}
}
fn test_segfault_read() {
segfault_child(|| {
let addr: *const u8 = std::hint::black_box(std::ptr::null());
let _ = unsafe { std::ptr::read(addr) };
});
segfault_child(|| {
// Ensure reading from kernel stack fails
let addr = 0xffff_ba00_0000_0000 as *const u8;
let _ = unsafe { std::ptr::read(addr) };
});
}
register_test!(test_segfault_read);
fn test_segfault_write() {
segfault_child(|| {
let addr: *mut u8 = std::hint::black_box(std::ptr::null_mut());
unsafe { std::ptr::write(addr, 42) };
});
segfault_child(|| {
let addr = 0xffff_ba00_0000_0000 as *mut u8;
unsafe { std::ptr::write(addr, 42) };
});
}
register_test!(test_segfault_write);
fn rust_stack_overflow() {
segfault_child(|| {
#[allow(unconditional_recursion)]
fn recurse(n: usize) -> usize {
let m = std::hint::black_box(n) + 1;
recurse(m)
}
recurse(0);
});
}
register_test!(rust_stack_overflow);