fix: critical privilege escalation + resource leak hardening

CRITICAL — MapPage privilege escalation:
  handle_map_page allowed mapping kernel memory (VA >= 0x80000000)
  into userspace. Any process with a Process capability could read/
  write kernel data structures. Fixed: reject src_va >= USER_VA_LIMIT.

HIGH — resource leaks:
  handle_kill: leaked pages (used cleanup_threads directly instead
    of destroy_process). Now uses destroy_process for full cleanup.
  handle_create_process: orphaned process on cap grant failure.
    Now destroys process on rollback.
  handle_create_endpoint: orphaned endpoint on cap grant failure.
    Now destroys endpoint on rollback.
  Thread ID array: hardcoded [None; 4] replaced with
    [None; MAX_THREADS_PER_PROCESS] slice. cleanup_threads now
    takes &[Option<ThreadId>] slice.

MEDIUM — quality fixes:
  handle_request_pages: replaced unreachable!() with proper error
    return + page pool rollback.
This commit is contained in:
2026-10-18 22:39:16 +02:00
parent d009818caf
commit 06863c84fa
4 changed files with 41 additions and 39 deletions

View File

@@ -218,12 +218,13 @@ impl<P: Platform> Kernel<P> {
}
pub(crate) fn destroy_process(&mut self, pid: ProcessId) {
// Collect thread IDs before cleanup
let thread_ids: [Option<ThreadId>; 4] = match self.processes.get(pid) {
use domain::process::MAX_THREADS_PER_PROCESS;
let thread_ids: [Option<ThreadId>; MAX_THREADS_PER_PROCESS] = match self.processes.get(pid) {
Ok(p) => {
let mut ids = [None; 4];
let mut ids = [None; MAX_THREADS_PER_PROCESS];
for (i, tid) in p.thread_ids().enumerate() {
if i < 4 { ids[i] = Some(tid); }
if i < MAX_THREADS_PER_PROCESS { ids[i] = Some(tid); }
}
ids
}
@@ -250,7 +251,7 @@ impl<P: Platform> Kernel<P> {
self.process_memory[pid.raw() as usize] = None;
}
pub(crate) fn cleanup_threads(&mut self, thread_ids: &[Option<ThreadId>; 4]) {
pub(crate) fn cleanup_threads(&mut self, thread_ids: &[Option<ThreadId>]) {
use domain::scheduler::Scheduler;
for slot in thread_ids {
if let Some(tid) = slot {