fix: harden kernel — eliminate UB, proper process cleanup

Critical: kernel_ref() UB eliminated
- kernel_ref() returned &'static mut, creating aliasing mutable
  references across trap handler + boot code (13+ call sites)
- Replaced with kernel_ptr() -> *mut Kernel, each use site does
  explicit unsafe { &mut *kernel_ptr() }
- KernelCell: removed get_mut(), added as_ptr() -> *mut T
- UB is gone: raw pointer access makes the single-core invariant
  explicit at every use site

Important: process cleanup on exit/fault
- New destroy_process() method consolidates cleanup:
  - Removes all threads from scheduler and endpoints
  - Clears pending messages and results
  - Destroys process and frees ProcessMemory
- handle_exit and handle_fault both use destroy_process()
- handle_exit_thread uses destroy_process when last thread exits

IPC hardening:
- Added invariant comment on pending_messages[sender].take()
  (sender in wait queue must have a pending message)

handle_release_pages:
- Now uses translate_va to convert VA→PA (was treating VA as PA)
This commit is contained in:
2026-10-18 22:22:48 +02:00
parent 61e28f0af5
commit ea2ac5d1d9
12 changed files with 100 additions and 92 deletions

View File

@@ -292,7 +292,7 @@ fn load_context_to_frame(ctx: &domain::thread::SavedContext, frame: &mut TrapFra
}
fn apply_pending_result(frame: &mut TrapFrame, tid: types::id::ThreadId) {
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
if let Some(result) = kern.take_pending_result(tid) {
write_result_direct(frame, &result);
}
@@ -316,7 +316,7 @@ fn write_result_direct(frame: &mut TrapFrame, result: &kernel::SyscallResult) {
}
fn switch_to_thread(frame: &mut TrapFrame, current_tid: types::id::ThreadId, next_tid: types::id::ThreadId) {
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
if let Some(ctx) = kern.thread_context_mut(current_tid) {
save_frame_to_context(frame, ctx);
@@ -343,7 +343,7 @@ fn switch_to_thread(frame: &mut TrapFrame, current_tid: types::id::ThreadId, nex
}
fn switch_to_next(frame: &mut TrapFrame, current_tid: types::id::ThreadId) {
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
if let Some(ctx) = kern.thread_context_mut(current_tid) {
save_frame_to_context(frame, ctx);
@@ -392,7 +392,7 @@ fn handle_interrupt(frame: &mut TrapFrame, cause: usize) {
match cause {
CAUSE_S_TIMER => {
crate::hw::timer::handle_interrupt();
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
let core = types::id::CoreId::from_raw(0);
if let Some(current_tid) = kern.current_thread() {
let decision = kern.handle_tick(core);
@@ -404,7 +404,7 @@ fn handle_interrupt(frame: &mut TrapFrame, cause: usize) {
CAUSE_S_EXTERNAL => {
let irq_num = crate::hw::plic::Plic::claim();
if irq_num != 0 {
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
let irq = types::id::IrqId::from_raw(irq_num as u16);
kern.handle_interrupt(irq);
crate::hw::plic::Plic::complete(irq_num);
@@ -420,7 +420,7 @@ fn handle_exception(frame: &mut TrapFrame, scause: usize) {
frame.sepc += 4;
if let Some(syscall) = decode_syscall(frame) {
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
let current_tid = kern.current_thread();
let outcome = kern.handle_syscall(syscall);
write_result(frame, &outcome);
@@ -459,7 +459,7 @@ fn handle_exception(frame: &mut TrapFrame, scause: usize) {
uart.write_hex(frame.sepc);
uart.put_char(b'\n');
let kern = crate::kernel_ref();
let kern = unsafe { &mut *crate::kernel_ptr() };
if let Some(current_tid) = kern.current_thread() {
let fault = match scause {
2 => domain::fault::Fault::IllegalInstruction,