mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-04-18 22:28:16 -04:00
segfault properly
This commit is contained in:
@@ -10,6 +10,7 @@ use crate::{
|
||||
memory::uaccess::UAccessResult,
|
||||
},
|
||||
memory::fault::{FaultResolution, handle_demand_fault, handle_protection_fault},
|
||||
process::thread_group::signal::SigId,
|
||||
sched::{current::current_task, spawn_kernel_work},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
@@ -119,15 +120,8 @@ pub fn handle_kernel_mem_fault(exception: Exception, info: AbortIss, state: &mut
|
||||
pub fn handle_mem_fault(exception: Exception, info: AbortIss) {
|
||||
match run_mem_fault_handler(exception, info) {
|
||||
Ok(FaultResolution::Resolved) => {}
|
||||
// TODO: Implement proc signals.
|
||||
Ok(FaultResolution::Denied) => {
|
||||
let task = current_task();
|
||||
panic!(
|
||||
"SIGSEGV on process {} {:?} PC: {:x}",
|
||||
task.process.tgid,
|
||||
exception,
|
||||
task.ctx.user().elr_el1
|
||||
)
|
||||
current_task().process.deliver_signal(SigId::SIGSEGV);
|
||||
}
|
||||
// If the page fault involves sleepy kernel work, we can
|
||||
// spawn that work on the process, since there is no other
|
||||
|
||||
@@ -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 _;
|
||||
|
||||
@@ -17,6 +17,7 @@ per_cpu_private! {
|
||||
pub(super) struct CurrentTaskPtr {
|
||||
pub(super) ptr: Cell<*mut OwnedTask>,
|
||||
pub(super) borrowed: Cell<bool>,
|
||||
pub location: Cell<Option<core::panic::Location<'static>>>,
|
||||
}
|
||||
|
||||
unsafe impl Send for CurrentTaskPtr {}
|
||||
@@ -51,15 +52,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();
|
||||
|
||||
@@ -194,6 +194,53 @@ fn test_mincore() {
|
||||
|
||||
register_test!(test_mincore);
|
||||
|
||||
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 run_test(test_fn: fn()) -> Result<(), i32> {
|
||||
// Fork a new process to run the test
|
||||
unsafe {
|
||||
|
||||
Reference in New Issue
Block a user