3 use crate::ptr::{self, NonNull};
5 use crate::cell::UnsafeCell;
7 use crate::ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
8 use crate::slice::SliceIndex;
10 use fortanix_sgx_abi::*;
11 use super::super::mem::is_user_range;
13 /// A type that can be safely read from or written to userspace.
15 /// Non-exhaustive list of specific requirements for reading and writing:
16 /// * **Type is `Copy`** (and therefore also not `Drop`). Copies will be
17 /// created when copying from/to userspace. Destructors will not be called.
18 /// * **No references or Rust-style owned pointers** (`Vec`, `Arc`, etc.). When
19 /// reading from userspace, references into enclave memory must not be
20 /// created. Also, only enclave memory is considered managed by the Rust
21 /// compiler's static analysis. When reading from userspace, there can be no
22 /// guarantee that the value correctly adheres to the expectations of the
23 /// type. When writing to userspace, memory addresses of data in enclave
24 /// memory must not be leaked for confidentiality reasons. `User` and
25 /// `UserRef` are also not allowed for the same reasons.
26 /// * **No fat pointers.** When reading from userspace, the size or vtable
27 /// pointer could be automatically interpreted and used by the code. When
28 /// writing to userspace, memory addresses of data in enclave memory (such
29 /// as vtable pointers) must not be leaked for confidentiality reasons.
31 /// Non-exhaustive list of specific requirements for reading from userspace:
32 /// * **Any bit pattern is valid** for this type (no `enum`s). There can be no
33 /// guarantee that the value correctly adheres to the expectations of the
34 /// type, so any value must be valid for this type.
36 /// Non-exhaustive list of specific requirements for writing to userspace:
37 /// * **No pointers to enclave memory.** Memory addresses of data in enclave
38 /// memory must not be leaked for confidentiality reasons.
39 /// * **No internal padding.** Padding might contain previously-initialized
40 /// secret data stored at that memory location and must not be leaked for
41 /// confidentiality reasons.
42 #[unstable(feature = "sgx_platform", issue = "56975")]
43 pub unsafe trait UserSafeSized: Copy + Sized {}
45 #[unstable(feature = "sgx_platform", issue = "56975")]
46 unsafe impl UserSafeSized for u8 {}
47 #[unstable(feature = "sgx_platform", issue = "56975")]
48 unsafe impl<T> UserSafeSized for FifoDescriptor<T> {}
49 #[unstable(feature = "sgx_platform", issue = "56975")]
50 unsafe impl UserSafeSized for ByteBuffer {}
51 #[unstable(feature = "sgx_platform", issue = "56975")]
52 unsafe impl UserSafeSized for Usercall {}
53 #[unstable(feature = "sgx_platform", issue = "56975")]
54 unsafe impl UserSafeSized for Return {}
55 #[unstable(feature = "sgx_platform", issue = "56975")]
56 unsafe impl<T: UserSafeSized> UserSafeSized for [T; 2] {}
58 /// A type that can be represented in memory as one or more `UserSafeSized`s.
59 #[unstable(feature = "sgx_platform", issue = "56975")]
60 pub unsafe trait UserSafe {
61 /// Equivalent to `mem::align_of::<Self>`.
62 fn align_of() -> usize;
64 /// Construct a pointer to `Self` given a memory range in user space.
66 /// N.B., this takes a size, not a length!
70 /// The caller must ensure the memory range is in user memory, is the
71 /// correct size and is correctly aligned and points to the right type.
72 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self;
74 /// Construct a pointer to `Self` given a memory range.
76 /// N.B., this takes a size, not a length!
80 /// The caller must ensure the memory range points to the correct type.
84 /// This function panics if:
86 /// * the pointer is not aligned.
87 /// * the pointer is null.
88 /// * the pointed-to range is not in user memory.
89 unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull<Self> {
90 let ret = Self::from_raw_sized_unchecked(ptr, size);
92 NonNull::new_unchecked(ret as _)
95 /// Checks if a pointer may point to `Self` in user memory.
99 /// The caller must ensure the memory range points to the correct type and
100 /// length (if this is a slice).
104 /// This function panics if:
106 /// * the pointer is not aligned.
107 /// * the pointer is null.
108 /// * the pointed-to range is not in user memory.
109 unsafe fn check_ptr(ptr: *const Self) {
110 let is_aligned = |p| -> bool {
111 0 == (p as usize) & (Self::align_of() - 1)
114 assert!(is_aligned(ptr as *const u8));
115 assert!(is_user_range(ptr as _, mem::size_of_val(&*ptr)));
116 assert!(!ptr.is_null());
120 #[unstable(feature = "sgx_platform", issue = "56975")]
121 unsafe impl<T: UserSafeSized> UserSafe for T {
122 fn align_of() -> usize {
126 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
127 assert_eq!(size, mem::size_of::<T>());
132 #[unstable(feature = "sgx_platform", issue = "56975")]
133 unsafe impl<T: UserSafeSized> UserSafe for [T] {
134 fn align_of() -> usize {
138 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
139 let elem_size = mem::size_of::<T>();
140 assert_eq!(size % elem_size, 0);
141 let len = size / elem_size;
142 slice::from_raw_parts_mut(ptr as _, len)
146 /// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
147 /// to `&T` in enclave memory. Access to the memory is only allowed by copying
148 /// to avoid TOCTTOU issues. After copying, code should make sure to completely
149 /// check the value before use.
151 /// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
152 /// regular mutable references, these are not exclusive. Userspace may always
153 /// write to the backing memory at any time, so it can't be assumed that there
154 /// the pointed-to memory is uniquely borrowed. The two different refence types
155 /// are used solely to indicate intent: a mutable reference is for writing to
156 /// user memory, an immutable reference for reading from user memory.
157 #[unstable(feature = "sgx_platform", issue = "56975")]
158 pub struct UserRef<T: ?Sized>(UnsafeCell<T>);
159 /// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
160 /// enclave memory. Access to the memory is only allowed by copying to avoid
161 /// TOCTTOU issues. The user memory will be freed when the value is dropped.
162 /// After copying, code should make sure to completely check the value before
164 #[unstable(feature = "sgx_platform", issue = "56975")]
165 pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>);
167 trait NewUserRef<T: ?Sized> {
168 unsafe fn new_userref(v: T) -> Self;
171 impl<T: ?Sized> NewUserRef<*mut T> for NonNull<UserRef<T>> {
172 unsafe fn new_userref(v: *mut T) -> Self {
173 NonNull::new_unchecked(v as _)
177 impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
178 unsafe fn new_userref(v: NonNull<T>) -> Self {
179 NonNull::new_userref(v.as_ptr())
183 #[unstable(feature = "sgx_platform", issue = "56975")]
184 impl<T: ?Sized> User<T> where T: UserSafe {
185 // This function returns memory that is practically uninitialized, but is
186 // not considered "unspecified" or "undefined" for purposes of an
187 // optimizing compiler. This is achieved by returning a pointer from
188 // from outside as obtained by `super::alloc`.
189 fn new_uninit_bytes(size: usize) -> Self {
191 // Mustn't call alloc with size 0.
192 let ptr = if size > 0 {
193 super::alloc(size, T::align_of()).expect("User memory allocation failed") as _
195 T::align_of() as _ // dangling pointer ok for size 0
197 User(NonNull::new_userref(T::from_raw_sized(ptr, size)))
201 /// Copies `val` into freshly allocated space in user memory.
202 pub fn new_from_enclave(val: &T) -> Self {
204 let ret = Self::new_uninit_bytes(mem::size_of_val(val));
206 val as *const T as *const u8,
207 ret.0.as_ptr() as *mut u8,
208 mem::size_of_val(val)
214 /// Creates an owned `User<T>` from a raw pointer.
217 /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
218 /// usercall and the alignment of `T`, and is uniquely owned.
221 /// This function panics if:
223 /// * The pointer is not aligned
224 /// * The pointer is null
225 /// * The pointed-to range is not in user memory
226 pub unsafe fn from_raw(ptr: *mut T) -> Self {
228 User(NonNull::new_userref(ptr))
231 /// Converts this value into a raw pointer. The value will no longer be
232 /// automatically freed.
233 pub fn into_raw(self) -> *mut T {
240 #[unstable(feature = "sgx_platform", issue = "56975")]
241 impl<T> User<T> where T: UserSafe {
242 /// Allocate space for `T` in user memory.
243 pub fn uninitialized() -> Self {
244 Self::new_uninit_bytes(mem::size_of::<T>())
248 #[unstable(feature = "sgx_platform", issue = "56975")]
249 impl<T> User<[T]> where [T]: UserSafe {
250 /// Allocate space for a `[T]` of `n` elements in user memory.
251 pub fn uninitialized(n: usize) -> Self {
252 Self::new_uninit_bytes(n * mem::size_of::<T>())
255 /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length.
258 /// The caller must ensure `ptr` points to `len` elements of `T`, is
259 /// freeable with the `free` usercall and the alignment of `T`, and is
263 /// This function panics if:
265 /// * The pointer is not aligned
266 /// * The pointer is null
267 /// * The pointed-to range is not in user memory
268 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
269 User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())))
273 #[unstable(feature = "sgx_platform", issue = "56975")]
274 impl<T: ?Sized> UserRef<T> where T: UserSafe {
275 /// Creates a `&UserRef<[T]>` from a raw pointer.
278 /// The caller must ensure `ptr` points to `T`.
281 /// This function panics if:
283 /// * The pointer is not aligned
284 /// * The pointer is null
285 /// * The pointed-to range is not in user memory
286 pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
288 &*(ptr as *const Self)
291 /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct
292 /// documentation for the nuances regarding a `&mut UserRef<T>`.
295 /// The caller must ensure `ptr` points to `T`.
298 /// This function panics if:
300 /// * The pointer is not aligned
301 /// * The pointer is null
302 /// * The pointed-to range is not in user memory
303 pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
305 &mut*(ptr as *mut Self)
308 /// Copies `val` into user memory.
311 /// This function panics if the destination doesn't have the same size as
312 /// the source. This can happen for dynamically-sized types such as slices.
313 pub fn copy_from_enclave(&mut self, val: &T) {
315 assert_eq!(mem::size_of_val(val), mem::size_of_val( &*self.0.get() ));
317 val as *const T as *const u8,
318 self.0.get() as *mut T as *mut u8,
319 mem::size_of_val(val)
324 /// Copies the value from user memory and place it into `dest`.
327 /// This function panics if the destination doesn't have the same size as
328 /// the source. This can happen for dynamically-sized types such as slices.
329 pub fn copy_to_enclave(&self, dest: &mut T) {
331 assert_eq!(mem::size_of_val(dest), mem::size_of_val( &*self.0.get() ));
333 self.0.get() as *const T as *const u8,
334 dest as *mut T as *mut u8,
335 mem::size_of_val(dest)
340 /// Obtain a raw pointer from this reference.
341 pub fn as_raw_ptr(&self) -> *const T {
342 self as *const _ as _
345 /// Obtain a raw pointer from this reference.
346 pub fn as_raw_mut_ptr(&mut self) -> *mut T {
351 #[unstable(feature = "sgx_platform", issue = "56975")]
352 impl<T> UserRef<T> where T: UserSafe {
353 /// Copies the value from user memory into enclave memory.
354 pub fn to_enclave(&self) -> T {
355 unsafe { ptr::read(self.0.get()) }
359 #[unstable(feature = "sgx_platform", issue = "56975")]
360 impl<T> UserRef<[T]> where [T]: UserSafe {
361 /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length.
364 /// The caller must ensure `ptr` points to `n` elements of `T`.
367 /// This function panics if:
369 /// * The pointer is not aligned
370 /// * The pointer is null
371 /// * The pointed-to range is not in user memory
372 pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
373 &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
376 /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
377 /// See the struct documentation for the nuances regarding a
378 /// `&mut UserRef<T>`.
381 /// The caller must ensure `ptr` points to `n` elements of `T`.
384 /// This function panics if:
386 /// * The pointer is not aligned
387 /// * The pointer is null
388 /// * The pointed-to range is not in user memory
389 pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
390 &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
393 /// Obtain a raw pointer to the first element of this user slice.
394 pub fn as_ptr(&self) -> *const T {
398 /// Obtain a raw pointer to the first element of this user slice.
399 pub fn as_mut_ptr(&mut self) -> *mut T {
403 /// Obtain the number of elements in this user slice.
404 pub fn len(&self) -> usize {
405 unsafe { (*self.0.get()).len() }
408 /// Copies the value from user memory and place it into `dest`. Afterwards,
409 /// `dest` will contain exactly `self.len()` elements.
412 /// This function panics if the destination doesn't have the same size as
413 /// the source. This can happen for dynamically-sized types such as slices.
414 pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
416 if let Some(missing) = self.len().checked_sub(dest.capacity()) {
417 dest.reserve(missing)
419 dest.set_len(self.len());
420 self.copy_to_enclave(&mut dest[..]);
424 /// Copies the value from user memory into a vector in enclave memory.
425 pub fn to_enclave(&self) -> Vec<T> {
426 let mut ret = Vec::with_capacity(self.len());
427 self.copy_to_enclave_vec(&mut ret);
431 /// Returns an iterator over the slice.
432 pub fn iter(&self) -> Iter<'_, T>
433 where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
436 Iter((&*self.as_raw_ptr()).iter())
440 /// Returns an iterator that allows modifying each value.
441 pub fn iter_mut(&mut self) -> IterMut<'_, T>
442 where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
445 IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
450 /// Immutable user slice iterator
452 /// This struct is created by the `iter` method on `UserRef<[T]>`.
453 #[unstable(feature = "sgx_platform", issue = "56975")]
454 pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
456 #[unstable(feature = "sgx_platform", issue = "56975")]
457 impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
458 type Item = &'a UserRef<T>;
461 fn next(&mut self) -> Option<Self::Item> {
463 self.0.next().map(|e| UserRef::from_ptr(e))
468 /// Mutable user slice iterator
470 /// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
471 #[unstable(feature = "sgx_platform", issue = "56975")]
472 pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
474 #[unstable(feature = "sgx_platform", issue = "56975")]
475 impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
476 type Item = &'a mut UserRef<T>;
479 fn next(&mut self) -> Option<Self::Item> {
481 self.0.next().map(|e| UserRef::from_mut_ptr(e))
486 #[unstable(feature = "sgx_platform", issue = "56975")]
487 impl<T: ?Sized> Deref for User<T> where T: UserSafe {
488 type Target = UserRef<T>;
490 fn deref(&self) -> &Self::Target {
491 unsafe { &*self.0.as_ptr() }
495 #[unstable(feature = "sgx_platform", issue = "56975")]
496 impl<T: ?Sized> DerefMut for User<T> where T: UserSafe {
497 fn deref_mut(&mut self) -> &mut Self::Target {
498 unsafe { &mut*self.0.as_ptr() }
502 #[unstable(feature = "sgx_platform", issue = "56975")]
503 impl<T: ?Sized> Drop for User<T> where T: UserSafe {
506 let ptr = (*self.0.as_ptr()).0.get();
507 super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of());
512 #[unstable(feature = "sgx_platform", issue = "56975")]
513 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
515 #[unstable(feature = "sgx_platform", issue = "56975")]
516 impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
517 type Output = UserRef<I::Output>;
520 fn index(&self, index: I) -> &UserRef<I::Output> {
522 UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
527 #[unstable(feature = "sgx_platform", issue = "56975")]
528 impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
530 fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
532 UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))
537 #[unstable(feature = "sgx_platform", issue = "56975")]
538 impl UserRef<super::raw::ByteBuffer> {
539 /// Copies the user memory range pointed to by the user `ByteBuffer` to
543 /// This function panics if:
545 /// * The pointer in the user `ByteBuffer` is null
546 /// * The pointed-to range in the user `ByteBuffer` is not in user memory
547 pub fn copy_user_buffer(&self) -> Vec<u8> {
549 let buf = self.to_enclave();
551 User::from_raw_parts(buf.data as _, buf.len).to_enclave()
553 // Mustn't look at `data` or call `free` if `len` is `0`.
554 Vec::with_capacity(0)