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:
@@ -1,6 +1,6 @@
|
||||
use crate::hw::uart::Uart;
|
||||
use crate::hw::virtio_blk::VirtioBlk;
|
||||
use crate::{board, boot_fs, kernel_ref, mmu};
|
||||
use crate::{boot_fs, mmu};
|
||||
use types::id::{ProcessId, ThreadId};
|
||||
|
||||
const USER_VA_BASE: usize = 0x10000;
|
||||
@@ -11,12 +11,16 @@ pub struct LoadedProcess {
|
||||
pub entry: usize,
|
||||
}
|
||||
|
||||
fn kern() -> &'static mut kernel::Kernel<crate::platform::RiscVPlatform> {
|
||||
unsafe { &mut *crate::kernel_ptr() }
|
||||
}
|
||||
|
||||
pub fn load_init(
|
||||
uart: &Uart,
|
||||
blk: &mut VirtioBlk,
|
||||
kernel_pt: &mmu::PageTable,
|
||||
) -> (LoadedProcess, ThreadId) {
|
||||
let (pid, tid) = kernel_ref()
|
||||
let (pid, tid) = kern()
|
||||
.boot(types::bounded::Priority::DEFAULT, types::time::TimeSlice::DEFAULT)
|
||||
.unwrap_or_else(|_| crate::halt(uart, "boot failed"));
|
||||
|
||||
@@ -35,11 +39,11 @@ pub fn load_server(
|
||||
filename: &[u8],
|
||||
label: &str,
|
||||
) -> LoadedProcess {
|
||||
let pid = kernel_ref().create_process_internal()
|
||||
let pid = kern().create_process_internal()
|
||||
.unwrap_or_else(|| crate::halt(uart, "process create failed"));
|
||||
let entry = load_elf(blk, kernel_pt, pid, filename);
|
||||
if entry == 0 { crate::halt(uart, "elf not found"); }
|
||||
let tid = kernel_ref().spawn_thread_internal(pid)
|
||||
let tid = kern().spawn_thread_internal(pid)
|
||||
.unwrap_or_else(|| crate::halt(uart, "thread spawn failed"));
|
||||
setup_thread(tid, entry);
|
||||
uart.write_str("k-os: ");
|
||||
@@ -50,8 +54,7 @@ pub fn load_server(
|
||||
}
|
||||
|
||||
pub fn enter_userspace(pid: ProcessId, entry: usize, shared_buf_va: usize) -> ! {
|
||||
let kern = kernel_ref();
|
||||
let pt_addr = kern.platform_mut().page_table_for(pid);
|
||||
let pt_addr = kern().platform_mut().page_table_for(pid);
|
||||
if pt_addr != 0 {
|
||||
mmu::activate(unsafe { &*(pt_addr as *const mmu::PageTable) });
|
||||
}
|
||||
@@ -79,7 +82,7 @@ pub fn enter_userspace(pid: ProcessId, entry: usize, shared_buf_va: usize) -> !
|
||||
}
|
||||
|
||||
fn setup_thread(tid: ThreadId, entry: usize) {
|
||||
if let Some(ctx) = kernel_ref().thread_context_mut(tid) {
|
||||
if let Some(ctx) = kern().thread_context_mut(tid) {
|
||||
ctx.set_pc(entry);
|
||||
ctx.registers_mut()[2] = USER_VA_BASE;
|
||||
ctx.set_status(1 << 5);
|
||||
@@ -168,6 +171,6 @@ fn load_elf(
|
||||
});
|
||||
}
|
||||
|
||||
kernel_ref().platform_mut().set_page_table(pid, user_pt as *const mmu::PageTable as usize);
|
||||
kern().platform_mut().set_page_table(pid, user_pt as *const mmu::PageTable as usize);
|
||||
elf_info.entry_point
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user