Skip to main content

ruvix_types/
error.rs

1//! Kernel error types.
2//!
3//! All syscalls return `Result<T, KernelError>` to indicate success or failure.
4//! Errors are designed to be informative without leaking sensitive information.
5
6/// Kernel error codes.
7///
8/// Every syscall can return these errors. Error codes are stable across
9/// kernel versions (part of the ABI contract).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[repr(u16)]
12pub enum KernelError {
13    /// The specified capability handle is invalid or does not exist.
14    InvalidCapability = 1,
15
16    /// The capability does not have the required rights for this operation.
17    InsufficientRights = 2,
18
19    /// The capability has been revoked (epoch mismatch).
20    CapabilityRevoked = 3,
21
22    /// The proof token is invalid (wrong hash, expired, or nonce reused).
23    ProofRejected = 4,
24
25    /// Out of memory when trying to allocate a region.
26    OutOfMemory = 5,
27
28    /// The queue is full and cannot accept more messages.
29    QueueFull = 6,
30
31    /// The queue is empty (timeout expired during receive).
32    QueueEmpty = 7,
33
34    /// The operation timed out.
35    Timeout = 8,
36
37    /// The RVF package signature verification failed.
38    InvalidSignature = 9,
39
40    /// The RVF manifest is malformed or references invalid components.
41    InvalidManifest = 10,
42
43    /// The object type does not support this operation.
44    InvalidObjectType = 11,
45
46    /// The operation would exceed system limits (e.g., max tasks, max regions).
47    LimitExceeded = 12,
48
49    /// The resource already exists (e.g., duplicate mount point).
50    AlreadyExists = 13,
51
52    /// The resource was not found.
53    NotFound = 14,
54
55    /// The operation is not permitted in the current state.
56    NotPermitted = 15,
57
58    /// The operation would violate coherence constraints.
59    CoherenceViolation = 16,
60
61    /// Maximum delegation depth exceeded.
62    DelegationDepthExceeded = 17,
63
64    /// The capability cannot be granted (no GRANT or GRANT_ONCE right).
65    CannotGrant = 18,
66
67    /// The handle generation does not match (stale handle detection).
68    StaleHandle = 19,
69
70    /// The slot handle is invalid or stale (slab regions).
71    InvalidSlot = 20,
72
73    /// The slab region has no free slots available.
74    SlabFull = 21,
75
76    /// The append-only region has reached its maximum size.
77    RegionFull = 22,
78
79    /// Operation violates the region's policy (e.g., write to immutable).
80    RegionPolicyViolation = 23,
81
82    /// The provided buffer is too small for the requested operation.
83    BufferTooSmall = 24,
84
85    /// An invalid argument was provided.
86    InvalidArgument = 25,
87
88    /// The message exceeds the queue's maximum message size.
89    MessageTooLarge = 26,
90
91    /// The descriptor references a region with an invalid policy for zero-copy.
92    /// Only Immutable and AppendOnly regions allow descriptors (TOCTOU protection).
93    InvalidDescriptorRegion = 27,
94
95    /// Internal kernel error (should not happen in normal operation).
96    InternalError = 255,
97}
98
99impl KernelError {
100    /// Returns a human-readable description of the error.
101    #[inline]
102    #[must_use]
103    pub const fn as_str(&self) -> &'static str {
104        match self {
105            Self::InvalidCapability => "Invalid capability handle",
106            Self::InsufficientRights => "Insufficient capability rights",
107            Self::CapabilityRevoked => "Capability has been revoked",
108            Self::ProofRejected => "Proof token rejected",
109            Self::OutOfMemory => "Out of memory",
110            Self::QueueFull => "Queue is full",
111            Self::QueueEmpty => "Queue is empty",
112            Self::Timeout => "Operation timed out",
113            Self::InvalidSignature => "Invalid RVF signature",
114            Self::InvalidManifest => "Invalid RVF manifest",
115            Self::InvalidObjectType => "Invalid object type for operation",
116            Self::LimitExceeded => "System limit exceeded",
117            Self::AlreadyExists => "Resource already exists",
118            Self::NotFound => "Resource not found",
119            Self::NotPermitted => "Operation not permitted",
120            Self::CoherenceViolation => "Coherence constraint violated",
121            Self::DelegationDepthExceeded => "Maximum delegation depth exceeded",
122            Self::CannotGrant => "Capability cannot be granted",
123            Self::StaleHandle => "Stale handle (generation mismatch)",
124            Self::InvalidSlot => "Invalid or stale slot handle",
125            Self::SlabFull => "Slab region has no free slots",
126            Self::RegionFull => "Region has reached maximum size",
127            Self::RegionPolicyViolation => "Operation violates region policy",
128            Self::BufferTooSmall => "Buffer too small for operation",
129            Self::InvalidArgument => "Invalid argument provided",
130            Self::MessageTooLarge => "Message exceeds maximum size",
131            Self::InvalidDescriptorRegion => "Descriptor region policy invalid for zero-copy",
132            Self::InternalError => "Internal kernel error",
133        }
134    }
135
136    /// Converts from a raw u16 error code.
137    #[inline]
138    #[must_use]
139    pub const fn from_u16(code: u16) -> Option<Self> {
140        match code {
141            1 => Some(Self::InvalidCapability),
142            2 => Some(Self::InsufficientRights),
143            3 => Some(Self::CapabilityRevoked),
144            4 => Some(Self::ProofRejected),
145            5 => Some(Self::OutOfMemory),
146            6 => Some(Self::QueueFull),
147            7 => Some(Self::QueueEmpty),
148            8 => Some(Self::Timeout),
149            9 => Some(Self::InvalidSignature),
150            10 => Some(Self::InvalidManifest),
151            11 => Some(Self::InvalidObjectType),
152            12 => Some(Self::LimitExceeded),
153            13 => Some(Self::AlreadyExists),
154            14 => Some(Self::NotFound),
155            15 => Some(Self::NotPermitted),
156            16 => Some(Self::CoherenceViolation),
157            17 => Some(Self::DelegationDepthExceeded),
158            18 => Some(Self::CannotGrant),
159            19 => Some(Self::StaleHandle),
160            20 => Some(Self::InvalidSlot),
161            21 => Some(Self::SlabFull),
162            22 => Some(Self::RegionFull),
163            23 => Some(Self::RegionPolicyViolation),
164            24 => Some(Self::BufferTooSmall),
165            25 => Some(Self::InvalidArgument),
166            26 => Some(Self::MessageTooLarge),
167            27 => Some(Self::InvalidDescriptorRegion),
168            255 => Some(Self::InternalError),
169            _ => None,
170        }
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177
178    #[test]
179    fn test_error_roundtrip() {
180        let errors = [
181            KernelError::InvalidCapability,
182            KernelError::InsufficientRights,
183            KernelError::ProofRejected,
184            KernelError::OutOfMemory,
185            KernelError::InternalError,
186        ];
187
188        for err in errors {
189            let code = err as u16;
190            let parsed = KernelError::from_u16(code).unwrap();
191            assert_eq!(err, parsed);
192        }
193    }
194
195    #[test]
196    fn test_error_as_str() {
197        assert_eq!(
198            KernelError::DelegationDepthExceeded.as_str(),
199            "Maximum delegation depth exceeded"
200        );
201    }
202}