]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/alloc.rs
8d0013a235ac774bbdfcb8f94564b04b842a1eb8
[rust.git] / src / libstd / sys / sgx / abi / usercalls / alloc.rs
1 #![allow(unused)]
2
3 use ptr::{self, NonNull};
4 use mem;
5 use cell::UnsafeCell;
6 use slice;
7 use ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
8 use 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     /// NB. This takes a size, not a length!
67     ///
68     /// # Safety
69     /// The caller must ensure the memory range is in user memory, is the
70     /// correct size and is correctly aligned and points to the right type.
71     unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self;
72
73     /// Construct a pointer to `Self` given a memory range.
74     ///
75     /// NB. This takes a size, not a length!
76     ///
77     /// # Safety
78     /// The caller must ensure the memory range points to the correct type.
79     ///
80     /// # Panics
81     /// This function panics if:
82     ///
83     /// * The pointer is not aligned
84     /// * The pointer is null
85     /// * The pointed-to range is not in user memory
86     unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull<Self> {
87         let ret = Self::from_raw_sized_unchecked(ptr, size);
88         Self::check_ptr(ret);
89         NonNull::new_unchecked(ret as _)
90     }
91
92     /// Check if a pointer may point to Self in user memory.
93     ///
94     /// # Safety
95     /// The caller must ensure the memory range points to the correct type and
96     /// length (if this is a slice).
97     ///
98     /// # Panics
99     /// This function panics if:
100     ///
101     /// * The pointer is not aligned
102     /// * The pointer is null
103     /// * The pointed-to range is not in user memory
104     unsafe fn check_ptr(ptr: *const Self) {
105         let is_aligned = |p| -> bool {
106             0 == (p as usize) & (Self::align_of() - 1)
107         };
108
109         assert!(is_aligned(ptr as *const u8));
110         assert!(is_user_range(ptr as _, mem::size_of_val(&*ptr)));
111         assert!(!ptr.is_null());
112     }
113 }
114
115 #[unstable(feature = "sgx_platform", issue = "56975")]
116 unsafe impl<T: UserSafeSized> UserSafe for T {
117     fn align_of() -> usize {
118         mem::align_of::<T>()
119     }
120
121     unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
122         assert_eq!(size, mem::size_of::<T>());
123         ptr as _
124     }
125 }
126
127 #[unstable(feature = "sgx_platform", issue = "56975")]
128 unsafe impl<T: UserSafeSized> UserSafe for [T] {
129     fn align_of() -> usize {
130         mem::align_of::<T>()
131     }
132
133     unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
134         let elem_size = mem::size_of::<T>();
135         assert_eq!(size % elem_size, 0);
136         let len = size / elem_size;
137         slice::from_raw_parts_mut(ptr as _, len)
138     }
139 }
140
141 /// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
142 /// to `&T` in enclave memory. Access to the memory is only allowed by copying
143 /// to avoid TOCTTOU issues. After copying, code should make sure to completely
144 /// check the value before use.
145 ///
146 /// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
147 /// regular mutable references, these are not exclusive. Userspace may always
148 /// write to the backing memory at any time, so it can't be assumed that there
149 /// the pointed-to memory is uniquely borrowed. The two different refence types
150 /// are used solely to indicate intent: a mutable reference is for writing to
151 /// user memory, an immutable reference for reading from user memory.
152 #[unstable(feature = "sgx_platform", issue = "56975")]
153 pub struct UserRef<T: ?Sized>(UnsafeCell<T>);
154 /// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
155 /// enclave memory. Access to the memory is only allowed by copying to avoid
156 /// TOCTTOU issues. The user memory will be freed when the value is dropped.
157 /// After copying, code should make sure to completely check the value before
158 /// use.
159 #[unstable(feature = "sgx_platform", issue = "56975")]
160 pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>);
161
162 trait NewUserRef<T: ?Sized> {
163     unsafe fn new_userref(v: T) -> Self;
164 }
165
166 impl<T: ?Sized> NewUserRef<*mut T> for NonNull<UserRef<T>> {
167     unsafe fn new_userref(v: *mut T) -> Self {
168         NonNull::new_unchecked(v as _)
169     }
170 }
171
172 impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
173     unsafe fn new_userref(v: NonNull<T>) -> Self {
174         NonNull::new_userref(v.as_ptr())
175     }
176 }
177
178 #[unstable(feature = "sgx_platform", issue = "56975")]
179 impl<T: ?Sized> User<T> where T: UserSafe {
180     // This function returns memory that is practically uninitialized, but is
181     // not considered "unspecified" or "undefined" for purposes of an
182     // optimizing compiler. This is achieved by returning a pointer from
183     // from outside as obtained by `super::alloc`.
184     fn new_uninit_bytes(size: usize) -> Self {
185         unsafe {
186             let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
187             User(NonNull::new_userref(T::from_raw_sized(ptr as _, size)))
188         }
189     }
190
191     /// Copy `val` into freshly allocated space in user memory.
192     pub fn new_from_enclave(val: &T) -> Self {
193         unsafe {
194             let ret = Self::new_uninit_bytes(mem::size_of_val(val));
195             ptr::copy(
196                 val as *const T as *const u8,
197                 ret.0.as_ptr() as *mut u8,
198                 mem::size_of_val(val)
199             );
200             ret
201         }
202     }
203
204     /// Create an owned `User<T>` from a raw pointer.
205     ///
206     /// # Safety
207     /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
208     /// usercall and the alignment of `T`, and is uniquely owned.
209     ///
210     /// # Panics
211     /// This function panics if:
212     ///
213     /// * The pointer is not aligned
214     /// * The pointer is null
215     /// * The pointed-to range is not in user memory
216     pub unsafe fn from_raw(ptr: *mut T) -> Self {
217         T::check_ptr(ptr);
218         User(NonNull::new_userref(ptr))
219     }
220
221     /// Convert this value into a raw pointer. The value will no longer be
222     /// automatically freed.
223     pub fn into_raw(self) -> *mut T {
224         let ret = self.0;
225         mem::forget(self);
226         ret.as_ptr() as _
227     }
228 }
229
230 #[unstable(feature = "sgx_platform", issue = "56975")]
231 impl<T> User<T> where T: UserSafe {
232     /// Allocate space for `T` in user memory.
233     pub fn uninitialized() -> Self {
234         Self::new_uninit_bytes(mem::size_of::<T>())
235     }
236 }
237
238 #[unstable(feature = "sgx_platform", issue = "56975")]
239 impl<T> User<[T]> where [T]: UserSafe {
240     /// Allocate space for a `[T]` of `n` elements in user memory.
241     pub fn uninitialized(n: usize) -> Self {
242         Self::new_uninit_bytes(n * mem::size_of::<T>())
243     }
244
245     /// Create an owned `User<[T]>` from a raw thin pointer and a slice length.
246     ///
247     /// # Safety
248     /// The caller must ensure `ptr` points to `len` elements of `T`, is
249     /// freeable with the `free` usercall and the alignment of `T`, and is
250     /// uniquely owned.
251     ///
252     /// # Panics
253     /// This function panics if:
254     ///
255     /// * The pointer is not aligned
256     /// * The pointer is null
257     /// * The pointed-to range is not in user memory
258     pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
259         User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())))
260     }
261 }
262
263 #[unstable(feature = "sgx_platform", issue = "56975")]
264 impl<T: ?Sized> UserRef<T> where T: UserSafe {
265     /// Create a `&UserRef<[T]>` from a raw pointer.
266     ///
267     /// # Safety
268     /// The caller must ensure `ptr` points to `T`.
269     ///
270     /// # Panics
271     /// This function panics if:
272     ///
273     /// * The pointer is not aligned
274     /// * The pointer is null
275     /// * The pointed-to range is not in user memory
276     pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
277         T::check_ptr(ptr);
278         &*(ptr as *const Self)
279     }
280
281     /// Create a `&mut UserRef<[T]>` from a raw pointer. See the struct
282     /// documentation for the nuances regarding a `&mut UserRef<T>`.
283     ///
284     /// # Safety
285     /// The caller must ensure `ptr` points to `T`.
286     ///
287     /// # Panics
288     /// This function panics if:
289     ///
290     /// * The pointer is not aligned
291     /// * The pointer is null
292     /// * The pointed-to range is not in user memory
293     pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
294         T::check_ptr(ptr);
295         &mut*(ptr as *mut Self)
296     }
297
298     /// Copy `val` into user memory.
299     ///
300     /// # Panics
301     /// This function panics if the destination doesn't have the same size as
302     /// the source. This can happen for dynamically-sized types such as slices.
303     pub fn copy_from_enclave(&mut self, val: &T) {
304         unsafe {
305             assert_eq!(mem::size_of_val(val), mem::size_of_val( &*self.0.get() ));
306             ptr::copy(
307                 val as *const T as *const u8,
308                 self.0.get() as *mut T as *mut u8,
309                 mem::size_of_val(val)
310             );
311         }
312     }
313
314     /// Copy the value from user memory and place it into `dest`.
315     ///
316     /// # Panics
317     /// This function panics if the destination doesn't have the same size as
318     /// the source. This can happen for dynamically-sized types such as slices.
319     pub fn copy_to_enclave(&self, dest: &mut T) {
320         unsafe {
321             assert_eq!(mem::size_of_val(dest), mem::size_of_val( &*self.0.get() ));
322             ptr::copy(
323                 self.0.get() as *const T as *const u8,
324                 dest as *mut T as *mut u8,
325                 mem::size_of_val(dest)
326             );
327         }
328     }
329
330     /// Obtain a raw pointer from this reference.
331     pub fn as_raw_ptr(&self) -> *const T {
332         self as *const _ as _
333     }
334
335     /// Obtain a raw pointer from this reference.
336     pub fn as_raw_mut_ptr(&mut self) -> *mut T {
337         self as *mut _ as _
338     }
339 }
340
341 #[unstable(feature = "sgx_platform", issue = "56975")]
342 impl<T> UserRef<T> where T: UserSafe {
343     /// Copy the value from user memory into enclave memory.
344     pub fn to_enclave(&self) -> T {
345         unsafe { ptr::read(self.0.get()) }
346     }
347 }
348
349 #[unstable(feature = "sgx_platform", issue = "56975")]
350 impl<T> UserRef<[T]> where [T]: UserSafe {
351     /// Create a `&UserRef<[T]>` from a raw thin pointer and a slice length.
352     ///
353     /// # Safety
354     /// The caller must ensure `ptr` points to `n` elements of `T`.
355     ///
356     /// # Panics
357     /// This function panics if:
358     ///
359     /// * The pointer is not aligned
360     /// * The pointer is null
361     /// * The pointed-to range is not in user memory
362     pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
363         &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
364     }
365
366     /// Create a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
367     /// See the struct documentation for the nuances regarding a
368     /// `&mut UserRef<T>`.
369     ///
370     /// # Safety
371     /// The caller must ensure `ptr` points to `n` elements of `T`.
372     ///
373     /// # Panics
374     /// This function panics if:
375     ///
376     /// * The pointer is not aligned
377     /// * The pointer is null
378     /// * The pointed-to range is not in user memory
379     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
380         &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
381     }
382
383     /// Obtain a raw pointer to the first element of this user slice.
384     pub fn as_ptr(&self) -> *const T {
385         self.0.get() as _
386     }
387
388     /// Obtain a raw pointer to the first element of this user slice.
389     pub fn as_mut_ptr(&mut self) -> *mut T {
390         self.0.get() as _
391     }
392
393     /// Obtain the number of elements in this user slice.
394     pub fn len(&self) -> usize {
395         unsafe { (*self.0.get()).len() }
396     }
397
398     /// Copy the value from user memory and place it into `dest`. Afterwards,
399     /// `dest` will contain exactly `self.len()` elements.
400     ///
401     /// # Panics
402     /// This function panics if the destination doesn't have the same size as
403     /// the source. This can happen for dynamically-sized types such as slices.
404     pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
405         unsafe {
406             if let Some(missing) = self.len().checked_sub(dest.capacity()) {
407                 dest.reserve(missing)
408             }
409             dest.set_len(self.len());
410             self.copy_to_enclave(&mut dest[..]);
411         }
412     }
413
414     /// Copy the value from user memory into a vector in enclave memory.
415     pub fn to_enclave(&self) -> Vec<T> {
416         let mut ret = Vec::with_capacity(self.len());
417         self.copy_to_enclave_vec(&mut ret);
418         ret
419     }
420
421     /// Returns an iterator over the slice.
422     pub fn iter(&self) -> Iter<T>
423         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
424     {
425         unsafe {
426             Iter((&*self.as_raw_ptr()).iter())
427         }
428     }
429
430     /// Returns an iterator that allows modifying each value.
431     pub fn iter_mut(&mut self) -> IterMut<T>
432         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
433     {
434         unsafe {
435             IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
436         }
437     }
438 }
439
440 /// Immutable user slice iterator
441 ///
442 /// This struct is created by the `iter` method on `UserRef<[T]>`.
443 #[unstable(feature = "sgx_platform", issue = "56975")]
444 pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
445
446 #[unstable(feature = "sgx_platform", issue = "56975")]
447 impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
448     type Item = &'a UserRef<T>;
449
450     #[inline]
451     fn next(&mut self) -> Option<Self::Item> {
452         unsafe {
453             self.0.next().map(|e| UserRef::from_ptr(e))
454         }
455     }
456 }
457
458 /// Mutable user slice iterator
459 ///
460 /// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
461 #[unstable(feature = "sgx_platform", issue = "56975")]
462 pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
463
464 #[unstable(feature = "sgx_platform", issue = "56975")]
465 impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
466     type Item = &'a mut UserRef<T>;
467
468     #[inline]
469     fn next(&mut self) -> Option<Self::Item> {
470         unsafe {
471             self.0.next().map(|e| UserRef::from_mut_ptr(e))
472         }
473     }
474 }
475
476 #[unstable(feature = "sgx_platform", issue = "56975")]
477 impl<T: ?Sized> Deref for User<T> where T: UserSafe {
478     type Target = UserRef<T>;
479
480     fn deref(&self) -> &Self::Target {
481         unsafe { &*self.0.as_ptr() }
482     }
483 }
484
485 #[unstable(feature = "sgx_platform", issue = "56975")]
486 impl<T: ?Sized> DerefMut for User<T> where T: UserSafe {
487     fn deref_mut(&mut self) -> &mut Self::Target {
488         unsafe { &mut*self.0.as_ptr() }
489     }
490 }
491
492 #[unstable(feature = "sgx_platform", issue = "56975")]
493 impl<T: ?Sized> Drop for User<T> where T: UserSafe {
494     fn drop(&mut self) {
495         unsafe {
496             let ptr = (*self.0.as_ptr()).0.get();
497             super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of());
498         }
499     }
500 }
501
502 #[unstable(feature = "sgx_platform", issue = "56975")]
503 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
504
505 #[unstable(feature = "sgx_platform", issue = "56975")]
506 impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
507     type Output = UserRef<I::Output>;
508
509     #[inline]
510     fn index(&self, index: I) -> &UserRef<I::Output> {
511         unsafe {
512             UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
513         }
514     }
515 }
516
517 #[unstable(feature = "sgx_platform", issue = "56975")]
518 impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
519     #[inline]
520     fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
521         unsafe {
522             UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))
523         }
524     }
525 }
526
527 #[unstable(feature = "sgx_platform", issue = "56975")]
528 impl UserRef<super::raw::ByteBuffer> {
529     /// Copy the user memory range pointed to by the user `ByteBuffer` to
530     /// enclave memory.
531     ///
532     /// # Panics
533     /// This function panics if:
534     ///
535     /// * The pointer in the user `ByteBuffer` is null
536     /// * The pointed-to range in the user `ByteBuffer` is not in user memory
537     pub fn copy_user_buffer(&self) -> Vec<u8> {
538         unsafe {
539             let buf = self.to_enclave();
540             User::from_raw_parts(buf.data as _, buf.len).to_enclave()
541         }
542     }
543 }