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 does not fit in the address space.
89 /// * the pointed-to range is not in user memory.
90 unsafe fn from_raw_sized(ptr
: *mut u8, size
: usize) -> NonNull
<Self> {
91 assert
!(ptr
.wrapping_add(size
) >= ptr
);
92 let ret
= Self::from_raw_sized_unchecked(ptr
, size
);
94 NonNull
::new_unchecked(ret
as _
)
97 /// Checks if a pointer may point to `Self` in user memory.
101 /// The caller must ensure the memory range points to the correct type and
102 /// length (if this is a slice).
106 /// This function panics if:
108 /// * the pointer is not aligned.
109 /// * the pointer is null.
110 /// * the pointed-to range is not in user memory.
111 unsafe fn check_ptr(ptr
: *const Self) {
112 let is_aligned
= |p
| -> bool
{
113 0 == (p
as usize) & (Self::align_of() - 1)
116 assert
!(is_aligned(ptr
as *const u8));
117 assert
!(is_user_range(ptr
as _
, mem
::size_of_val(&*ptr
)));
118 assert
!(!ptr
.is_null());
122 #[unstable(feature = "sgx_platform", issue = "56975")]
123 unsafe impl<T
: UserSafeSized
> UserSafe
for T
{
124 fn align_of() -> usize {
128 unsafe fn from_raw_sized_unchecked(ptr
: *mut u8, size
: usize) -> *mut Self {
129 assert_eq
!(size
, mem
::size_of
::<T
>());
134 #[unstable(feature = "sgx_platform", issue = "56975")]
135 unsafe impl<T
: UserSafeSized
> UserSafe
for [T
] {
136 fn align_of() -> usize {
140 unsafe fn from_raw_sized_unchecked(ptr
: *mut u8, size
: usize) -> *mut Self {
141 let elem_size
= mem
::size_of
::<T
>();
142 assert_eq
!(size
% elem_size
, 0);
143 let len
= size
/ elem_size
;
144 slice
::from_raw_parts_mut(ptr
as _
, len
)
148 /// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
149 /// to `&T` in enclave memory. Access to the memory is only allowed by copying
150 /// to avoid TOCTTOU issues. After copying, code should make sure to completely
151 /// check the value before use.
153 /// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
154 /// regular mutable references, these are not exclusive. Userspace may always
155 /// write to the backing memory at any time, so it can't be assumed that there
156 /// the pointed-to memory is uniquely borrowed. The two different refence types
157 /// are used solely to indicate intent: a mutable reference is for writing to
158 /// user memory, an immutable reference for reading from user memory.
159 #[unstable(feature = "sgx_platform", issue = "56975")]
160 pub struct UserRef
<T
: ?Sized
>(UnsafeCell
<T
>);
161 /// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
162 /// enclave memory. Access to the memory is only allowed by copying to avoid
163 /// TOCTTOU issues. The user memory will be freed when the value is dropped.
164 /// After copying, code should make sure to completely check the value before
166 #[unstable(feature = "sgx_platform", issue = "56975")]
167 pub struct User
<T
: UserSafe
+ ?Sized
>(NonNull
<UserRef
<T
>>);
169 trait NewUserRef
<T
: ?Sized
> {
170 unsafe fn new_userref(v
: T
) -> Self;
173 impl<T
: ?Sized
> NewUserRef
<*mut T
> for NonNull
<UserRef
<T
>> {
174 unsafe fn new_userref(v
: *mut T
) -> Self {
175 NonNull
::new_unchecked(v
as _
)
179 impl<T
: ?Sized
> NewUserRef
<NonNull
<T
>> for NonNull
<UserRef
<T
>> {
180 unsafe fn new_userref(v
: NonNull
<T
>) -> Self {
181 NonNull
::new_userref(v
.as_ptr())
185 #[unstable(feature = "sgx_platform", issue = "56975")]
186 impl<T
: ?Sized
> User
<T
> where T
: UserSafe
{
187 // This function returns memory that is practically uninitialized, but is
188 // not considered "unspecified" or "undefined" for purposes of an
189 // optimizing compiler. This is achieved by returning a pointer from
190 // from outside as obtained by `super::alloc`.
191 fn new_uninit_bytes(size
: usize) -> Self {
193 // Mustn't call alloc with size 0.
194 let ptr
= if size
> 0 {
195 rtunwrap
!(Ok
, super::alloc(size
, T
::align_of())) as _
197 T
::align_of() as _
// dangling pointer ok for size 0
199 if let Ok(v
) = crate::panic
::catch_unwind(|| T
::from_raw_sized(ptr
, size
)) {
200 User(NonNull
::new_userref(v
))
202 rtabort
!("Got invalid pointer from alloc() usercall")
207 /// Copies `val` into freshly allocated space in user memory.
208 pub fn new_from_enclave(val
: &T
) -> Self {
210 let ret
= Self::new_uninit_bytes(mem
::size_of_val(val
));
212 val
as *const T
as *const u8,
213 ret
.0.as_ptr() as *mut u8,
214 mem
::size_of_val(val
)
220 /// Creates an owned `User<T>` from a raw pointer.
223 /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
224 /// usercall and the alignment of `T`, and is uniquely owned.
227 /// This function panics if:
229 /// * The pointer is not aligned
230 /// * The pointer is null
231 /// * The pointed-to range is not in user memory
232 pub unsafe fn from_raw(ptr
: *mut T
) -> Self {
234 User(NonNull
::new_userref(ptr
))
237 /// Converts this value into a raw pointer. The value will no longer be
238 /// automatically freed.
239 pub fn into_raw(self) -> *mut T
{
246 #[unstable(feature = "sgx_platform", issue = "56975")]
247 impl<T
> User
<T
> where T
: UserSafe
{
248 /// Allocate space for `T` in user memory.
249 pub fn uninitialized() -> Self {
250 Self::new_uninit_bytes(mem
::size_of
::<T
>())
254 #[unstable(feature = "sgx_platform", issue = "56975")]
255 impl<T
> User
<[T
]> where [T
]: UserSafe
{
256 /// Allocate space for a `[T]` of `n` elements in user memory.
257 pub fn uninitialized(n
: usize) -> Self {
258 Self::new_uninit_bytes(n
* mem
::size_of
::<T
>())
261 /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length.
264 /// The caller must ensure `ptr` points to `len` elements of `T`, is
265 /// freeable with the `free` usercall and the alignment of `T`, and is
269 /// This function panics if:
271 /// * The pointer is not aligned
272 /// * The pointer is null
273 /// * The pointed-to range does not fit in the address space
274 /// * The pointed-to range is not in user memory
275 pub unsafe fn from_raw_parts(ptr
: *mut T
, len
: usize) -> Self {
276 User(NonNull
::new_userref(<[T
]>::from_raw_sized(ptr
as _
, len
* mem
::size_of
::<T
>())))
280 #[unstable(feature = "sgx_platform", issue = "56975")]
281 impl<T
: ?Sized
> UserRef
<T
> where T
: UserSafe
{
282 /// Creates a `&UserRef<[T]>` from a raw pointer.
285 /// The caller must ensure `ptr` points to `T`.
288 /// This function panics if:
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_ptr
<'a
>(ptr
: *const T
) -> &'a
Self {
295 &*(ptr
as *const Self)
298 /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct
299 /// documentation for the nuances regarding a `&mut UserRef<T>`.
302 /// The caller must ensure `ptr` points to `T`.
305 /// This function panics if:
307 /// * The pointer is not aligned
308 /// * The pointer is null
309 /// * The pointed-to range is not in user memory
310 pub unsafe fn from_mut_ptr
<'a
>(ptr
: *mut T
) -> &'a
mut Self {
312 &mut*(ptr
as *mut Self)
315 /// Copies `val` into user memory.
318 /// This function panics if the destination doesn't have the same size as
319 /// the source. This can happen for dynamically-sized types such as slices.
320 pub fn copy_from_enclave(&mut self, val
: &T
) {
322 assert_eq
!(mem
::size_of_val(val
), mem
::size_of_val( &*self.0.get() ));
324 val
as *const T
as *const u8,
325 self.0.get() as *mut T
as *mut u8,
326 mem
::size_of_val(val
)
331 /// Copies the value from user memory and place it into `dest`.
334 /// This function panics if the destination doesn't have the same size as
335 /// the source. This can happen for dynamically-sized types such as slices.
336 pub fn copy_to_enclave(&self, dest
: &mut T
) {
338 assert_eq
!(mem
::size_of_val(dest
), mem
::size_of_val( &*self.0.get() ));
340 self.0.get() as *const T
as *const u8,
341 dest
as *mut T
as *mut u8,
342 mem
::size_of_val(dest
)
347 /// Obtain a raw pointer from this reference.
348 pub fn as_raw_ptr(&self) -> *const T
{
349 self as *const _
as _
352 /// Obtain a raw pointer from this reference.
353 pub fn as_raw_mut_ptr(&mut self) -> *mut T
{
358 #[unstable(feature = "sgx_platform", issue = "56975")]
359 impl<T
> UserRef
<T
> where T
: UserSafe
{
360 /// Copies the value from user memory into enclave memory.
361 pub fn to_enclave(&self) -> T
{
362 unsafe { ptr::read(self.0.get()) }
366 #[unstable(feature = "sgx_platform", issue = "56975")]
367 impl<T
> UserRef
<[T
]> where [T
]: UserSafe
{
368 /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length.
371 /// The caller must ensure `ptr` points to `n` elements of `T`.
374 /// This function panics if:
376 /// * The pointer is not aligned
377 /// * The pointer is null
378 /// * The pointed-to range does not fit in the address space
379 /// * The pointed-to range is not in user memory
380 pub unsafe fn from_raw_parts
<'a
>(ptr
: *const T
, len
: usize) -> &'a
Self {
381 &*(<[T
]>::from_raw_sized(ptr
as _
, len
* mem
::size_of
::<T
>()).as_ptr() as *const Self)
384 /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
385 /// See the struct documentation for the nuances regarding a
386 /// `&mut UserRef<T>`.
389 /// The caller must ensure `ptr` points to `n` elements of `T`.
392 /// This function panics if:
394 /// * The pointer is not aligned
395 /// * The pointer is null
396 /// * The pointed-to range does not fit in the address space
397 /// * The pointed-to range is not in user memory
398 pub unsafe fn from_raw_parts_mut
<'a
>(ptr
: *mut T
, len
: usize) -> &'a
mut Self {
399 &mut*(<[T
]>::from_raw_sized(ptr
as _
, len
* mem
::size_of
::<T
>()).as_ptr() as *mut Self)
402 /// Obtain a raw pointer to the first element of this user slice.
403 pub fn as_ptr(&self) -> *const T
{
407 /// Obtain a raw pointer to the first element of this user slice.
408 pub fn as_mut_ptr(&mut self) -> *mut T
{
412 /// Obtain the number of elements in this user slice.
413 pub fn len(&self) -> usize {
414 unsafe { (*self.0.get()).len() }
417 /// Copies the value from user memory and place it into `dest`. Afterwards,
418 /// `dest` will contain exactly `self.len()` elements.
421 /// This function panics if the destination doesn't have the same size as
422 /// the source. This can happen for dynamically-sized types such as slices.
423 pub fn copy_to_enclave_vec(&self, dest
: &mut Vec
<T
>) {
425 if let Some(missing
) = self.len().checked_sub(dest
.capacity()) {
426 dest
.reserve(missing
)
428 dest
.set_len(self.len());
429 self.copy_to_enclave(&mut dest
[..]);
433 /// Copies the value from user memory into a vector in enclave memory.
434 pub fn to_enclave(&self) -> Vec
<T
> {
435 let mut ret
= Vec
::with_capacity(self.len());
436 self.copy_to_enclave_vec(&mut ret
);
440 /// Returns an iterator over the slice.
441 pub fn iter(&self) -> Iter
<'_
, T
>
442 where T
: UserSafe
// FIXME: should be implied by [T]: UserSafe?
445 Iter((&*self.as_raw_ptr()).iter())
449 /// Returns an iterator that allows modifying each value.
450 pub fn iter_mut(&mut self) -> IterMut
<'_
, T
>
451 where T
: UserSafe
// FIXME: should be implied by [T]: UserSafe?
454 IterMut((&mut*self.as_raw_mut_ptr()).iter_mut())
459 /// Immutable user slice iterator
461 /// This struct is created by the `iter` method on `UserRef<[T]>`.
462 #[unstable(feature = "sgx_platform", issue = "56975")]
463 pub struct Iter
<'a
, T
: 'a
+ UserSafe
>(slice
::Iter
<'a
, T
>);
465 #[unstable(feature = "sgx_platform", issue = "56975")]
466 impl<'a
, T
: UserSafe
> Iterator
for Iter
<'a
, T
> {
467 type Item
= &'a UserRef
<T
>;
470 fn next(&mut self) -> Option
<Self::Item
> {
472 self.0.next().map(|e
| UserRef
::from_ptr(e
))
477 /// Mutable user slice iterator
479 /// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
480 #[unstable(feature = "sgx_platform", issue = "56975")]
481 pub struct IterMut
<'a
, T
: 'a
+ UserSafe
>(slice
::IterMut
<'a
, T
>);
483 #[unstable(feature = "sgx_platform", issue = "56975")]
484 impl<'a
, T
: UserSafe
> Iterator
for IterMut
<'a
, T
> {
485 type Item
= &'a
mut UserRef
<T
>;
488 fn next(&mut self) -> Option
<Self::Item
> {
490 self.0.next().map(|e
| UserRef
::from_mut_ptr(e
))
495 #[unstable(feature = "sgx_platform", issue = "56975")]
496 impl<T
: ?Sized
> Deref
for User
<T
> where T
: UserSafe
{
497 type Target
= UserRef
<T
>;
499 fn deref(&self) -> &Self::Target
{
500 unsafe { &*self.0.as_ptr() }
504 #[unstable(feature = "sgx_platform", issue = "56975")]
505 impl<T
: ?Sized
> DerefMut
for User
<T
> where T
: UserSafe
{
506 fn deref_mut(&mut self) -> &mut Self::Target
{
507 unsafe { &mut*self.0.as_ptr() }
511 #[unstable(feature = "sgx_platform", issue = "56975")]
512 impl<T
: ?Sized
> Drop
for User
<T
> where T
: UserSafe
{
515 let ptr
= (*self.0.as_ptr()).0.get();
516 super::free(ptr
as _
, mem
::size_of_val(&mut*ptr
), T
::align_of());
521 #[unstable(feature = "sgx_platform", issue = "56975")]
522 impl<T
: CoerceUnsized
<U
>, U
> CoerceUnsized
<UserRef
<U
>> for UserRef
<T
> {}
524 #[unstable(feature = "sgx_platform", issue = "56975")]
525 impl<T
, I
> Index
<I
> for UserRef
<[T
]>
528 I
: SliceIndex
<[T
], Output
: UserSafe
>,
530 type Output
= UserRef
<I
::Output
>;
533 fn index(&self, index
: I
) -> &UserRef
<I
::Output
> {
535 if let Some(slice
) = index
.get(&*self.as_raw_ptr()) {
536 UserRef
::from_ptr(slice
)
538 rtabort
!("index out of range for user slice");
544 #[unstable(feature = "sgx_platform", issue = "56975")]
545 impl<T
, I
> IndexMut
<I
> for UserRef
<[T
]>
548 I
: SliceIndex
<[T
], Output
: UserSafe
>,
551 fn index_mut(&mut self, index
: I
) -> &mut UserRef
<I
::Output
> {
553 if let Some(slice
) = index
.get_mut(&mut*self.as_raw_mut_ptr()) {
554 UserRef
::from_mut_ptr(slice
)
556 rtabort
!("index out of range for user slice");
562 #[unstable(feature = "sgx_platform", issue = "56975")]
563 impl UserRef
<super::raw
::ByteBuffer
> {
564 /// Copies the user memory range pointed to by the user `ByteBuffer` to
568 /// This function panics if, in the user `ByteBuffer`:
570 /// * The pointer is null
571 /// * The pointed-to range does not fit in the address space
572 /// * The pointed-to range is not in user memory
573 pub fn copy_user_buffer(&self) -> Vec
<u8> {
575 let buf
= self.to_enclave();
577 User
::from_raw_parts(buf
.data
as _
, buf
.len
).to_enclave()
579 // Mustn't look at `data` or call `free` if `len` is `0`.
580 Vec
::with_capacity(0)