⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/ipc/
cap_transfer.rs

1//! Capability transfer through IPC
2//!
3//! This module handles the secure transfer of capabilities between processes
4//! through IPC messages.
5
6use super::{
7    error::{IpcError, Result},
8    message::Message,
9};
10use crate::{
11    cap::{
12        manager::{cap_manager, CapError},
13        space::CapabilitySpace,
14        token::{CapabilityToken, Rights},
15    },
16    process::ProcessId,
17};
18
19/// Transfer a capability through an IPC message
20///
21/// This function handles the delegation of a capability from the sender
22/// to the receiver of an IPC message.
23pub fn transfer_capability(
24    msg: &Message,
25    sender_cap_space: &CapabilitySpace,
26    receiver_pid: ProcessId,
27) -> Result<Option<CapabilityToken>> {
28    let cap_id = msg.capability();
29
30    // If no capability in message, nothing to transfer
31    if cap_id == 0 {
32        return Ok(None);
33    }
34
35    // Convert to capability token
36    let cap_token = CapabilityToken::from_u64(cap_id);
37
38    // Verify sender has the capability and GRANT right
39    match crate::cap::manager::check_capability(cap_token, Rights::GRANT, sender_cap_space) {
40        Ok(()) => {}
41        Err(CapError::InvalidCapability) => return Err(IpcError::InvalidCapability),
42        Err(CapError::InsufficientRights) => return Err(IpcError::PermissionDenied),
43        Err(CapError::CapabilityRevoked) => return Err(IpcError::InvalidCapability),
44        Err(_) => return Err(IpcError::InvalidCapability),
45    }
46
47    // Get receiver's capability space
48    let receiver_process = match crate::process::table::get_process(receiver_pid) {
49        Some(process) => process,
50        None => return Err(IpcError::ProcessNotFound),
51    };
52    let receiver_cap_space = receiver_process.capability_space.lock();
53
54    // Determine rights to transfer (same as sender's minus GRANT)
55    let sender_rights = sender_cap_space
56        .lookup(cap_token)
57        .ok_or(IpcError::InvalidCapability)?;
58    let transfer_rights = sender_rights.difference(Rights::GRANT);
59
60    // Delegate the capability to receiver
61    match cap_manager().delegate(
62        cap_token,
63        sender_cap_space,
64        &receiver_cap_space,
65        transfer_rights,
66    ) {
67        Ok(new_cap) => Ok(Some(new_cap)),
68        Err(CapError::OutOfMemory) => Err(IpcError::OutOfMemory),
69        Err(_) => Err(IpcError::PermissionDenied),
70    }
71}
72
73/// Extract and validate capabilities from received message
74///
75/// This function should be called when a process receives an IPC message
76/// to properly handle any transferred capabilities.
77#[allow(dead_code)] // IPC capability transfer API
78pub fn receive_capability(
79    msg: &Message,
80    receiver_cap_space: &CapabilitySpace,
81) -> Result<Option<CapabilityToken>> {
82    let cap_id = msg.capability();
83
84    // If no capability in message, nothing to receive
85    if cap_id == 0 {
86        return Ok(None);
87    }
88
89    // Convert to capability token
90    let cap_token = CapabilityToken::from_u64(cap_id);
91
92    // Check if the capability exists in receiver's space
93    // (It should have been transferred during send)
94    if receiver_cap_space.lookup(cap_token).is_some() {
95        Ok(Some(cap_token))
96    } else {
97        // Capability wasn't properly transferred
98        Err(IpcError::InvalidCapability)
99    }
100}
101
102/// Revoke a capability that was transferred via IPC
103///
104/// This allows the original owner to revoke a capability they previously
105/// granted through IPC.
106#[allow(dead_code)] // IPC capability revocation API
107pub fn revoke_transferred_capability(
108    cap_token: CapabilityToken,
109    owner_cap_space: &CapabilitySpace,
110) -> Result<()> {
111    // Verify owner has the capability
112    if owner_cap_space.lookup(cap_token).is_none() {
113        return Err(IpcError::InvalidCapability);
114    }
115
116    // Revoke globally
117    match cap_manager().revoke(cap_token) {
118        Ok(()) => Ok(()),
119        Err(CapError::InvalidCapability) => Err(IpcError::InvalidCapability),
120        Err(_) => Err(IpcError::PermissionDenied),
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    // Tests would go here but are disabled in no_std environment
127}