Files
k-os/crates/kernel/src/syscall/capability.rs
Gabriel Kaszewski 76f10ff1f1 feat(kernel): seL4-style IPC, notifications, status ABI
- badges + Mint, Call/Reply/ReplyRecv w/ gen-checked reply slot
- cap transfer (1/msg, copy, needs Delegate, rechecked at delivery)
- notifications: signal/wait/poll/bind, irq -> notification routing
- WaitAny/WaitForInterrupt removed; a0=status, ErrorCode
- libkos: single ecall primitive, compat wrappers + typed new api
- fix: trap return clobbered user t0 on every trap
- fix: wait queues FIFO, delegate keeps badge, fault cap checked
- docs/ipc.md spec, ipc tests, ipc fuzz, kani ntfn + waitqueue
2026-10-26 20:27:38 +01:00

86 lines
2.9 KiB
Rust

use platform::Platform;
use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> {
pub(crate) fn handle_delegate(
&mut self,
caller_pid: types::id::ProcessId,
slot: types::bounded::CapSlot,
to_endpoint: types::bounded::CapSlot,
restrict: types::permission::PermissionSet,
) -> SyscallOutcome {
// A copy of the capability itself, so its badge and generation
// travel with it; only the permissions narrow.
let copy = match self.check_cap(caller_pid, slot, types::permission::Permission::Delegate) {
Ok(cap) => domain::capability::Capability::new(
cap.resource().clone(),
cap.permissions().restrict_to(&restrict),
*cap.generation(),
)
.with_badge(cap.badge()),
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
let target_pid = match self.check_cap(
caller_pid,
to_endpoint,
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: to_endpoint,
needed: types::permission::Permission::Execute,
},
));
}
},
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
let inserted = self
.processes
.get_mut(target_pid)
.and_then(|p| p.capabilities_mut().insert(copy));
if let Err(e) = inserted {
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
SyscallOutcome::Complete(SyscallResult::Ok)
}
pub(crate) fn handle_revoke(
&mut self,
caller_pid: types::id::ProcessId,
slot: types::bounded::CapSlot,
) -> SyscallOutcome {
let resource = match self.check_cap(caller_pid, slot, types::permission::Permission::Revoke)
{
Ok(cap) => cap.resource().clone(),
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
self.revoke_resource(&resource);
SyscallOutcome::Complete(SyscallResult::Ok)
}
pub(crate) fn handle_drop_cap(
&mut self,
caller_pid: types::id::ProcessId,
slot: types::bounded::CapSlot,
) -> SyscallOutcome {
let result = self
.processes
.get_mut(caller_pid)
.and_then(|p| p.capabilities_mut().remove(slot));
SyscallOutcome::Complete(match result {
Ok(()) => SyscallResult::Ok,
Err(e) => SyscallResult::Error(e),
})
}
}