Files
k-os/crates/kernel/src/syscall/lifecycle.rs
Gabriel Kaszewski 154599e3af feat(kernel): derivation-tree revocation, region caps
- caps record parent (mint/delegate/ipc), CapRef w/ pid+slot gens
- Revoke = delete subtree, keep self; drop/death re-parents children
- CreateRegion/MapRegion; mapping lives only as long as its cap
- drop Permission::Revoke + object-wide revoke
- mint any cap (badge only ep/ntfn), process caps delegable
- kani: descendants == subtree; model-based fuzz vs spec
2026-10-26 20:41:03 +01:00

172 lines
6.0 KiB
Rust

use platform::Platform;
use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> {
pub(crate) fn handle_spawn_thread(
&mut self,
pid: types::id::ProcessId,
entry: types::address::EntryPoint,
stack: types::address::StackPointer,
) -> SyscallOutcome {
use domain::scheduler::Scheduler;
use domain::thread::SavedContext;
let priority = types::bounded::Priority::DEFAULT;
let time_slice = types::time::TimeSlice::DEFAULT;
let context = SavedContext::with_entry_and_stack(entry, stack);
let tid = match self
.threads
.spawn_with_context(pid, priority, time_slice, None, context)
{
Ok(t) => t,
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
if let Err(e) = self.processes.get_mut(pid).and_then(|p| p.add_thread(tid)) {
let _ = self.threads.destroy(tid);
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
let core = self.platform.core_id();
self.scheduler.add(tid, priority, core);
SyscallOutcome::Complete(SyscallResult::Value(tid.raw() as usize))
}
pub(crate) fn handle_create_process(
&mut self,
caller_pid: types::id::ProcessId,
create_cap: types::bounded::CapSlot,
_image: types::address::DataRef,
) -> SyscallOutcome {
if let Err(e) = self.check_cap(
caller_pid,
create_cap,
types::permission::Permission::Execute,
) {
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
let new_pid = match self
.processes
.create(domain::capability::CapabilityTable::new(), None)
{
Ok(p) => p,
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
if let Err(e) = self.create_address_space(new_pid) {
let _ = self.processes.destroy(new_pid);
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
match self.grant_cap(
caller_pid,
domain::resource::Resource::Process(new_pid),
// The creator has full authority over what it creates,
// including handing that authority on.
types::permission::PermissionSet::empty()
.with(types::permission::Permission::Execute)
.with(types::permission::Permission::Read)
.with(types::permission::Permission::Delegate),
) {
Ok(slot) => SyscallOutcome::Complete(SyscallResult::Slot(slot)),
Err(e) => {
// Rollback: destroy orphaned process
self.teardown_memory(new_pid);
let _ = self.processes.destroy(new_pid);
SyscallOutcome::Complete(SyscallResult::Error(e))
}
}
}
pub(crate) fn handle_spawn_thread_in(
&mut self,
caller_pid: types::id::ProcessId,
process_cap: types::bounded::CapSlot,
entry: types::address::EntryPoint,
stack: types::address::StackPointer,
) -> SyscallOutcome {
use domain::scheduler::Scheduler;
use domain::thread::SavedContext;
let target_pid = match self.check_cap(
caller_pid,
process_cap,
types::permission::Permission::Execute,
) {
Ok(cap) => match cap.resource() {
domain::resource::Resource::Process(pid) => *pid,
_ => {
return SyscallOutcome::Complete(SyscallResult::Error(
domain::error::KernelError::PermissionDenied {
slot: process_cap,
needed: types::permission::Permission::Execute,
},
));
}
},
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
let priority = types::bounded::Priority::DEFAULT;
let time_slice = types::time::TimeSlice::DEFAULT;
let context = SavedContext::with_entry_and_stack(entry, stack);
let tid = match self
.threads
.spawn_with_context(target_pid, priority, time_slice, None, context)
{
Ok(t) => t,
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
if let Err(e) = self
.processes
.get_mut(target_pid)
.and_then(|p| p.add_thread(tid))
{
let _ = self.threads.destroy(tid);
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
let core = self.platform.core_id();
self.scheduler.add(tid, priority, core);
SyscallOutcome::Complete(SyscallResult::Value(tid.raw() as usize))
}
pub(crate) fn handle_kill(
&mut self,
caller_pid: types::id::ProcessId,
process_cap: types::bounded::CapSlot,
) -> SyscallOutcome {
let target_pid = match self.check_cap(
caller_pid,
process_cap,
types::permission::Permission::Execute,
) {
Ok(cap) => match cap.resource() {
domain::resource::Resource::Process(pid) => *pid,
_ => {
return SyscallOutcome::Complete(SyscallResult::Error(
domain::error::KernelError::PermissionDenied {
slot: process_cap,
needed: types::permission::Permission::Execute,
},
));
}
},
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
self.destroy_process(target_pid);
if target_pid == caller_pid {
// The caller no longer exists; nothing to return to.
return SyscallOutcome::TerminateCaller;
}
SyscallOutcome::Complete(SyscallResult::Ok)
}
}