1use std::marker::PhantomData;
69
70#[repr(u32)]
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum CapabilityPermission {
75 None = 0,
76 Read = 1 << 0,
77 Write = 1 << 1,
78 Execute = 1 << 2,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum CapabilityError {
83 OutOfBounds,
84 PermissionDenied,
85 Sealed,
86 AddressOverflow,
87}
88
89const SEALED_BIT: u32 = 1 << 31;
90const WRITE_BIT: u32 = CapabilityPermission::Write as u32;
91
92#[derive(Debug, Clone, Copy)]
108#[repr(C)]
109pub struct ReadableCapability<T> {
110 ptr: *const T,
111 base: usize,
112 length: u32,
113 perms: u32,
114 _phantom: PhantomData<*const T>,
115}
116
117impl<T> ReadableCapability<T> {
118 pub const SIGNATURE: subetha_core::AxisMask = subetha_core::AxisMask::from_axes(
122 &[subetha_core::Axis::Bounds],
123 );
124
125 pub unsafe fn new(ptr: *const T, base: usize, length: u32, perms: u32)
131 -> Result<Self, CapabilityError>
132 {
133 let region_end = base.checked_add(length as usize)
134 .ok_or(CapabilityError::AddressOverflow)?;
135 let addr = ptr as usize;
136 if addr < base { return Err(CapabilityError::OutOfBounds); }
137 let access_end = addr.checked_add(std::mem::size_of::<T>())
138 .ok_or(CapabilityError::AddressOverflow)?;
139 if access_end > region_end {
140 return Err(CapabilityError::OutOfBounds);
141 }
142 Ok(Self {
143 ptr, base, length,
144 perms: perms & !WRITE_BIT, _phantom: PhantomData,
146 })
147 }
148
149 pub fn from_slice(slice: &[T], perms: u32)
152 -> (ReadableCapability<T>, &[T])
153 {
154 let ptr = slice.as_ptr();
155 let base = ptr as usize;
156 let length = std::mem::size_of_val(slice) as u32;
157 let cap = ReadableCapability {
158 ptr, base, length,
159 perms: perms & !WRITE_BIT,
160 _phantom: PhantomData,
161 };
162 (cap, slice)
163 }
164
165 #[inline]
166 pub fn has_permission(&self, p: CapabilityPermission) -> bool {
167 if self.is_sealed() { return false; }
168 (self.perms & p as u32) != 0
171 }
172
173 #[inline]
174 pub fn is_sealed(&self) -> bool { (self.perms & SEALED_BIT) != 0 }
175
176 pub fn sealed(mut self) -> Self {
177 self.perms |= SEALED_BIT;
178 self
179 }
180
181 pub fn unsealed(mut self) -> Self {
182 self.perms &= !SEALED_BIT;
183 self
184 }
185
186 pub fn read(&self) -> Result<T, CapabilityError>
188 where T: Copy,
189 {
190 if self.is_sealed() { return Err(CapabilityError::Sealed); }
191 if !self.has_permission(CapabilityPermission::Read) {
192 return Err(CapabilityError::PermissionDenied);
193 }
194 let addr = self.ptr as usize;
195 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
196 let access_end = addr.checked_add(std::mem::size_of::<T>())
197 .ok_or(CapabilityError::AddressOverflow)?;
198 let region_end = self.base.checked_add(self.length as usize)
199 .ok_or(CapabilityError::AddressOverflow)?;
200 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
201 Ok(unsafe { std::ptr::read(self.ptr) })
205 }
206
207 pub fn narrow(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
210 -> Result<Self, CapabilityError>
211 {
212 let sub_end = sub_base.checked_add(sub_length as usize)
213 .ok_or(CapabilityError::AddressOverflow)?;
214 let region_end = self.base.checked_add(self.length as usize)
215 .ok_or(CapabilityError::AddressOverflow)?;
216 if sub_base < self.base || sub_end > region_end {
217 return Err(CapabilityError::OutOfBounds);
218 }
219 let new_perms = (self.perms & sub_perms) & !SEALED_BIT & !WRITE_BIT;
220 Ok(Self {
221 ptr: sub_base as *const T,
222 base: sub_base,
223 length: sub_length,
224 perms: new_perms,
225 _phantom: PhantomData,
226 })
227 }
228}
229
230#[derive(Debug)]
242#[repr(C)]
243pub struct WritableCapability<T> {
244 ptr: *mut T,
245 base: usize,
246 length: u32,
247 perms: u32,
248 _phantom: PhantomData<*mut T>,
249}
250
251impl<T> WritableCapability<T> {
252 pub const SIGNATURE: subetha_core::AxisMask = subetha_core::AxisMask::from_axes(
256 &[subetha_core::Axis::Bounds],
257 );
258
259 pub unsafe fn new(ptr: *mut T, base: usize, length: u32, perms: u32)
265 -> Result<Self, CapabilityError>
266 {
267 let region_end = base.checked_add(length as usize)
268 .ok_or(CapabilityError::AddressOverflow)?;
269 let addr = ptr as usize;
270 if addr < base { return Err(CapabilityError::OutOfBounds); }
271 let access_end = addr.checked_add(std::mem::size_of::<T>())
272 .ok_or(CapabilityError::AddressOverflow)?;
273 if access_end > region_end {
274 return Err(CapabilityError::OutOfBounds);
275 }
276 Ok(Self { ptr, base, length, perms, _phantom: PhantomData })
277 }
278
279 pub fn from_slice_mut(slice: &mut [T])
282 -> (WritableCapability<T>, &mut [T])
283 {
284 let base = slice.as_ptr() as usize;
285 let length = std::mem::size_of_val(slice) as u32;
286 let ptr = slice.as_mut_ptr();
287 let perms = CapabilityPermission::Read as u32
288 | CapabilityPermission::Write as u32;
289 let cap = WritableCapability {
290 ptr, base, length, perms, _phantom: PhantomData,
291 };
292 (cap, slice)
293 }
294
295 #[inline]
296 pub fn has_permission(&self, p: CapabilityPermission) -> bool {
297 if self.is_sealed() { return false; }
298 (self.perms & p as u32) != 0
299 }
300
301 #[inline]
302 pub fn is_sealed(&self) -> bool { (self.perms & SEALED_BIT) != 0 }
303
304 pub fn sealed(mut self) -> Self {
305 self.perms |= SEALED_BIT;
306 self
307 }
308
309 pub fn unsealed(mut self) -> Self {
310 self.perms &= !SEALED_BIT;
311 self
312 }
313
314 pub fn read(&self) -> Result<T, CapabilityError>
316 where T: Copy,
317 {
318 if self.is_sealed() { return Err(CapabilityError::Sealed); }
319 if !self.has_permission(CapabilityPermission::Read) {
320 return Err(CapabilityError::PermissionDenied);
321 }
322 let addr = self.ptr as usize;
323 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
324 let access_end = addr.checked_add(std::mem::size_of::<T>())
325 .ok_or(CapabilityError::AddressOverflow)?;
326 let region_end = self.base.checked_add(self.length as usize)
327 .ok_or(CapabilityError::AddressOverflow)?;
328 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
329 Ok(unsafe { std::ptr::read(self.ptr) })
331 }
332
333 pub fn write(&mut self, value: T) -> Result<(), CapabilityError> {
337 if self.is_sealed() { return Err(CapabilityError::Sealed); }
338 if !self.has_permission(CapabilityPermission::Write) {
339 return Err(CapabilityError::PermissionDenied);
340 }
341 let addr = self.ptr as usize;
342 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
343 let access_end = addr.checked_add(std::mem::size_of::<T>())
344 .ok_or(CapabilityError::AddressOverflow)?;
345 let region_end = self.base.checked_add(self.length as usize)
346 .ok_or(CapabilityError::AddressOverflow)?;
347 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
348 unsafe { std::ptr::write(self.ptr, value); }
351 Ok(())
352 }
353
354 pub fn narrow(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
357 -> Result<Self, CapabilityError>
358 {
359 let sub_end = sub_base.checked_add(sub_length as usize)
360 .ok_or(CapabilityError::AddressOverflow)?;
361 let region_end = self.base.checked_add(self.length as usize)
362 .ok_or(CapabilityError::AddressOverflow)?;
363 if sub_base < self.base || sub_end > region_end {
364 return Err(CapabilityError::OutOfBounds);
365 }
366 let new_perms = (self.perms & sub_perms) & !SEALED_BIT;
367 Ok(Self {
368 ptr: sub_base as *mut T,
369 base: sub_base,
370 length: sub_length,
371 perms: new_perms,
372 _phantom: PhantomData,
373 })
374 }
375
376 pub fn narrow_readable(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
379 -> Result<ReadableCapability<T>, CapabilityError>
380 {
381 let sub_end = sub_base.checked_add(sub_length as usize)
382 .ok_or(CapabilityError::AddressOverflow)?;
383 let region_end = self.base.checked_add(self.length as usize)
384 .ok_or(CapabilityError::AddressOverflow)?;
385 if sub_base < self.base || sub_end > region_end {
386 return Err(CapabilityError::OutOfBounds);
387 }
388 let new_perms = (self.perms & sub_perms) & !SEALED_BIT & !WRITE_BIT;
389 Ok(ReadableCapability {
390 ptr: sub_base as *const T,
391 base: sub_base,
392 length: sub_length,
393 perms: new_perms,
394 _phantom: PhantomData,
395 })
396 }
397
398 pub fn as_readable(&self) -> ReadableCapability<T> {
403 ReadableCapability {
404 ptr: self.ptr as *const T,
405 base: self.base,
406 length: self.length,
407 perms: self.perms & !WRITE_BIT,
408 _phantom: PhantomData,
409 }
410 }
411}
412
413pub struct OwnedReadableCapability<T> {
420 cap: ReadableCapability<T>,
421}
422
423impl<T> OwnedReadableCapability<T> {
424 pub fn new(value: T) -> Self {
426 Self::from_box(Box::new(value))
427 }
428
429 pub fn from_box(b: Box<T>) -> Self {
432 let ptr = Box::into_raw(b) as *const T;
433 let base = ptr as usize;
434 let length = std::mem::size_of::<T>() as u32;
435 let cap = unsafe {
439 ReadableCapability::new(
440 ptr, base, length, CapabilityPermission::Read as u32,
441 )
442 }.expect("Box::into_raw region cannot fail bounds check");
443 Self { cap }
444 }
445
446 pub fn cap(&self) -> &ReadableCapability<T> { &self.cap }
447
448 pub fn into_box(self) -> Box<T> {
450 let raw = self.cap.ptr as *mut T;
451 std::mem::forget(self);
452 unsafe { Box::from_raw(raw) }
454 }
455}
456
457impl<T> std::ops::Deref for OwnedReadableCapability<T> {
458 type Target = ReadableCapability<T>;
459 fn deref(&self) -> &Self::Target { &self.cap }
460}
461
462impl<T> Drop for OwnedReadableCapability<T> {
463 fn drop(&mut self) {
464 let raw = self.cap.ptr as *mut T;
465 let _reclaimed = unsafe { Box::from_raw(raw) };
468 }
469}
470
471pub struct OwnedWritableCapability<T> {
474 cap: WritableCapability<T>,
475}
476
477impl<T> OwnedWritableCapability<T> {
478 pub fn new(value: T) -> Self {
480 Self::from_box(Box::new(value))
481 }
482
483 pub fn from_box(b: Box<T>) -> Self {
485 let ptr = Box::into_raw(b);
486 let base = ptr as usize;
487 let length = std::mem::size_of::<T>() as u32;
488 let perms = CapabilityPermission::Read as u32
489 | CapabilityPermission::Write as u32;
490 let cap = unsafe {
492 WritableCapability::new(ptr, base, length, perms)
493 }.expect("Box::into_raw region cannot fail bounds check");
494 Self { cap }
495 }
496
497 pub fn cap(&self) -> &WritableCapability<T> { &self.cap }
498 pub fn cap_mut(&mut self) -> &mut WritableCapability<T> { &mut self.cap }
499
500 pub fn into_box(self) -> Box<T> {
502 let raw = self.cap.ptr;
503 std::mem::forget(self);
504 unsafe { Box::from_raw(raw) }
506 }
507}
508
509impl<T> std::ops::Deref for OwnedWritableCapability<T> {
510 type Target = WritableCapability<T>;
511 fn deref(&self) -> &Self::Target { &self.cap }
512}
513
514impl<T> std::ops::DerefMut for OwnedWritableCapability<T> {
515 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.cap }
516}
517
518impl<T> Drop for OwnedWritableCapability<T> {
519 fn drop(&mut self) {
520 let raw = self.cap.ptr;
521 let _reclaimed = unsafe { Box::from_raw(raw) };
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529
530 #[test]
533 fn readable_layout_is_24_bytes() {
534 assert_eq!(std::mem::size_of::<ReadableCapability<u64>>(), 24);
535 }
536
537 #[test]
538 fn writable_layout_is_24_bytes() {
539 assert_eq!(std::mem::size_of::<WritableCapability<u64>>(), 24);
540 }
541
542 #[test]
545 fn readable_from_slice_strips_write_bit() {
546 let storage: Vec<u64> = vec![42];
547 let (cap, _anchor) = ReadableCapability::from_slice(
548 &storage,
549 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
550 );
551 assert!(cap.has_permission(CapabilityPermission::Read));
552 assert!(!cap.has_permission(CapabilityPermission::Write));
554 }
555
556 #[test]
557 fn readable_read_with_permission() {
558 let storage: Vec<u64> = vec![42];
559 let (cap, _anchor) = ReadableCapability::from_slice(
560 &storage, CapabilityPermission::Read as u32,
561 );
562 assert_eq!(cap.read().unwrap(), 42);
563 }
564
565 #[test]
566 fn readable_read_without_permission_fails() {
567 let storage: Vec<u64> = vec![99];
568 let (cap, _anchor) = ReadableCapability::from_slice(&storage, 0);
569 assert_eq!(cap.read().err(), Some(CapabilityError::PermissionDenied));
570 }
571
572 #[test]
573 fn readable_sealed_blocks_read() {
574 let storage: Vec<u64> = vec![1];
575 let (cap, _anchor) = ReadableCapability::from_slice(
576 &storage, CapabilityPermission::Read as u32,
577 );
578 let sealed = cap.sealed();
579 assert_eq!(sealed.read().err(), Some(CapabilityError::Sealed));
580 }
581
582 #[test]
583 fn readable_unseal_restores() {
584 let storage: Vec<u64> = vec![7];
585 let (cap, _anchor) = ReadableCapability::from_slice(
586 &storage, CapabilityPermission::Read as u32,
587 );
588 let unsealed = cap.sealed().unsealed();
589 assert_eq!(unsealed.read().unwrap(), 7);
590 }
591
592 #[test]
593 fn readable_narrow_strips_write() {
594 let storage: Vec<u64> = vec![0, 0, 0, 0];
595 let (cap, anchor) = ReadableCapability::from_slice(
596 &storage,
597 CapabilityPermission::Read as u32,
598 );
599 let base = anchor.as_ptr() as usize;
600 let narrowed = cap.narrow(
601 base, 16,
602 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
603 ).unwrap();
604 assert!(narrowed.has_permission(CapabilityPermission::Read));
605 assert!(!narrowed.has_permission(CapabilityPermission::Write));
606 }
607
608 #[test]
609 fn readable_unsafe_new_overflow_guards() {
610 let ptr = usize::MAX as *const u64;
611 let r = unsafe {
612 ReadableCapability::<u64>::new(
613 ptr, usize::MAX, 16, CapabilityPermission::Read as u32,
614 )
615 };
616 assert_eq!(r.err(), Some(CapabilityError::AddressOverflow));
617 }
618
619 #[test]
622 fn writable_from_slice_mut_grants_read_and_write() {
623 let mut storage: Vec<u64> = vec![0];
624 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
625 assert!(cap.has_permission(CapabilityPermission::Read));
626 assert!(cap.has_permission(CapabilityPermission::Write));
627 }
628
629 #[test]
630 fn writable_write_then_read() {
631 let mut storage: Vec<u64> = vec![0];
632 {
633 let (mut cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
634 cap.write(7777).unwrap();
635 assert_eq!(cap.read().unwrap(), 7777);
636 }
637 assert_eq!(storage[0], 7777);
638 }
639
640 #[test]
641 fn writable_sealed_blocks_write() {
642 let mut storage: Vec<u64> = vec![0];
643 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
644 let mut sealed = cap.sealed();
645 assert_eq!(sealed.write(99u64).err(), Some(CapabilityError::Sealed));
646 }
647
648 #[test]
649 fn writable_as_readable_view_strips_write() {
650 let mut storage: Vec<u64> = vec![42];
651 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
652 let read_view = cap.as_readable();
653 assert!(read_view.has_permission(CapabilityPermission::Read));
654 assert!(!read_view.has_permission(CapabilityPermission::Write));
655 assert_eq!(read_view.read().unwrap(), 42);
656 }
657
658 #[test]
659 fn writable_narrow_readable_strips_write() {
660 let mut storage: Vec<u64> = vec![0, 0];
661 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
662 let base = cap.ptr as usize;
663 let narrowed: ReadableCapability<u64> = cap.narrow_readable(
664 base, 8,
665 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
666 ).unwrap();
667 assert!(narrowed.has_permission(CapabilityPermission::Read));
668 assert!(!narrowed.has_permission(CapabilityPermission::Write));
669 }
670
671 #[test]
672 fn writable_unsafe_new_overflow_guards() {
673 let ptr = usize::MAX as *mut u64;
674 let r = unsafe {
675 WritableCapability::<u64>::new(
676 ptr, usize::MAX, 16,
677 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
678 )
679 };
680 assert_eq!(r.err(), Some(CapabilityError::AddressOverflow));
681 }
682
683 #[test]
686 fn owned_readable_new_and_read() {
687 let owned = OwnedReadableCapability::new(42u64);
688 assert_eq!(owned.read().unwrap(), 42);
689 }
690
691 #[test]
692 fn owned_readable_drop_reclaims() {
693 use std::sync::atomic::{AtomicUsize, Ordering};
694 static DROPS: AtomicUsize = AtomicUsize::new(0);
695 struct DropCounter;
696 impl Drop for DropCounter {
697 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
698 }
699 let before = DROPS.load(Ordering::Relaxed);
700 { let _o = OwnedReadableCapability::new(DropCounter); }
701 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
702 }
703
704 #[test]
707 fn owned_writable_write_then_read() {
708 let mut owned = OwnedWritableCapability::new(0u64);
709 owned.cap_mut().write(555).unwrap();
710 assert_eq!(owned.read().unwrap(), 555);
711 }
712
713 #[test]
714 fn owned_writable_drop_reclaims() {
715 use std::sync::atomic::{AtomicUsize, Ordering};
716 static DROPS: AtomicUsize = AtomicUsize::new(0);
717 struct DropCounter;
718 impl Drop for DropCounter {
719 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
720 }
721 let before = DROPS.load(Ordering::Relaxed);
722 { let _o = OwnedWritableCapability::new(DropCounter); }
723 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
724 }
725
726 #[test]
727 fn owned_writable_into_box_suppresses_drop() {
728 use std::sync::atomic::{AtomicUsize, Ordering};
729 static DROPS: AtomicUsize = AtomicUsize::new(0);
730 struct DropCounter(u32);
731 impl Drop for DropCounter {
732 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
733 }
734 let before = DROPS.load(Ordering::Relaxed);
735 let owned = OwnedWritableCapability::new(DropCounter(99));
736 let b = owned.into_box();
737 assert_eq!(DROPS.load(Ordering::Relaxed), before);
739 assert_eq!(b.0, 99);
740 drop(b);
741 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
743 }
744
745 #[test]
746 fn owned_writable_into_box_round_trip_value() {
747 let owned = OwnedWritableCapability::new(12345u64);
748 let b = owned.into_box();
749 assert_eq!(*b, 12345);
750 }
751}