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:
@@ -1,3 +1,4 @@
|
||||
use domain::process::MAX_THREADS_PER_PROCESS;
|
||||
use platform::Platform;
|
||||
|
||||
use super::{SyscallOutcome, SyscallResult};
|
||||
@@ -14,7 +15,7 @@ impl<P: Platform> Kernel<P> {
|
||||
use domain::thread::SavedContext;
|
||||
|
||||
let priority = types::bounded::Priority::DEFAULT;
|
||||
let time_slice = types::time::TimeSlice::DEFAULT;
|
||||
let time_slice = types::time::TimeSlice::new(100);
|
||||
let context = SavedContext::with_entry_and_stack(entry, stack);
|
||||
|
||||
let tid = match self.threads.spawn_with_context(pid, priority, time_slice, None, context) {
|
||||
@@ -38,8 +39,6 @@ impl<P: Platform> Kernel<P> {
|
||||
create_cap: types::bounded::CapSlot,
|
||||
_image: types::address::DataRef,
|
||||
) -> SyscallOutcome {
|
||||
use domain::scheduler::Scheduler;
|
||||
|
||||
if let Err(e) = self.check_cap(caller_pid, create_cap, types::permission::Permission::Execute) {
|
||||
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
||||
}
|
||||
@@ -55,18 +54,21 @@ impl<P: Platform> Kernel<P> {
|
||||
self.process_memory[new_pid.raw() as usize] =
|
||||
Some(domain::memory::process_memory::ProcessMemory::new(new_pid, 1024));
|
||||
|
||||
let slot = match self.grant_cap(
|
||||
match self.grant_cap(
|
||||
caller_pid,
|
||||
domain::resource::Resource::Process(new_pid),
|
||||
types::permission::PermissionSet::empty()
|
||||
.with(types::permission::Permission::Execute)
|
||||
.with(types::permission::Permission::Read),
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
||||
};
|
||||
|
||||
SyscallOutcome::Complete(SyscallResult::Slot(slot))
|
||||
Ok(slot) => SyscallOutcome::Complete(SyscallResult::Slot(slot)),
|
||||
Err(e) => {
|
||||
// Rollback: destroy orphaned process
|
||||
let _ = self.processes.destroy(new_pid);
|
||||
self.process_memory[new_pid.raw() as usize] = None;
|
||||
SyscallOutcome::Complete(SyscallResult::Error(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_spawn_thread_in(
|
||||
@@ -97,7 +99,7 @@ impl<P: Platform> Kernel<P> {
|
||||
};
|
||||
|
||||
let priority = types::bounded::Priority::DEFAULT;
|
||||
let time_slice = types::time::TimeSlice::DEFAULT;
|
||||
let time_slice = types::time::TimeSlice::new(100);
|
||||
let context = SavedContext::with_entry_and_stack(entry, stack);
|
||||
|
||||
let tid = match self.threads.spawn_with_context(target_pid, priority, time_slice, None, context) {
|
||||
@@ -133,23 +135,7 @@ impl<P: Platform> Kernel<P> {
|
||||
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
||||
};
|
||||
|
||||
let thread_ids: [Option<types::id::ThreadId>; 4] = {
|
||||
match self.processes.get(target_pid) {
|
||||
Ok(p) => {
|
||||
let mut ids = [None; 4];
|
||||
for (i, tid) in p.thread_ids().enumerate() {
|
||||
if i < 4 { ids[i] = Some(tid); }
|
||||
}
|
||||
ids
|
||||
}
|
||||
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
||||
}
|
||||
};
|
||||
|
||||
self.cleanup_threads(&thread_ids);
|
||||
|
||||
let _ = self.processes.destroy(target_pid);
|
||||
self.process_memory[target_pid.raw() as usize] = None;
|
||||
self.destroy_process(target_pid);
|
||||
SyscallOutcome::Complete(SyscallResult::Ok)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user