- 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
86 lines
2.9 KiB
Rust
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),
|
|
})
|
|
}
|
|
}
|