]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/alloc.rs
SGX target: convert a bunch of panics to aborts
[rust.git] / src / libstd / sys / sgx / abi / usercalls / alloc.rs
1 #![allow(unused)]
2
3 use crate::ptr::{self, NonNull};
4 use crate::mem;
5 use crate::cell::UnsafeCell;
6 use crate::slice;
7 use crate::ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
8 use crate::slice::SliceIndex;
9
10 use fortanix_sgx_abi::*;
11 use super::super::mem::is_user_range;
12
13 /// A type that can be safely read from or written to userspace.
14 ///
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.
30 ///
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.
35 ///
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 {}
44
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] {}
57
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;
63
64     /// Construct a pointer to `Self` given a memory range in user space.
65     ///
66     /// N.B., this takes a size, not a length!
67     ///
68     /// # Safety
69     ///
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;
73
74     /// Construct a pointer to `Self` given a memory range.
75     ///
76     /// N.B., this takes a size, not a length!
77     ///
78     /// # Safety
79     ///
80     /// The caller must ensure the memory range points to the correct type.
81     ///
82     /// # Panics
83     ///
84     /// This function panics if:
85     ///
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);
91         Self::check_ptr(ret);
92         NonNull::new_unchecked(ret as _)
93     }
94
95     /// Checks if a pointer may point to `Self` in user memory.
96     ///
97     /// # Safety
98     ///
99     /// The caller must ensure the memory range points to the correct type and
100     /// length (if this is a slice).
101     ///
102     /// # Panics
103     ///
104     /// This function panics if:
105     ///
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)
112         };
113
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());
117     }
118 }
119
120 #[unstable(feature = "sgx_platform", issue = "56975")]
121 unsafe impl<T: UserSafeSized> UserSafe for T {
122     fn align_of() -> usize {
123         mem::align_of::<T>()
124     }
125
126     unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
127         assert_eq!(size, mem::size_of::<T>());
128         ptr as _
129     }
130 }
131
132 #[unstable(feature = "sgx_platform", issue = "56975")]
133 unsafe impl<T: UserSafeSized> UserSafe for [T] {
134     fn align_of() -> usize {
135         mem::align_of::<T>()
136     }
137
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)
143     }
144 }
145
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.
150 ///
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
163 /// use.
164 #[unstable(feature = "sgx_platform", issue = "56975")]
165 pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>);
166
167 trait NewUserRef<T: ?Sized> {
168     unsafe fn new_userref(v: T) -> Self;
169 }
170
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 _)
174     }
175 }
176
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())
180     }
181 }
182
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 {
190         unsafe {
191             // Mustn't call alloc with size 0.
192             let ptr = if size > 0 {
193                 rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
194             } else {
195                 T::align_of() as _ // dangling pointer ok for size 0
196             };
197             if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) {
198                 User(NonNull::new_userref(v))
199             } else {
200                 rtabort!("Got invalid pointer from alloc() usercall")
201             }
202         }
203     }
204
205     /// Copies `val` into freshly allocated space in user memory.
206     pub fn new_from_enclave(val: &T) -> Self {
207         unsafe {
208             let ret = Self::new_uninit_bytes(mem::size_of_val(val));
209             ptr::copy(
210                 val as *const T as *const u8,
211                 ret.0.as_ptr() as *mut u8,
212                 mem::size_of_val(val)
213             );
214             ret
215         }
216     }
217
218     /// Creates an owned `User<T>` from a raw pointer.
219     ///
220     /// # Safety
221     /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
222     /// usercall and the alignment of `T`, and is uniquely owned.
223     ///
224     /// # Panics
225     /// This function panics if:
226     ///
227     /// * The pointer is not aligned
228     /// * The pointer is null
229     /// * The pointed-to range is not in user memory
230     pub unsafe fn from_raw(ptr: *mut T) -> Self {
231         T::check_ptr(ptr);
232         User(NonNull::new_userref(ptr))
233     }
234
235     /// Converts this value into a raw pointer. The value will no longer be
236     /// automatically freed.
237     pub fn into_raw(self) -> *mut T {
238         let ret = self.0;
239         mem::forget(self);
240         ret.as_ptr() as _
241     }
242 }
243
244 #[unstable(feature = "sgx_platform", issue = "56975")]
245 impl<T> User<T> where T: UserSafe {
246     /// Allocate space for `T` in user memory.
247     pub fn uninitialized() -> Self {
248         Self::new_uninit_bytes(mem::size_of::<T>())
249     }
250 }
251
252 #[unstable(feature = "sgx_platform", issue = "56975")]
253 impl<T> User<[T]> where [T]: UserSafe {
254     /// Allocate space for a `[T]` of `n` elements in user memory.
255     pub fn uninitialized(n: usize) -> Self {
256         Self::new_uninit_bytes(n * mem::size_of::<T>())
257     }
258
259     /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length.
260     ///
261     /// # Safety
262     /// The caller must ensure `ptr` points to `len` elements of `T`, is
263     /// freeable with the `free` usercall and the alignment of `T`, and is
264     /// uniquely owned.
265     ///
266     /// # Panics
267     /// This function panics if:
268     ///
269     /// * The pointer is not aligned
270     /// * The pointer is null
271     /// * The pointed-to range is not in user memory
272     pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
273         User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())))
274     }
275 }
276
277 #[unstable(feature = "sgx_platform", issue = "56975")]
278 impl<T: ?Sized> UserRef<T> where T: UserSafe {
279     /// Creates a `&UserRef<[T]>` from a raw pointer.
280     ///
281     /// # Safety
282     /// The caller must ensure `ptr` points to `T`.
283     ///
284     /// # Panics
285     /// This function panics if:
286     ///
287     /// * The pointer is not aligned
288     /// * The pointer is null
289     /// * The pointed-to range is not in user memory
290     pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
291         T::check_ptr(ptr);
292         &*(ptr as *const Self)
293     }
294
295     /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct
296     /// documentation for the nuances regarding a `&mut UserRef<T>`.
297     ///
298     /// # Safety
299     /// The caller must ensure `ptr` points to `T`.
300     ///
301     /// # Panics
302     /// This function panics if:
303     ///
304     /// * The pointer is not aligned
305     /// * The pointer is null
306     /// * The pointed-to range is not in user memory
307     pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
308         T::check_ptr(ptr);
309         &mut*(ptr as *mut Self)
310     }
311
312     /// Copies `val` into user memory.
313     ///
314     /// # Panics
315     /// This function panics if the destination doesn't have the same size as
316     /// the source. This can happen for dynamically-sized types such as slices.
317     pub fn copy_from_enclave(&mut self, val: &T) {
318         unsafe {
319             assert_eq!(mem::size_of_val(val), mem::size_of_val( &*self.0.get() ));
320             ptr::copy(
321                 val as *const T as *const u8,
322                 self.0.get() as *mut T as *mut u8,
323                 mem::size_of_val(val)
324             );
325         }
326     }
327
328     /// Copies the value from user memory and place it into `dest`.
329     ///
330     /// # Panics
331     /// This function panics if the destination doesn't have the same size as
332     /// the source. This can happen for dynamically-sized types such as slices.
333     pub fn copy_to_enclave(&self, dest: &mut T) {
334         unsafe {
335             assert_eq!(mem::size_of_val(dest), mem::size_of_val( &*self.0.get() ));
336             ptr::copy(
337                 self.0.get() as *const T as *const u8,
338                 dest as *mut T as *mut u8,
339                 mem::size_of_val(dest)
340             );
341         }
342     }
343
344     /// Obtain a raw pointer from this reference.
345     pub fn as_raw_ptr(&self) -> *const T {
346         self as *const _ as _
347     }
348
349     /// Obtain a raw pointer from this reference.
350     pub fn as_raw_mut_ptr(&mut self) -> *mut T {
351         self as *mut _ as _
352     }
353 }
354
355 #[unstable(feature = "sgx_platform", issue = "56975")]
356 impl<T> UserRef<T> where T: UserSafe {
357     /// Copies the value from user memory into enclave memory.
358     pub fn to_enclave(&self) -> T {
359         unsafe { ptr::read(self.0.get()) }
360     }
361 }
362
363 #[unstable(feature = "sgx_platform", issue = "56975")]
364 impl<T> UserRef<[T]> where [T]: UserSafe {
365     /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length.
366     ///
367     /// # Safety
368     /// The caller must ensure `ptr` points to `n` elements of `T`.
369     ///
370     /// # Panics
371     /// This function panics if:
372     ///
373     /// * The pointer is not aligned
374     /// * The pointer is null
375     /// * The pointed-to range is not in user memory
376     pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
377         &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
378     }
379
380     /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
381     /// See the struct documentation for the nuances regarding a
382     /// `&mut UserRef<T>`.
383     ///
384     /// # Safety
385     /// The caller must ensure `ptr` points to `n` elements of `T`.
386     ///
387     /// # Panics
388     /// This function panics if:
389     ///
390     /// * The pointer is not aligned
391     /// * The pointer is null
392     /// * The pointed-to range is not in user memory
393     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
394         &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
395     }
396
397     /// Obtain a raw pointer to the first element of this user slice.
398     pub fn as_ptr(&self) -> *const T {
399         self.0.get() as _
400     }
401
402     /// Obtain a raw pointer to the first element of this user slice.
403     pub fn as_mut_ptr(&mut self) -> *mut T {
404         self.0.get() as _
405     }
406
407     /// Obtain the number of elements in this user slice.
408     pub fn len(&self) -> usize {
409         unsafe { (*self.0.get()).len() }
410     }
411
412     /// Copies the value from user memory and place it into `dest`. Afterwards,
413     /// `dest` will contain exactly `self.len()` elements.
414     ///
415     /// # Panics
416     /// This function panics if the destination doesn't have the same size as
417     /// the source. This can happen for dynamically-sized types such as slices.
418     pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
419         unsafe {
420             if let Some(missing) = self.len().checked_sub(dest.capacity()) {
421                 dest.reserve(missing)
422             }
423             dest.set_len(self.len());
424             self.copy_to_enclave(&mut dest[..]);
425         }
426     }
427
428     /// Copies the value from user memory into a vector in enclave memory.
429     pub fn to_enclave(&self) -> Vec<T> {
430         let mut ret = Vec::with_capacity(self.len());
431         self.copy_to_enclave_vec(&mut ret);
432         ret
433     }
434
435     /// Returns an iterator over the slice.
436     pub fn iter(&self) -> Iter<'_, T>
437         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
438     {
439         unsafe {
440             Iter((&*self.as_raw_ptr()).iter())
441         }
442     }
443
444     /// Returns an iterator that allows modifying each value.
445     pub fn iter_mut(&mut self) -> IterMut<'_, T>
446         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
447     {
448         unsafe {
449             IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
450         }
451     }
452 }
453
454 /// Immutable user slice iterator
455 ///
456 /// This struct is created by the `iter` method on `UserRef<[T]>`.
457 #[unstable(feature = "sgx_platform", issue = "56975")]
458 pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
459
460 #[unstable(feature = "sgx_platform", issue = "56975")]
461 impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
462     type Item = &'a UserRef<T>;
463
464     #[inline]
465     fn next(&mut self) -> Option<Self::Item> {
466         unsafe {
467             self.0.next().map(|e| UserRef::from_ptr(e))
468         }
469     }
470 }
471
472 /// Mutable user slice iterator
473 ///
474 /// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
475 #[unstable(feature = "sgx_platform", issue = "56975")]
476 pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
477
478 #[unstable(feature = "sgx_platform", issue = "56975")]
479 impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
480     type Item = &'a mut UserRef<T>;
481
482     #[inline]
483     fn next(&mut self) -> Option<Self::Item> {
484         unsafe {
485             self.0.next().map(|e| UserRef::from_mut_ptr(e))
486         }
487     }
488 }
489
490 #[unstable(feature = "sgx_platform", issue = "56975")]
491 impl<T: ?Sized> Deref for User<T> where T: UserSafe {
492     type Target = UserRef<T>;
493
494     fn deref(&self) -> &Self::Target {
495         unsafe { &*self.0.as_ptr() }
496     }
497 }
498
499 #[unstable(feature = "sgx_platform", issue = "56975")]
500 impl<T: ?Sized> DerefMut for User<T> where T: UserSafe {
501     fn deref_mut(&mut self) -> &mut Self::Target {
502         unsafe { &mut*self.0.as_ptr() }
503     }
504 }
505
506 #[unstable(feature = "sgx_platform", issue = "56975")]
507 impl<T: ?Sized> Drop for User<T> where T: UserSafe {
508     fn drop(&mut self) {
509         unsafe {
510             let ptr = (*self.0.as_ptr()).0.get();
511             super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of());
512         }
513     }
514 }
515
516 #[unstable(feature = "sgx_platform", issue = "56975")]
517 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
518
519 #[unstable(feature = "sgx_platform", issue = "56975")]
520 impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
521     type Output = UserRef<I::Output>;
522
523     #[inline]
524     fn index(&self, index: I) -> &UserRef<I::Output> {
525         unsafe {
526             UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
527         }
528     }
529 }
530
531 #[unstable(feature = "sgx_platform", issue = "56975")]
532 impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
533     #[inline]
534     fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
535         unsafe {
536             UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))
537         }
538     }
539 }
540
541 #[unstable(feature = "sgx_platform", issue = "56975")]
542 impl UserRef<super::raw::ByteBuffer> {
543     /// Copies the user memory range pointed to by the user `ByteBuffer` to
544     /// enclave memory.
545     ///
546     /// # Panics
547     /// This function panics if:
548     ///
549     /// * The pointer in the user `ByteBuffer` is null
550     /// * The pointed-to range in the user `ByteBuffer` is not in user memory
551     pub fn copy_user_buffer(&self) -> Vec<u8> {
552         unsafe {
553             let buf = self.to_enclave();
554             if buf.len > 0 {
555                 User::from_raw_parts(buf.data as _, buf.len).to_enclave()
556             } else {
557                 // Mustn't look at `data` or call `free` if `len` is `0`.
558                 Vec::with_capacity(0)
559             }
560         }
561     }
562 }