Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/arch/arm64/proc/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _;
Expand Down
11 changes: 9 additions & 2 deletions src/sched/current.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -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);
}
}

Expand All @@ -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();
Expand Down
60 changes: 60 additions & 0 deletions usertest/src/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Loading