use platform::Platform; use super::{SyscallOutcome, SyscallResult}; use crate::Kernel; impl Kernel

{ 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), }) } }