1use crate::sync::SpinLock;
7use alloc::collections::BTreeMap;
8use core::sync::atomic::{AtomicU64, Ordering};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct CapId(u64);
13
14impl CapId {
15 pub fn new() -> Self {
17 static NEXT_ID: AtomicU64 = AtomicU64::new(0);
18 CapId(NEXT_ID.fetch_add(1, Ordering::SeqCst))
19 }
20
21 pub fn from_raw(raw: u64) -> Self {
23 CapId(raw)
24 }
25
26 pub fn as_u64(self) -> u64 {
28 self.0
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum ResourceType {
35 MemoryRegion,
36 IoPortRange,
37 InterruptLine,
38 IpcPort,
39 Channel,
41 SharedRing,
43 Semaphore,
45 Device,
46 AddressSpace,
47 Silo,
48 Module,
49 File,
50 Nic,
51 FileSystem,
52 Console,
53 Keyboard,
54 Volume,
55 Namespace,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub struct CapPermissions {
61 pub read: bool,
62 pub write: bool,
63 pub execute: bool,
64 pub grant: bool,
66 pub revoke: bool,
68}
69
70impl CapPermissions {
71 pub const fn none() -> Self {
73 CapPermissions {
74 read: false,
75 write: false,
76 execute: false,
77 grant: false,
78 revoke: false,
79 }
80 }
81
82 pub const fn read_write() -> Self {
84 CapPermissions {
85 read: true,
86 write: true,
87 execute: false,
88 grant: false,
89 revoke: false,
90 }
91 }
92
93 pub const fn all() -> Self {
95 CapPermissions {
96 read: true,
97 write: true,
98 execute: true,
99 grant: true,
100 revoke: true,
101 }
102 }
103}
104
105#[derive(Debug, Clone)]
107pub struct Capability {
108 pub id: CapId,
110 pub resource_type: ResourceType,
112 pub permissions: CapPermissions,
114 pub resource: usize, }
117
118pub struct CapabilityTable {
120 capabilities: BTreeMap<CapId, Capability>,
122}
123
124impl Clone for CapabilityTable {
125 fn clone(&self) -> Self {
127 Self {
128 capabilities: self.capabilities.clone(),
129 }
130 }
131}
132
133impl CapabilityTable {
134 pub fn new() -> Self {
136 CapabilityTable {
137 capabilities: BTreeMap::new(),
138 }
139 }
140
141 pub fn insert(&mut self, cap: Capability) -> CapId {
143 let id = cap.id;
144 self.capabilities.insert(id, cap);
145 id
146 }
147
148 pub fn remove(&mut self, id: CapId) -> Option<Capability> {
150 self.capabilities.remove(&id)
151 }
152
153 pub fn get(&self, id: CapId) -> Option<&Capability> {
155 self.capabilities.get(&id)
156 }
157
158 pub fn revoke_all(&mut self) {
161 let mgr = get_capability_manager();
162 for (id, _) in self.capabilities.iter() {
164 mgr.revoke_capability(*id);
165 }
166 self.capabilities.clear();
167 }
168
169 pub fn has_resource_type_with_permissions(
171 &self,
172 resource_type: ResourceType,
173 required: CapPermissions,
174 ) -> bool {
175 self.capabilities.values().any(|cap| {
176 cap.resource_type == resource_type
177 && (!required.read || cap.permissions.read)
178 && (!required.write || cap.permissions.write)
179 && (!required.execute || cap.permissions.execute)
180 && (!required.grant || cap.permissions.grant)
181 && (!required.revoke || cap.permissions.revoke)
182 })
183 }
184
185 pub fn has_resource_with_permissions(
187 &self,
188 resource_type: ResourceType,
189 resource: usize,
190 required: CapPermissions,
191 ) -> bool {
192 self.capabilities.values().any(|cap| {
193 cap.resource_type == resource_type
194 && cap.resource == resource
195 && (!required.read || cap.permissions.read)
196 && (!required.write || cap.permissions.write)
197 && (!required.execute || cap.permissions.execute)
198 && (!required.grant || cap.permissions.grant)
199 && (!required.revoke || cap.permissions.revoke)
200 })
201 }
202
203 pub fn get_with_permissions(&self, id: CapId, required: CapPermissions) -> Option<&Capability> {
205 self.capabilities.get(&id).filter(|cap| {
206 (!required.read || cap.permissions.read)
208 && (!required.write || cap.permissions.write)
209 && (!required.execute || cap.permissions.execute)
210 && (!required.grant || cap.permissions.grant)
211 && (!required.revoke || cap.permissions.revoke)
212 })
213 }
214
215 pub fn get_mut_with_permissions(
217 &mut self,
218 id: CapId,
219 required: CapPermissions,
220 ) -> Option<&mut Capability> {
221 if let Some(cap) = self.capabilities.get_mut(&id) {
222 if (!required.read || cap.permissions.read)
224 && (!required.write || cap.permissions.write)
225 && (!required.execute || cap.permissions.execute)
226 && (!required.grant || cap.permissions.grant)
227 && (!required.revoke || cap.permissions.revoke)
228 {
229 Some(cap)
230 } else {
231 None
232 }
233 } else {
234 None
235 }
236 }
237
238 pub fn duplicate(&mut self, id: CapId) -> Option<Capability> {
240 if let Some(cap) = self.capabilities.get(&id) {
241 if cap.permissions.grant {
242 Some(Capability {
244 id: CapId::new(),
245 resource_type: cap.resource_type,
246 permissions: cap.permissions,
247 resource: cap.resource,
248 })
249 } else {
250 None
251 }
252 } else {
253 None
254 }
255 }
256}
257
258pub struct CapabilityManager {
260 all_capabilities: SpinLock<BTreeMap<CapId, Capability>>,
262}
263
264impl CapabilityManager {
265 pub fn new() -> Self {
267 CapabilityManager {
268 all_capabilities: SpinLock::new(BTreeMap::new()),
269 }
270 }
271
272 pub fn create_capability(
274 &self,
275 resource_type: ResourceType,
276 resource: usize,
277 permissions: CapPermissions,
278 ) -> Capability {
279 let cap = Capability {
280 id: CapId::new(),
281 resource_type,
282 permissions,
283 resource,
284 };
285
286 self.all_capabilities.lock().insert(cap.id, cap.clone());
287 cap
288 }
289
290 pub fn revoke_capability(&self, id: CapId) -> Option<Capability> {
292 self.all_capabilities.lock().remove(&id)
293 }
294}
295
296use spin::Once;
297
298static CAPABILITY_MANAGER: Once<CapabilityManager> = Once::new();
299
300pub fn get_capability_manager() -> &'static CapabilityManager {
302 CAPABILITY_MANAGER.call_once(CapabilityManager::new)
303}