kernel/object/
introspection.rs

1//! KernelObject introspection and capability discovery
2//!
3//! This module provides types and functions for discovering KernelObject
4//! types and capabilities at runtime, enabling type-safe user-space wrappers.
5
6/// Information about a KernelObject that can be queried by user space
7#[repr(C)]
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct KernelObjectInfo {
10    /// The type of the underlying KernelObject
11    pub object_type: KernelObjectType,
12    /// Available capabilities for this object
13    pub capabilities: ObjectCapabilities,
14    /// Current handle metadata
15    pub handle_role: HandleRole,
16    /// Access permissions
17    pub access_mode: u32,
18}
19
20/// Types of KernelObject that can be distinguished by user space
21#[repr(u32)]
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum KernelObjectType {
24    /// Regular file object
25    File = 1,
26    /// Pipe object for IPC
27    Pipe = 2,
28    /// Event channel for pub/sub IPC
29    EventChannel = 3,
30    /// Event subscription for receiving events
31    EventSubscription = 4,
32    /// Character device (future)
33    CharDevice = 5,
34    /// Block device (future)
35    BlockDevice = 6,
36    /// Socket (future)
37    Socket = 7,
38    /// Shared memory for IPC
39    SharedMemory = 8,
40    /// Counter for event notification (like eventfd)
41    Counter = 9,
42    /// Unknown or unsupported type
43    Unknown = 0,
44}
45
46/// Capabilities available for a KernelObject
47#[repr(C)]
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub struct ObjectCapabilities {
50    /// Supports StreamOps (read/write)
51    pub stream_ops: bool,
52    /// Supports FileOps (seek, truncate, etc.)
53    pub file_ops: bool,
54    /// Supports PipeOps (pipe-specific operations)
55    pub pipe_ops: bool,
56    /// Supports Event capabilities (EventSender/EventReceiver/EventSubscriber operations)
57    pub event_ops: bool,
58    /// Supports CloneOps (custom cloning)
59    pub clone_ops: bool,
60    /// Reserved for future capabilities
61    pub reserved: [bool; 3],
62}
63
64/// Handle role information (simplified from HandleType)
65#[repr(u32)]
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum HandleRole {
68    /// Standard input/output stream
69    StandardInputOutput = 1,
70    /// Inter-process communication
71    IpcChannel = 2,
72    /// Regular usage
73    Regular = 3,
74}
75
76impl KernelObjectInfo {
77    /// Create info for a File KernelObject
78    pub fn for_file(handle_role: HandleRole, readable: bool, writable: bool) -> Self {
79        Self {
80            object_type: KernelObjectType::File,
81            capabilities: ObjectCapabilities {
82                stream_ops: true,
83                file_ops: true,
84                pipe_ops: false,
85                event_ops: false,
86                clone_ops: false,
87                reserved: [false; 3],
88            },
89            handle_role,
90            access_mode: Self::encode_access_mode(readable, writable),
91        }
92    }
93
94    /// Create info for a Pipe KernelObject
95    pub fn for_pipe(handle_role: HandleRole, readable: bool, writable: bool) -> Self {
96        Self {
97            object_type: KernelObjectType::Pipe,
98            capabilities: ObjectCapabilities {
99                stream_ops: true,
100                file_ops: false,
101                pipe_ops: true,
102                event_ops: false,
103                clone_ops: true,
104                reserved: [false; 3],
105            },
106            handle_role,
107            access_mode: Self::encode_access_mode(readable, writable),
108        }
109    }
110
111    /// Create info for a Counter KernelObject
112    pub fn for_counter(handle_role: HandleRole, readable: bool, writable: bool) -> Self {
113        Self {
114            object_type: KernelObjectType::Counter,
115            capabilities: ObjectCapabilities {
116                stream_ops: true,
117                file_ops: false,
118                pipe_ops: false,
119                event_ops: false,
120                clone_ops: true,
121                reserved: [false; 3],
122            },
123            handle_role,
124            access_mode: Self::encode_access_mode(readable, writable),
125        }
126    }
127
128    /// Create info for a Socket KernelObject
129    pub fn for_socket(handle_role: HandleRole, readable: bool, writable: bool) -> Self {
130        Self {
131            object_type: KernelObjectType::Socket,
132            // Sockets are stream-like and support handle transfer; we conservatively
133            // model them as supporting StreamOps + PipeOps + CloneOps.
134            capabilities: ObjectCapabilities {
135                stream_ops: true,
136                file_ops: false,
137                pipe_ops: true,
138                event_ops: false,
139                clone_ops: true,
140                reserved: [false; 3],
141            },
142            handle_role,
143            access_mode: Self::encode_access_mode(readable, writable),
144        }
145    }
146
147    /// Create info for an EventChannel KernelObject
148    pub fn for_event_channel(handle_role: HandleRole) -> Self {
149        Self {
150            object_type: KernelObjectType::EventChannel,
151            capabilities: ObjectCapabilities {
152                stream_ops: false,
153                file_ops: false,
154                pipe_ops: false,
155                event_ops: true,
156                clone_ops: true,
157                reserved: [false; 3],
158            },
159            handle_role,
160            access_mode: Self::encode_access_mode(true, true), // Channel can be read and written
161        }
162    }
163
164    /// Create info for an EventSubscription KernelObject
165    pub fn for_event_subscription(handle_role: HandleRole) -> Self {
166        Self {
167            object_type: KernelObjectType::EventSubscription,
168            capabilities: ObjectCapabilities {
169                stream_ops: true, // Can receive events like reading
170                file_ops: false,
171                pipe_ops: false,
172                event_ops: true,
173                clone_ops: true,
174                reserved: [false; 3],
175            },
176            handle_role,
177            access_mode: Self::encode_access_mode(true, false), // Subscription is read-only
178        }
179    }
180
181    /// Create info for a SharedMemory KernelObject
182    pub fn for_shared_memory(handle_role: HandleRole, readable: bool, writable: bool) -> Self {
183        Self {
184            object_type: KernelObjectType::SharedMemory,
185            capabilities: ObjectCapabilities {
186                stream_ops: false, // Shared memory doesn't support stream operations
187                file_ops: false,
188                pipe_ops: false,
189                event_ops: false,
190                clone_ops: false, // Uses Arc::clone directly
191                reserved: [false; 3],
192            },
193            handle_role,
194            access_mode: Self::encode_access_mode(readable, writable),
195        }
196    }
197
198    /// Create info for unknown KernelObject
199    pub fn unknown() -> Self {
200        Self {
201            object_type: KernelObjectType::Unknown,
202            capabilities: ObjectCapabilities {
203                stream_ops: false,
204                file_ops: false,
205                pipe_ops: false,
206                event_ops: false,
207                clone_ops: false,
208                reserved: [false; 3],
209            },
210            handle_role: HandleRole::Regular,
211            access_mode: 0,
212        }
213    }
214
215    fn encode_access_mode(readable: bool, writable: bool) -> u32 {
216        let mut mode = 0;
217        if readable {
218            mode |= 0x1;
219        }
220        if writable {
221            mode |= 0x2;
222        }
223        mode
224    }
225}
226
227/// Convert from HandleType to HandleRole for user space
228impl From<crate::object::handle::HandleType> for HandleRole {
229    fn from(handle_type: crate::object::handle::HandleType) -> Self {
230        match handle_type {
231            crate::object::handle::HandleType::StandardInputOutput(_) => {
232                HandleRole::StandardInputOutput
233            }
234            crate::object::handle::HandleType::IpcChannel => HandleRole::IpcChannel,
235            crate::object::handle::HandleType::EventChannel => HandleRole::IpcChannel, // Map to IPC channel for now
236            crate::object::handle::HandleType::EventSubscription => HandleRole::IpcChannel, // Map to IPC channel for now
237            crate::object::handle::HandleType::Regular => HandleRole::Regular,
238        }
239    }
240}
241
242/// Convert from AccessMode to boolean flags
243impl From<crate::object::handle::AccessMode> for (bool, bool) {
244    fn from(access_mode: crate::object::handle::AccessMode) -> Self {
245        match access_mode {
246            crate::object::handle::AccessMode::ReadOnly => (true, false),
247            crate::object::handle::AccessMode::WriteOnly => (false, true),
248            crate::object::handle::AccessMode::ReadWrite => (true, true),
249        }
250    }
251}