1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
17 use ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
18 use slice::SliceIndex;
20 use fortanix_sgx_abi::*;
21 use super::super::mem::is_user_range;
23 /// A type that can be safely read from or written to userspace.
25 /// Non-exhaustive list of specific requirements for reading and writing:
26 /// * **Type is `Copy`** (and therefore also not `Drop`). Copies will be
27 /// created when copying from/to userspace. Destructors will not be called.
28 /// * **No references or Rust-style owned pointers** (`Vec`, `Arc`, etc.). When
29 /// reading from userspace, references into enclave memory must not be
30 /// created. Also, only enclave memory is considered managed by the Rust
31 /// compiler's static analysis. When reading from userspace, there can be no
32 /// guarantee that the value correctly adheres to the expectations of the
33 /// type. When writing to userspace, memory addresses of data in enclave
34 /// memory must not be leaked for confidentiality reasons. `User` and
35 /// `UserRef` are also not allowed for the same reasons.
36 /// * **No fat pointers.** When reading from userspace, the size or vtable
37 /// pointer could be automatically interpreted and used by the code. When
38 /// writing to userspace, memory addresses of data in enclave memory (such
39 /// as vtable pointers) must not be leaked for confidentiality reasons.
41 /// Non-exhaustive list of specific requirements for reading from userspace:
42 /// * Any bit pattern is valid for this type (no `enum`s). There can be no
43 /// guarantee that the value correctly adheres to the expectations of the
44 /// type, so any value must be valid for this type.
46 /// Non-exhaustive list of specific requirements for writing to userspace:
47 /// * No pointers to enclave memory. Memory addresses of data in enclave memory
48 /// must not be leaked for confidentiality reasons.
49 /// * No internal padding. Padding might contain previously-initialized secret
50 /// data stored at that memory location and must not be leaked for
51 /// confidentiality reasons.
52 pub unsafe trait UserSafeSized: Copy + Sized {}
54 unsafe impl UserSafeSized for u8 {}
55 unsafe impl<T> UserSafeSized for FifoDescriptor<T> {}
56 unsafe impl UserSafeSized for ByteBuffer {}
57 unsafe impl UserSafeSized for Usercall {}
58 unsafe impl UserSafeSized for Return {}
59 unsafe impl<T: UserSafeSized> UserSafeSized for [T; 2] {}
61 /// A type that can be represented in memory as one or more `UserSafeSized`s.
62 pub unsafe trait UserSafe {
63 unsafe fn align_of() -> usize;
65 /// NB. This takes a size, not a length!
66 unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self;
68 /// NB. This takes a size, not a length!
69 unsafe fn from_raw_sized(ptr: *const u8, size: usize) -> *const Self {
70 let ret = Self::from_raw_sized_unchecked(ptr, size);
75 unsafe fn check_ptr(ptr: *const Self) {
76 let is_aligned = |p| -> bool {
77 0 == (p as usize) & (Self::align_of() - 1)
80 assert!(is_aligned(ptr as *const u8));
81 assert!(is_user_range(ptr as _, mem::size_of_val(&*ptr)));
82 assert!(!ptr.is_null());
86 unsafe impl<T: UserSafeSized> UserSafe for T {
87 unsafe fn align_of() -> usize {
91 unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self {
92 assert_eq!(size, mem::size_of::<T>());
97 unsafe impl<T: UserSafeSized> UserSafe for [T] {
98 unsafe fn align_of() -> usize {
102 unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self {
103 let elem_size = mem::size_of::<T>();
104 assert_eq!(size % elem_size, 0);
105 let len = size / elem_size;
106 slice::from_raw_parts(ptr as _, len)
110 /// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
111 /// to `&T` in enclave memory. Access to the memory is only allowed by copying
112 /// to avoid TOCTTOU issues. After copying, code should make sure to completely
113 /// check the value before use.
114 pub struct UserRef<T: ?Sized>(UnsafeCell<T>);
115 /// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
116 /// enclave memory. Access to the memory is only allowed by copying to avoid
117 /// TOCTTOU issues. The user memory will be freed when the value is dropped.
118 /// After copying, code should make sure to completely check the value before
120 pub struct User<T: UserSafe + ?Sized>(*mut UserRef<T>);
122 impl<T: ?Sized> User<T> where T: UserSafe {
123 // This function returns memory that is practically uninitialized, but is
124 // not considered "unspecified" or "undefined" for purposes of an
125 // optimizing compiler. This is achieved by returning a pointer from
126 // from outside as obtained by `super::alloc`.
127 fn new_uninit_bytes(size: usize) -> Self {
129 let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
130 User(T::from_raw_sized(ptr as _, size) as _)
134 pub fn new_from_enclave(val: &T) -> Self {
136 let ret = Self::new_uninit_bytes(mem::size_of_val(val));
138 val as *const T as *const u8,
139 ret.0 as *mut T as *mut u8,
140 mem::size_of_val(val)
146 /// Create an owned `User<T>` from a raw pointer. The pointer should be
147 /// freeable with the `free` usercall and the alignment of `T`.
150 /// This function panics if:
152 /// * The pointer is not aligned
153 /// * The pointer is null
154 /// * The pointed-to range is not in user memory
155 pub unsafe fn from_raw(ptr: *mut T) -> Self {
160 /// Convert this value into a raw pointer. The value will no longer be
161 /// automatically freed.
162 pub fn into_raw(self) -> *mut T {
169 impl<T> User<T> where T: UserSafe {
170 pub fn uninitialized() -> Self {
171 Self::new_uninit_bytes(mem::size_of::<T>())
175 impl<T> User<[T]> where [T]: UserSafe {
176 pub fn uninitialized(n: usize) -> Self {
177 Self::new_uninit_bytes(n * mem::size_of::<T>())
180 /// Create an owned `User<[T]>` from a raw thin pointer and a slice length.
181 /// The pointer should be freeable with the `free` usercall and the
182 /// alignment of `T`.
185 /// This function panics if:
187 /// * The pointer is not aligned
188 /// * The pointer is null
189 /// * The pointed-to range is not in user memory
190 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
191 User(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()) as _)
195 impl<T: ?Sized> UserRef<T> where T: UserSafe {
196 /// Create a `&UserRef<[T]>` from a raw pointer.
199 /// This function panics if:
201 /// * The pointer is not aligned
202 /// * The pointer is null
203 /// * The pointed-to range is not in user memory
204 pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
206 &*(ptr as *const Self)
209 /// Create a `&mut UserRef<[T]>` from a raw pointer.
212 /// This function panics if:
214 /// * The pointer is not aligned
215 /// * The pointer is null
216 /// * The pointed-to range is not in user memory
217 pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
219 &mut*(ptr as *mut Self)
223 /// This function panics if the destination doesn't have the same size as
224 /// the source. This can happen for dynamically-sized types such as slices.
225 pub fn copy_from_enclave(&mut self, val: &T) {
227 assert_eq!(mem::size_of_val(val), mem::size_of_val( &*self.0.get() ));
229 val as *const T as *const u8,
230 self.0.get() as *mut T as *mut u8,
231 mem::size_of_val(val)
237 /// This function panics if the destination doesn't have the same size as
238 /// the source. This can happen for dynamically-sized types such as slices.
239 pub fn copy_to_enclave(&self, dest: &mut T) {
241 assert_eq!(mem::size_of_val(dest), mem::size_of_val( &*self.0.get() ));
243 self.0.get() as *const T as *const u8,
244 dest as *mut T as *mut u8,
245 mem::size_of_val(dest)
250 pub fn as_raw_ptr(&self) -> *const T {
251 self as *const _ as _
254 pub fn as_raw_mut_ptr(&mut self) -> *mut T {
259 impl<T> UserRef<T> where T: UserSafe {
260 pub fn to_enclave(&self) -> T {
261 unsafe { ptr::read(self.0.get()) }
265 impl<T> UserRef<[T]> where [T]: UserSafe {
266 /// Create a `&UserRef<[T]>` from a raw thin pointer and a slice length.
269 /// This function panics if:
271 /// * The pointer is not aligned
272 /// * The pointer is null
273 /// * The pointed-to range is not in user memory
274 pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
275 &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()) as *const Self)
278 /// Create a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
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_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
287 &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()) as *mut Self)
290 pub fn as_ptr(&self) -> *const T {
294 pub fn as_mut_ptr(&mut self) -> *mut T {
298 pub fn len(&self) -> usize {
299 unsafe { (*self.0.get()).len() }
302 pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
304 if let Some(missing) = self.len().checked_sub(dest.capacity()) {
305 dest.reserve(missing)
307 dest.set_len(self.len());
308 self.copy_to_enclave(&mut dest[..]);
312 pub fn to_enclave(&self) -> Vec<T> {
313 let mut ret = Vec::with_capacity(self.len());
314 self.copy_to_enclave_vec(&mut ret);
318 pub fn iter(&self) -> Iter<T>
319 where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
322 Iter((&*self.as_raw_ptr()).iter())
326 pub fn iter_mut(&mut self) -> IterMut<T>
327 where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
330 IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
335 pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
337 impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
338 type Item = &'a UserRef<T>;
341 fn next(&mut self) -> Option<Self::Item> {
343 self.0.next().map(|e| UserRef::from_ptr(e))
348 pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
350 impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
351 type Item = &'a mut UserRef<T>;
354 fn next(&mut self) -> Option<Self::Item> {
356 self.0.next().map(|e| UserRef::from_mut_ptr(e))
361 impl<T: ?Sized> Deref for User<T> where T: UserSafe {
362 type Target = UserRef<T>;
364 fn deref(&self) -> &Self::Target {
369 impl<T: ?Sized> DerefMut for User<T> where T: UserSafe {
370 fn deref_mut(&mut self) -> &mut Self::Target {
371 unsafe { &mut*self.0 }
375 impl<T: ?Sized> Drop for User<T> where T: UserSafe {
378 let ptr = (*self.0).0.get();
379 super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of());
384 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
386 impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
387 type Output = UserRef<I::Output>;
390 fn index(&self, index: I) -> &UserRef<I::Output> {
392 UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
397 impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
399 fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
401 UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))