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

@@ -1,7 +1,10 @@
use crate::hw::uart::Uart;
use crate::kernel_ref;
use types::id::ProcessId;
fn kern() -> &'static mut kernel::Kernel<crate::platform::RiscVPlatform> {
unsafe { &mut *crate::kernel_ptr() }
}
pub fn grant_all(
uart: &Uart,
init_pid: ProcessId,
@@ -19,48 +22,37 @@ pub fn grant_all(
.with(types::permission::Permission::Read)
.with(types::permission::Permission::Execute);
// Storage endpoint
let storage_ep = kernel_ref().create_endpoint()
let storage_ep = kern().create_endpoint()
.unwrap_or_else(|_| crate::halt(uart, "storage endpoint failed"));
// Init: slot 0 = ProcessCreate (from boot)
// slot 1 = Process(storage)
// slot 2 = Endpoint(storage)
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Process(storage_pid), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Process(storage_pid), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Endpoint(storage_ep), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Endpoint(storage_ep), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
// Storage: slot 0 = Endpoint
kernel_ref().grant_capability(storage_pid, domain::resource::Resource::Endpoint(storage_ep), ipc_perms)
kern().grant_capability(storage_pid, domain::resource::Resource::Endpoint(storage_ep), ipc_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
// Display endpoint
let display_ep = kernel_ref().create_endpoint()
let display_ep = kern().create_endpoint()
.unwrap_or_else(|_| crate::halt(uart, "display endpoint failed"));
// Display: slot 0 = Endpoint
kernel_ref().grant_capability(display_pid, domain::resource::Resource::Endpoint(display_ep), ipc_perms)
kern().grant_capability(display_pid, domain::resource::Resource::Endpoint(display_ep), ipc_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
// Init: slot 3 = Endpoint(display), slot 4 = Process(display)
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Endpoint(display_ep), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Endpoint(display_ep), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Process(display_pid), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Process(display_pid), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
// Input endpoint
let input_ep = kernel_ref().create_endpoint()
let input_ep = kern().create_endpoint()
.unwrap_or_else(|_| crate::halt(uart, "input endpoint failed"));
// Input: slot 0 = Endpoint
kernel_ref().grant_capability(input_pid, domain::resource::Resource::Endpoint(input_ep), ipc_perms)
kern().grant_capability(input_pid, domain::resource::Resource::Endpoint(input_ep), ipc_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
// Init: slot 5 = Endpoint(input), slot 6 = Process(input)
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Endpoint(input_ep), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Endpoint(input_ep), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
kernel_ref().grant_capability(init_pid, domain::resource::Resource::Process(input_pid), all_perms)
kern().grant_capability(init_pid, domain::resource::Resource::Process(input_pid), all_perms)
.unwrap_or_else(|_| crate::halt(uart, "grant failed"));
uart.write_str("k-os: capabilities granted\n");