]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/alloc.rs
Auto merge of #56005 - GuillaumeGomez:speedup-doc-render, r=QuietMisdreavus
[rust.git] / src / libstd / sys / sgx / abi / usercalls / alloc.rs
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.
4 //
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.
10
11 #![allow(unused)]
12
13 use ptr;
14 use mem;
15 use cell::UnsafeCell;
16 use slice;
17 use ops::{Deref, DerefMut, Index, IndexMut, CoerceUnsized};
18 use slice::SliceIndex;
19
20 use fortanix_sgx_abi::*;
21 use super::super::mem::is_user_range;
22
23 /// A type that can be safely read from or written to userspace.
24 ///
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.
40 ///
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.
45 ///
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 {}
53
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] {}
60
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;
64
65     /// NB. This takes a size, not a length!
66     unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self;
67
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);
71         Self::check_ptr(ret);
72         ret
73     }
74
75     unsafe fn check_ptr(ptr: *const Self) {
76         let is_aligned = |p| -> bool {
77             0 == (p as usize) & (Self::align_of() - 1)
78         };
79
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());
83     }
84 }
85
86 unsafe impl<T: UserSafeSized> UserSafe for T {
87     unsafe fn align_of() -> usize {
88         mem::align_of::<T>()
89     }
90
91     unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self {
92         assert_eq!(size, mem::size_of::<T>());
93         ptr as _
94     }
95 }
96
97 unsafe impl<T: UserSafeSized> UserSafe for [T] {
98     unsafe fn align_of() -> usize {
99         mem::align_of::<T>()
100     }
101
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)
107     }
108 }
109
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
119 /// use.
120 pub struct User<T: UserSafe + ?Sized>(*mut UserRef<T>);
121
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 {
128         unsafe {
129             let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
130             User(T::from_raw_sized(ptr as _, size) as _)
131         }
132     }
133
134     pub fn new_from_enclave(val: &T) -> Self {
135         unsafe {
136             let ret = Self::new_uninit_bytes(mem::size_of_val(val));
137             ptr::copy(
138                 val as *const T as *const u8,
139                 ret.0 as *mut T as *mut u8,
140                 mem::size_of_val(val)
141             );
142             ret
143         }
144     }
145
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`.
148     ///
149     /// # Panics
150     /// This function panics if:
151     ///
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 {
156         T::check_ptr(ptr);
157         User(ptr as _)
158     }
159
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 {
163         let ret = self.0;
164         mem::forget(self);
165         ret as _
166     }
167 }
168
169 impl<T> User<T> where T: UserSafe {
170     pub fn uninitialized() -> Self {
171         Self::new_uninit_bytes(mem::size_of::<T>())
172     }
173 }
174
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>())
178     }
179
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`.
183     ///
184     /// # Panics
185     /// This function panics if:
186     ///
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 _)
192     }
193 }
194
195 impl<T: ?Sized> UserRef<T> where T: UserSafe {
196     /// Create a `&UserRef<[T]>` from a raw pointer.
197     ///
198     /// # Panics
199     /// This function panics if:
200     ///
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 {
205         T::check_ptr(ptr);
206         &*(ptr as *const Self)
207     }
208
209     /// Create a `&mut UserRef<[T]>` from a raw pointer.
210     ///
211     /// # Panics
212     /// This function panics if:
213     ///
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 {
218         T::check_ptr(ptr);
219         &mut*(ptr as *mut Self)
220     }
221
222     /// # Panics
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) {
226         unsafe {
227             assert_eq!(mem::size_of_val(val), mem::size_of_val( &*self.0.get() ));
228             ptr::copy(
229                 val as *const T as *const u8,
230                 self.0.get() as *mut T as *mut u8,
231                 mem::size_of_val(val)
232             );
233         }
234     }
235
236     /// # Panics
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) {
240         unsafe {
241             assert_eq!(mem::size_of_val(dest), mem::size_of_val( &*self.0.get() ));
242             ptr::copy(
243                 self.0.get() as *const T as *const u8,
244                 dest as *mut T as *mut u8,
245                 mem::size_of_val(dest)
246             );
247         }
248     }
249
250     pub fn as_raw_ptr(&self) -> *const T {
251         self as *const _ as _
252     }
253
254     pub fn as_raw_mut_ptr(&mut self) -> *mut T {
255         self as *mut _ as _
256     }
257 }
258
259 impl<T> UserRef<T> where T: UserSafe {
260     pub fn to_enclave(&self) -> T {
261         unsafe { ptr::read(self.0.get()) }
262     }
263 }
264
265 impl<T> UserRef<[T]> where [T]: UserSafe {
266     /// Create a `&UserRef<[T]>` from a raw thin pointer and a slice length.
267     ///
268     /// # Panics
269     /// This function panics if:
270     ///
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)
276     }
277
278     /// Create a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
279     ///
280     /// # Panics
281     /// This function panics if:
282     ///
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)
288     }
289
290     pub fn as_ptr(&self) -> *const T {
291         self.0.get() as _
292     }
293
294     pub fn as_mut_ptr(&mut self) -> *mut T {
295         self.0.get() as _
296     }
297
298     pub fn len(&self) -> usize {
299         unsafe { (*self.0.get()).len() }
300     }
301
302     pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
303         unsafe {
304             if let Some(missing) = self.len().checked_sub(dest.capacity()) {
305                 dest.reserve(missing)
306             }
307             dest.set_len(self.len());
308             self.copy_to_enclave(&mut dest[..]);
309         }
310     }
311
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);
315         ret
316     }
317
318     pub fn iter(&self) -> Iter<T>
319         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
320     {
321         unsafe {
322             Iter((&*self.as_raw_ptr()).iter())
323         }
324     }
325
326     pub fn iter_mut(&mut self) -> IterMut<T>
327         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
328     {
329         unsafe {
330             IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
331         }
332     }
333 }
334
335 pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
336
337 impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
338     type Item = &'a UserRef<T>;
339
340     #[inline]
341     fn next(&mut self) -> Option<Self::Item> {
342         unsafe {
343             self.0.next().map(|e| UserRef::from_ptr(e))
344         }
345     }
346 }
347
348 pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
349
350 impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
351     type Item = &'a mut UserRef<T>;
352
353     #[inline]
354     fn next(&mut self) -> Option<Self::Item> {
355         unsafe {
356             self.0.next().map(|e| UserRef::from_mut_ptr(e))
357         }
358     }
359 }
360
361 impl<T: ?Sized> Deref for User<T> where T: UserSafe {
362     type Target = UserRef<T>;
363
364     fn deref(&self) -> &Self::Target {
365         unsafe { &*self.0 }
366     }
367 }
368
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 }
372     }
373 }
374
375 impl<T: ?Sized> Drop for User<T> where T: UserSafe {
376     fn drop(&mut self) {
377         unsafe {
378             let ptr = (*self.0).0.get();
379             super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of());
380         }
381     }
382 }
383
384 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
385
386 impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
387     type Output = UserRef<I::Output>;
388
389     #[inline]
390     fn index(&self, index: I) -> &UserRef<I::Output> {
391         unsafe {
392             UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
393         }
394     }
395 }
396
397 impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe {
398     #[inline]
399     fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
400         unsafe {
401             UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))
402         }
403     }
404 }