1use std::marker::PhantomData;
61
62#[repr(u32)]
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum CapabilityPermission {
67 None = 0,
68 Read = 1 << 0,
69 Write = 1 << 1,
70 Execute = 1 << 2,
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum CapabilityError {
75 OutOfBounds,
76 PermissionDenied,
77 Sealed,
78 AddressOverflow,
79}
80
81const SEALED_BIT: u32 = 1 << 31;
82const WRITE_BIT: u32 = CapabilityPermission::Write as u32;
83
84#[derive(Debug, Clone, Copy)]
100#[repr(C)]
101pub struct ReadableCapability<T> {
102 ptr: *const T,
103 base: usize,
104 length: u32,
105 perms: u32,
106 _phantom: PhantomData<*const T>,
107}
108
109impl<T> ReadableCapability<T> {
110 pub const SIGNATURE: subetha_core::AxisMask = subetha_core::AxisMask::from_axes(
114 &[subetha_core::Axis::Bounds],
115 );
116
117 pub unsafe fn new(ptr: *const T, base: usize, length: u32, perms: u32)
123 -> Result<Self, CapabilityError>
124 {
125 let region_end = base.checked_add(length as usize)
126 .ok_or(CapabilityError::AddressOverflow)?;
127 let addr = ptr as usize;
128 if addr < base { return Err(CapabilityError::OutOfBounds); }
129 let access_end = addr.checked_add(std::mem::size_of::<T>())
130 .ok_or(CapabilityError::AddressOverflow)?;
131 if access_end > region_end {
132 return Err(CapabilityError::OutOfBounds);
133 }
134 Ok(Self {
135 ptr, base, length,
136 perms: perms & !WRITE_BIT, _phantom: PhantomData,
138 })
139 }
140
141 pub fn from_slice(slice: &[T], perms: u32)
144 -> (ReadableCapability<T>, &[T])
145 {
146 let ptr = slice.as_ptr();
147 let base = ptr as usize;
148 let length = std::mem::size_of_val(slice) as u32;
149 let cap = ReadableCapability {
150 ptr, base, length,
151 perms: perms & !WRITE_BIT,
152 _phantom: PhantomData,
153 };
154 (cap, slice)
155 }
156
157 #[inline]
158 pub fn has_permission(&self, p: CapabilityPermission) -> bool {
159 if self.is_sealed() { return false; }
160 (self.perms & p as u32) != 0
163 }
164
165 #[inline]
166 pub fn is_sealed(&self) -> bool { (self.perms & SEALED_BIT) != 0 }
167
168 pub fn sealed(mut self) -> Self {
169 self.perms |= SEALED_BIT;
170 self
171 }
172
173 pub fn unsealed(mut self) -> Self {
174 self.perms &= !SEALED_BIT;
175 self
176 }
177
178 pub fn read(&self) -> Result<T, CapabilityError>
180 where T: Copy,
181 {
182 if self.is_sealed() { return Err(CapabilityError::Sealed); }
183 if !self.has_permission(CapabilityPermission::Read) {
184 return Err(CapabilityError::PermissionDenied);
185 }
186 let addr = self.ptr as usize;
187 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
188 let access_end = addr.checked_add(std::mem::size_of::<T>())
189 .ok_or(CapabilityError::AddressOverflow)?;
190 let region_end = self.base.checked_add(self.length as usize)
191 .ok_or(CapabilityError::AddressOverflow)?;
192 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
193 Ok(unsafe { std::ptr::read(self.ptr) })
197 }
198
199 pub fn narrow(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
202 -> Result<Self, CapabilityError>
203 {
204 let sub_end = sub_base.checked_add(sub_length as usize)
205 .ok_or(CapabilityError::AddressOverflow)?;
206 let region_end = self.base.checked_add(self.length as usize)
207 .ok_or(CapabilityError::AddressOverflow)?;
208 if sub_base < self.base || sub_end > region_end {
209 return Err(CapabilityError::OutOfBounds);
210 }
211 let new_perms = (self.perms & sub_perms) & !SEALED_BIT & !WRITE_BIT;
212 Ok(Self {
213 ptr: sub_base as *const T,
214 base: sub_base,
215 length: sub_length,
216 perms: new_perms,
217 _phantom: PhantomData,
218 })
219 }
220}
221
222#[derive(Debug)]
234#[repr(C)]
235pub struct WritableCapability<T> {
236 ptr: *mut T,
237 base: usize,
238 length: u32,
239 perms: u32,
240 _phantom: PhantomData<*mut T>,
241}
242
243impl<T> WritableCapability<T> {
244 pub const SIGNATURE: subetha_core::AxisMask = subetha_core::AxisMask::from_axes(
248 &[subetha_core::Axis::Bounds],
249 );
250
251 pub unsafe fn new(ptr: *mut T, base: usize, length: u32, perms: u32)
257 -> Result<Self, CapabilityError>
258 {
259 let region_end = base.checked_add(length as usize)
260 .ok_or(CapabilityError::AddressOverflow)?;
261 let addr = ptr as usize;
262 if addr < base { return Err(CapabilityError::OutOfBounds); }
263 let access_end = addr.checked_add(std::mem::size_of::<T>())
264 .ok_or(CapabilityError::AddressOverflow)?;
265 if access_end > region_end {
266 return Err(CapabilityError::OutOfBounds);
267 }
268 Ok(Self { ptr, base, length, perms, _phantom: PhantomData })
269 }
270
271 pub fn from_slice_mut(slice: &mut [T])
274 -> (WritableCapability<T>, &mut [T])
275 {
276 let base = slice.as_ptr() as usize;
277 let length = std::mem::size_of_val(slice) as u32;
278 let ptr = slice.as_mut_ptr();
279 let perms = CapabilityPermission::Read as u32
280 | CapabilityPermission::Write as u32;
281 let cap = WritableCapability {
282 ptr, base, length, perms, _phantom: PhantomData,
283 };
284 (cap, slice)
285 }
286
287 #[inline]
288 pub fn has_permission(&self, p: CapabilityPermission) -> bool {
289 if self.is_sealed() { return false; }
290 (self.perms & p as u32) != 0
291 }
292
293 #[inline]
294 pub fn is_sealed(&self) -> bool { (self.perms & SEALED_BIT) != 0 }
295
296 pub fn sealed(mut self) -> Self {
297 self.perms |= SEALED_BIT;
298 self
299 }
300
301 pub fn unsealed(mut self) -> Self {
302 self.perms &= !SEALED_BIT;
303 self
304 }
305
306 pub fn read(&self) -> Result<T, CapabilityError>
308 where T: Copy,
309 {
310 if self.is_sealed() { return Err(CapabilityError::Sealed); }
311 if !self.has_permission(CapabilityPermission::Read) {
312 return Err(CapabilityError::PermissionDenied);
313 }
314 let addr = self.ptr as usize;
315 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
316 let access_end = addr.checked_add(std::mem::size_of::<T>())
317 .ok_or(CapabilityError::AddressOverflow)?;
318 let region_end = self.base.checked_add(self.length as usize)
319 .ok_or(CapabilityError::AddressOverflow)?;
320 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
321 Ok(unsafe { std::ptr::read(self.ptr) })
323 }
324
325 pub fn write(&mut self, value: T) -> Result<(), CapabilityError> {
329 if self.is_sealed() { return Err(CapabilityError::Sealed); }
330 if !self.has_permission(CapabilityPermission::Write) {
331 return Err(CapabilityError::PermissionDenied);
332 }
333 let addr = self.ptr as usize;
334 if addr < self.base { return Err(CapabilityError::OutOfBounds); }
335 let access_end = addr.checked_add(std::mem::size_of::<T>())
336 .ok_or(CapabilityError::AddressOverflow)?;
337 let region_end = self.base.checked_add(self.length as usize)
338 .ok_or(CapabilityError::AddressOverflow)?;
339 if access_end > region_end { return Err(CapabilityError::OutOfBounds); }
340 unsafe { std::ptr::write(self.ptr, value); }
343 Ok(())
344 }
345
346 pub fn narrow(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
349 -> Result<Self, CapabilityError>
350 {
351 let sub_end = sub_base.checked_add(sub_length as usize)
352 .ok_or(CapabilityError::AddressOverflow)?;
353 let region_end = self.base.checked_add(self.length as usize)
354 .ok_or(CapabilityError::AddressOverflow)?;
355 if sub_base < self.base || sub_end > region_end {
356 return Err(CapabilityError::OutOfBounds);
357 }
358 let new_perms = (self.perms & sub_perms) & !SEALED_BIT;
359 Ok(Self {
360 ptr: sub_base as *mut T,
361 base: sub_base,
362 length: sub_length,
363 perms: new_perms,
364 _phantom: PhantomData,
365 })
366 }
367
368 pub fn narrow_readable(&self, sub_base: usize, sub_length: u32, sub_perms: u32)
371 -> Result<ReadableCapability<T>, CapabilityError>
372 {
373 let sub_end = sub_base.checked_add(sub_length as usize)
374 .ok_or(CapabilityError::AddressOverflow)?;
375 let region_end = self.base.checked_add(self.length as usize)
376 .ok_or(CapabilityError::AddressOverflow)?;
377 if sub_base < self.base || sub_end > region_end {
378 return Err(CapabilityError::OutOfBounds);
379 }
380 let new_perms = (self.perms & sub_perms) & !SEALED_BIT & !WRITE_BIT;
381 Ok(ReadableCapability {
382 ptr: sub_base as *const T,
383 base: sub_base,
384 length: sub_length,
385 perms: new_perms,
386 _phantom: PhantomData,
387 })
388 }
389
390 pub fn as_readable(&self) -> ReadableCapability<T> {
395 ReadableCapability {
396 ptr: self.ptr as *const T,
397 base: self.base,
398 length: self.length,
399 perms: self.perms & !WRITE_BIT,
400 _phantom: PhantomData,
401 }
402 }
403}
404
405pub struct OwnedReadableCapability<T> {
412 cap: ReadableCapability<T>,
413}
414
415impl<T> OwnedReadableCapability<T> {
416 pub fn new(value: T) -> Self {
418 Self::from_box(Box::new(value))
419 }
420
421 pub fn from_box(b: Box<T>) -> Self {
424 let ptr = Box::into_raw(b) as *const T;
425 let base = ptr as usize;
426 let length = std::mem::size_of::<T>() as u32;
427 let cap = unsafe {
431 ReadableCapability::new(
432 ptr, base, length, CapabilityPermission::Read as u32,
433 )
434 }.expect("Box::into_raw region cannot fail bounds check");
435 Self { cap }
436 }
437
438 pub fn cap(&self) -> &ReadableCapability<T> { &self.cap }
439
440 pub fn into_box(self) -> Box<T> {
442 let raw = self.cap.ptr as *mut T;
443 std::mem::forget(self);
444 unsafe { Box::from_raw(raw) }
446 }
447}
448
449impl<T> std::ops::Deref for OwnedReadableCapability<T> {
450 type Target = ReadableCapability<T>;
451 fn deref(&self) -> &Self::Target { &self.cap }
452}
453
454impl<T> Drop for OwnedReadableCapability<T> {
455 fn drop(&mut self) {
456 let raw = self.cap.ptr as *mut T;
457 let _reclaimed = unsafe { Box::from_raw(raw) };
460 }
461}
462
463pub struct OwnedWritableCapability<T> {
466 cap: WritableCapability<T>,
467}
468
469impl<T> OwnedWritableCapability<T> {
470 pub fn new(value: T) -> Self {
472 Self::from_box(Box::new(value))
473 }
474
475 pub fn from_box(b: Box<T>) -> Self {
477 let ptr = Box::into_raw(b);
478 let base = ptr as usize;
479 let length = std::mem::size_of::<T>() as u32;
480 let perms = CapabilityPermission::Read as u32
481 | CapabilityPermission::Write as u32;
482 let cap = unsafe {
484 WritableCapability::new(ptr, base, length, perms)
485 }.expect("Box::into_raw region cannot fail bounds check");
486 Self { cap }
487 }
488
489 pub fn cap(&self) -> &WritableCapability<T> { &self.cap }
490 pub fn cap_mut(&mut self) -> &mut WritableCapability<T> { &mut self.cap }
491
492 pub fn into_box(self) -> Box<T> {
494 let raw = self.cap.ptr;
495 std::mem::forget(self);
496 unsafe { Box::from_raw(raw) }
498 }
499}
500
501impl<T> std::ops::Deref for OwnedWritableCapability<T> {
502 type Target = WritableCapability<T>;
503 fn deref(&self) -> &Self::Target { &self.cap }
504}
505
506impl<T> std::ops::DerefMut for OwnedWritableCapability<T> {
507 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.cap }
508}
509
510impl<T> Drop for OwnedWritableCapability<T> {
511 fn drop(&mut self) {
512 let raw = self.cap.ptr;
513 let _reclaimed = unsafe { Box::from_raw(raw) };
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521
522 #[test]
525 fn readable_layout_is_24_bytes() {
526 assert_eq!(std::mem::size_of::<ReadableCapability<u64>>(), 24);
527 }
528
529 #[test]
530 fn writable_layout_is_24_bytes() {
531 assert_eq!(std::mem::size_of::<WritableCapability<u64>>(), 24);
532 }
533
534 #[test]
537 fn readable_from_slice_strips_write_bit() {
538 let storage: Vec<u64> = vec![42];
539 let (cap, _anchor) = ReadableCapability::from_slice(
540 &storage,
541 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
542 );
543 assert!(cap.has_permission(CapabilityPermission::Read));
544 assert!(!cap.has_permission(CapabilityPermission::Write));
546 }
547
548 #[test]
549 fn readable_read_with_permission() {
550 let storage: Vec<u64> = vec![42];
551 let (cap, _anchor) = ReadableCapability::from_slice(
552 &storage, CapabilityPermission::Read as u32,
553 );
554 assert_eq!(cap.read().unwrap(), 42);
555 }
556
557 #[test]
558 fn readable_read_without_permission_fails() {
559 let storage: Vec<u64> = vec![99];
560 let (cap, _anchor) = ReadableCapability::from_slice(&storage, 0);
561 assert_eq!(cap.read().err(), Some(CapabilityError::PermissionDenied));
562 }
563
564 #[test]
565 fn readable_sealed_blocks_read() {
566 let storage: Vec<u64> = vec![1];
567 let (cap, _anchor) = ReadableCapability::from_slice(
568 &storage, CapabilityPermission::Read as u32,
569 );
570 let sealed = cap.sealed();
571 assert_eq!(sealed.read().err(), Some(CapabilityError::Sealed));
572 }
573
574 #[test]
575 fn readable_unseal_restores() {
576 let storage: Vec<u64> = vec![7];
577 let (cap, _anchor) = ReadableCapability::from_slice(
578 &storage, CapabilityPermission::Read as u32,
579 );
580 let unsealed = cap.sealed().unsealed();
581 assert_eq!(unsealed.read().unwrap(), 7);
582 }
583
584 #[test]
585 fn readable_narrow_strips_write() {
586 let storage: Vec<u64> = vec![0, 0, 0, 0];
587 let (cap, anchor) = ReadableCapability::from_slice(
588 &storage,
589 CapabilityPermission::Read as u32,
590 );
591 let base = anchor.as_ptr() as usize;
592 let narrowed = cap.narrow(
593 base, 16,
594 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
595 ).unwrap();
596 assert!(narrowed.has_permission(CapabilityPermission::Read));
597 assert!(!narrowed.has_permission(CapabilityPermission::Write));
598 }
599
600 #[test]
601 fn readable_unsafe_new_overflow_guards() {
602 let ptr = usize::MAX as *const u64;
603 let r = unsafe {
604 ReadableCapability::<u64>::new(
605 ptr, usize::MAX, 16, CapabilityPermission::Read as u32,
606 )
607 };
608 assert_eq!(r.err(), Some(CapabilityError::AddressOverflow));
609 }
610
611 #[test]
614 fn writable_from_slice_mut_grants_read_and_write() {
615 let mut storage: Vec<u64> = vec![0];
616 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
617 assert!(cap.has_permission(CapabilityPermission::Read));
618 assert!(cap.has_permission(CapabilityPermission::Write));
619 }
620
621 #[test]
622 fn writable_write_then_read() {
623 let mut storage: Vec<u64> = vec![0];
624 {
625 let (mut cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
626 cap.write(7777).unwrap();
627 assert_eq!(cap.read().unwrap(), 7777);
628 }
629 assert_eq!(storage[0], 7777);
630 }
631
632 #[test]
633 fn writable_sealed_blocks_write() {
634 let mut storage: Vec<u64> = vec![0];
635 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
636 let mut sealed = cap.sealed();
637 assert_eq!(sealed.write(99u64).err(), Some(CapabilityError::Sealed));
638 }
639
640 #[test]
641 fn writable_as_readable_view_strips_write() {
642 let mut storage: Vec<u64> = vec![42];
643 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
644 let read_view = cap.as_readable();
645 assert!(read_view.has_permission(CapabilityPermission::Read));
646 assert!(!read_view.has_permission(CapabilityPermission::Write));
647 assert_eq!(read_view.read().unwrap(), 42);
648 }
649
650 #[test]
651 fn writable_narrow_readable_strips_write() {
652 let mut storage: Vec<u64> = vec![0, 0];
653 let (cap, _anchor) = WritableCapability::from_slice_mut(&mut storage);
654 let base = cap.ptr as usize;
655 let narrowed: ReadableCapability<u64> = cap.narrow_readable(
656 base, 8,
657 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
658 ).unwrap();
659 assert!(narrowed.has_permission(CapabilityPermission::Read));
660 assert!(!narrowed.has_permission(CapabilityPermission::Write));
661 }
662
663 #[test]
664 fn writable_unsafe_new_overflow_guards() {
665 let ptr = usize::MAX as *mut u64;
666 let r = unsafe {
667 WritableCapability::<u64>::new(
668 ptr, usize::MAX, 16,
669 CapabilityPermission::Read as u32 | CapabilityPermission::Write as u32,
670 )
671 };
672 assert_eq!(r.err(), Some(CapabilityError::AddressOverflow));
673 }
674
675 #[test]
678 fn owned_readable_new_and_read() {
679 let owned = OwnedReadableCapability::new(42u64);
680 assert_eq!(owned.read().unwrap(), 42);
681 }
682
683 #[test]
684 fn owned_readable_drop_reclaims() {
685 use std::sync::atomic::{AtomicUsize, Ordering};
686 static DROPS: AtomicUsize = AtomicUsize::new(0);
687 struct DropCounter;
688 impl Drop for DropCounter {
689 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
690 }
691 let before = DROPS.load(Ordering::Relaxed);
692 { let _o = OwnedReadableCapability::new(DropCounter); }
693 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
694 }
695
696 #[test]
699 fn owned_writable_write_then_read() {
700 let mut owned = OwnedWritableCapability::new(0u64);
701 owned.cap_mut().write(555).unwrap();
702 assert_eq!(owned.read().unwrap(), 555);
703 }
704
705 #[test]
706 fn owned_writable_drop_reclaims() {
707 use std::sync::atomic::{AtomicUsize, Ordering};
708 static DROPS: AtomicUsize = AtomicUsize::new(0);
709 struct DropCounter;
710 impl Drop for DropCounter {
711 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
712 }
713 let before = DROPS.load(Ordering::Relaxed);
714 { let _o = OwnedWritableCapability::new(DropCounter); }
715 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
716 }
717
718 #[test]
719 fn owned_writable_into_box_suppresses_drop() {
720 use std::sync::atomic::{AtomicUsize, Ordering};
721 static DROPS: AtomicUsize = AtomicUsize::new(0);
722 struct DropCounter(u32);
723 impl Drop for DropCounter {
724 fn drop(&mut self) { DROPS.fetch_add(1, Ordering::Relaxed); }
725 }
726 let before = DROPS.load(Ordering::Relaxed);
727 let owned = OwnedWritableCapability::new(DropCounter(99));
728 let b = owned.into_box();
729 assert_eq!(DROPS.load(Ordering::Relaxed), before);
731 assert_eq!(b.0, 99);
732 drop(b);
733 assert_eq!(DROPS.load(Ordering::Relaxed), before + 1);
735 }
736
737 #[test]
738 fn owned_writable_into_box_round_trip_value() {
739 let owned = OwnedWritableCapability::new(12345u64);
740 let b = owned.into_box();
741 assert_eq!(*b, 12345);
742 }
743}