]>
Commit | Line | Data |
---|---|---|
0731742a XL |
1 | #![allow(unused)] |
2 | ||
532ac7d7 | 3 | use crate::cell::UnsafeCell; |
60c5eb7d XL |
4 | use crate::mem; |
5 | use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; | |
6 | use crate::ptr::{self, NonNull}; | |
532ac7d7 | 7 | use crate::slice; |
532ac7d7 | 8 | use crate::slice::SliceIndex; |
0731742a | 9 | |
0731742a | 10 | use super::super::mem::is_user_range; |
60c5eb7d | 11 | use fortanix_sgx_abi::*; |
0731742a XL |
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 | /// | |
9fa01778 | 66 | /// N.B., this takes a size, not a length! |
0731742a XL |
67 | /// |
68 | /// # Safety | |
9fa01778 | 69 | /// |
0731742a XL |
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 | /// | |
9fa01778 | 76 | /// N.B., this takes a size, not a length! |
0731742a XL |
77 | /// |
78 | /// # Safety | |
9fa01778 | 79 | /// |
0731742a XL |
80 | /// The caller must ensure the memory range points to the correct type. |
81 | /// | |
82 | /// # Panics | |
9fa01778 | 83 | /// |
0731742a XL |
84 | /// This function panics if: |
85 | /// | |
9fa01778 XL |
86 | /// * the pointer is not aligned. |
87 | /// * the pointer is null. | |
48663c56 | 88 | /// * the pointed-to range does not fit in the address space. |
9fa01778 | 89 | /// * the pointed-to range is not in user memory. |
0731742a | 90 | unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull<Self> { |
48663c56 | 91 | assert!(ptr.wrapping_add(size) >= ptr); |
0731742a XL |
92 | let ret = Self::from_raw_sized_unchecked(ptr, size); |
93 | Self::check_ptr(ret); | |
94 | NonNull::new_unchecked(ret as _) | |
95 | } | |
96 | ||
9fa01778 | 97 | /// Checks if a pointer may point to `Self` in user memory. |
0731742a XL |
98 | /// |
99 | /// # Safety | |
9fa01778 | 100 | /// |
0731742a XL |
101 | /// The caller must ensure the memory range points to the correct type and |
102 | /// length (if this is a slice). | |
103 | /// | |
104 | /// # Panics | |
9fa01778 | 105 | /// |
0731742a XL |
106 | /// This function panics if: |
107 | /// | |
9fa01778 XL |
108 | /// * the pointer is not aligned. |
109 | /// * the pointer is null. | |
110 | /// * the pointed-to range is not in user memory. | |
0731742a | 111 | unsafe fn check_ptr(ptr: *const Self) { |
60c5eb7d | 112 | let is_aligned = |p| -> bool { 0 == (p as usize) & (Self::align_of() - 1) }; |
0731742a XL |
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")] | |
60c5eb7d XL |
184 | impl<T: ?Sized> User<T> |
185 | where | |
186 | T: UserSafe, | |
187 | { | |
0731742a XL |
188 | // This function returns memory that is practically uninitialized, but is |
189 | // not considered "unspecified" or "undefined" for purposes of an | |
190 | // optimizing compiler. This is achieved by returning a pointer from | |
191 | // from outside as obtained by `super::alloc`. | |
192 | fn new_uninit_bytes(size: usize) -> Self { | |
193 | unsafe { | |
532ac7d7 XL |
194 | // Mustn't call alloc with size 0. |
195 | let ptr = if size > 0 { | |
196 | rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ | |
197 | } else { | |
198 | T::align_of() as _ // dangling pointer ok for size 0 | |
199 | }; | |
200 | if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) { | |
201 | User(NonNull::new_userref(v)) | |
202 | } else { | |
203 | rtabort!("Got invalid pointer from alloc() usercall") | |
204 | } | |
0731742a XL |
205 | } |
206 | } | |
207 | ||
9fa01778 | 208 | /// Copies `val` into freshly allocated space in user memory. |
0731742a XL |
209 | pub fn new_from_enclave(val: &T) -> Self { |
210 | unsafe { | |
211 | let ret = Self::new_uninit_bytes(mem::size_of_val(val)); | |
212 | ptr::copy( | |
213 | val as *const T as *const u8, | |
214 | ret.0.as_ptr() as *mut u8, | |
60c5eb7d | 215 | mem::size_of_val(val), |
0731742a XL |
216 | ); |
217 | ret | |
218 | } | |
219 | } | |
220 | ||
9fa01778 | 221 | /// Creates an owned `User<T>` from a raw pointer. |
0731742a XL |
222 | /// |
223 | /// # Safety | |
224 | /// The caller must ensure `ptr` points to `T`, is freeable with the `free` | |
225 | /// usercall and the alignment of `T`, and is uniquely owned. | |
226 | /// | |
227 | /// # Panics | |
228 | /// This function panics if: | |
229 | /// | |
230 | /// * The pointer is not aligned | |
231 | /// * The pointer is null | |
232 | /// * The pointed-to range is not in user memory | |
233 | pub unsafe fn from_raw(ptr: *mut T) -> Self { | |
234 | T::check_ptr(ptr); | |
235 | User(NonNull::new_userref(ptr)) | |
236 | } | |
237 | ||
9fa01778 | 238 | /// Converts this value into a raw pointer. The value will no longer be |
0731742a XL |
239 | /// automatically freed. |
240 | pub fn into_raw(self) -> *mut T { | |
241 | let ret = self.0; | |
242 | mem::forget(self); | |
243 | ret.as_ptr() as _ | |
244 | } | |
245 | } | |
246 | ||
247 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
248 | impl<T> User<T> |
249 | where | |
250 | T: UserSafe, | |
251 | { | |
0731742a XL |
252 | /// Allocate space for `T` in user memory. |
253 | pub fn uninitialized() -> Self { | |
254 | Self::new_uninit_bytes(mem::size_of::<T>()) | |
255 | } | |
256 | } | |
257 | ||
258 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
259 | impl<T> User<[T]> |
260 | where | |
261 | [T]: UserSafe, | |
262 | { | |
0731742a XL |
263 | /// Allocate space for a `[T]` of `n` elements in user memory. |
264 | pub fn uninitialized(n: usize) -> Self { | |
265 | Self::new_uninit_bytes(n * mem::size_of::<T>()) | |
266 | } | |
267 | ||
9fa01778 | 268 | /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
269 | /// |
270 | /// # Safety | |
271 | /// The caller must ensure `ptr` points to `len` elements of `T`, is | |
272 | /// freeable with the `free` usercall and the alignment of `T`, and is | |
273 | /// uniquely owned. | |
274 | /// | |
275 | /// # Panics | |
276 | /// This function panics if: | |
277 | /// | |
278 | /// * The pointer is not aligned | |
279 | /// * The pointer is null | |
48663c56 | 280 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
281 | /// * The pointed-to range is not in user memory |
282 | pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { | |
283 | User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()))) | |
284 | } | |
285 | } | |
286 | ||
287 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
288 | impl<T: ?Sized> UserRef<T> |
289 | where | |
290 | T: UserSafe, | |
291 | { | |
9fa01778 | 292 | /// Creates a `&UserRef<[T]>` from a raw pointer. |
0731742a XL |
293 | /// |
294 | /// # Safety | |
295 | /// The caller must ensure `ptr` points to `T`. | |
296 | /// | |
297 | /// # Panics | |
298 | /// This function panics if: | |
299 | /// | |
300 | /// * The pointer is not aligned | |
301 | /// * The pointer is null | |
302 | /// * The pointed-to range is not in user memory | |
303 | pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self { | |
304 | T::check_ptr(ptr); | |
305 | &*(ptr as *const Self) | |
306 | } | |
307 | ||
9fa01778 | 308 | /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct |
0731742a XL |
309 | /// documentation for the nuances regarding a `&mut UserRef<T>`. |
310 | /// | |
311 | /// # Safety | |
312 | /// The caller must ensure `ptr` points to `T`. | |
313 | /// | |
314 | /// # Panics | |
315 | /// This function panics if: | |
316 | /// | |
317 | /// * The pointer is not aligned | |
318 | /// * The pointer is null | |
319 | /// * The pointed-to range is not in user memory | |
320 | pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self { | |
321 | T::check_ptr(ptr); | |
60c5eb7d | 322 | &mut *(ptr as *mut Self) |
0731742a XL |
323 | } |
324 | ||
9fa01778 | 325 | /// Copies `val` into user memory. |
0731742a XL |
326 | /// |
327 | /// # Panics | |
328 | /// This function panics if the destination doesn't have the same size as | |
329 | /// the source. This can happen for dynamically-sized types such as slices. | |
330 | pub fn copy_from_enclave(&mut self, val: &T) { | |
331 | unsafe { | |
60c5eb7d | 332 | assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get())); |
0731742a XL |
333 | ptr::copy( |
334 | val as *const T as *const u8, | |
335 | self.0.get() as *mut T as *mut u8, | |
60c5eb7d | 336 | mem::size_of_val(val), |
0731742a XL |
337 | ); |
338 | } | |
339 | } | |
340 | ||
9fa01778 | 341 | /// Copies the value from user memory and place it into `dest`. |
0731742a XL |
342 | /// |
343 | /// # Panics | |
344 | /// This function panics if the destination doesn't have the same size as | |
345 | /// the source. This can happen for dynamically-sized types such as slices. | |
346 | pub fn copy_to_enclave(&self, dest: &mut T) { | |
347 | unsafe { | |
60c5eb7d | 348 | assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get())); |
0731742a XL |
349 | ptr::copy( |
350 | self.0.get() as *const T as *const u8, | |
351 | dest as *mut T as *mut u8, | |
60c5eb7d | 352 | mem::size_of_val(dest), |
0731742a XL |
353 | ); |
354 | } | |
355 | } | |
356 | ||
357 | /// Obtain a raw pointer from this reference. | |
358 | pub fn as_raw_ptr(&self) -> *const T { | |
359 | self as *const _ as _ | |
360 | } | |
361 | ||
362 | /// Obtain a raw pointer from this reference. | |
363 | pub fn as_raw_mut_ptr(&mut self) -> *mut T { | |
364 | self as *mut _ as _ | |
365 | } | |
366 | } | |
367 | ||
368 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
369 | impl<T> UserRef<T> |
370 | where | |
371 | T: UserSafe, | |
372 | { | |
9fa01778 | 373 | /// Copies the value from user memory into enclave memory. |
0731742a XL |
374 | pub fn to_enclave(&self) -> T { |
375 | unsafe { ptr::read(self.0.get()) } | |
376 | } | |
377 | } | |
378 | ||
379 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
380 | impl<T> UserRef<[T]> |
381 | where | |
382 | [T]: UserSafe, | |
383 | { | |
9fa01778 | 384 | /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
385 | /// |
386 | /// # Safety | |
387 | /// The caller must ensure `ptr` points to `n` elements of `T`. | |
388 | /// | |
389 | /// # Panics | |
390 | /// This function panics if: | |
391 | /// | |
392 | /// * The pointer is not aligned | |
393 | /// * The pointer is null | |
48663c56 | 394 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
395 | /// * The pointed-to range is not in user memory |
396 | pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self { | |
397 | &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self) | |
398 | } | |
399 | ||
9fa01778 | 400 | /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
401 | /// See the struct documentation for the nuances regarding a |
402 | /// `&mut UserRef<T>`. | |
403 | /// | |
404 | /// # Safety | |
405 | /// The caller must ensure `ptr` points to `n` elements of `T`. | |
406 | /// | |
407 | /// # Panics | |
408 | /// This function panics if: | |
409 | /// | |
410 | /// * The pointer is not aligned | |
411 | /// * The pointer is null | |
48663c56 | 412 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
413 | /// * The pointed-to range is not in user memory |
414 | pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self { | |
60c5eb7d | 415 | &mut *(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self) |
0731742a XL |
416 | } |
417 | ||
418 | /// Obtain a raw pointer to the first element of this user slice. | |
419 | pub fn as_ptr(&self) -> *const T { | |
420 | self.0.get() as _ | |
421 | } | |
422 | ||
423 | /// Obtain a raw pointer to the first element of this user slice. | |
424 | pub fn as_mut_ptr(&mut self) -> *mut T { | |
425 | self.0.get() as _ | |
426 | } | |
427 | ||
428 | /// Obtain the number of elements in this user slice. | |
429 | pub fn len(&self) -> usize { | |
430 | unsafe { (*self.0.get()).len() } | |
431 | } | |
432 | ||
9fa01778 | 433 | /// Copies the value from user memory and place it into `dest`. Afterwards, |
0731742a XL |
434 | /// `dest` will contain exactly `self.len()` elements. |
435 | /// | |
436 | /// # Panics | |
437 | /// This function panics if the destination doesn't have the same size as | |
438 | /// the source. This can happen for dynamically-sized types such as slices. | |
439 | pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) { | |
440 | unsafe { | |
441 | if let Some(missing) = self.len().checked_sub(dest.capacity()) { | |
442 | dest.reserve(missing) | |
443 | } | |
444 | dest.set_len(self.len()); | |
445 | self.copy_to_enclave(&mut dest[..]); | |
446 | } | |
447 | } | |
448 | ||
9fa01778 | 449 | /// Copies the value from user memory into a vector in enclave memory. |
0731742a XL |
450 | pub fn to_enclave(&self) -> Vec<T> { |
451 | let mut ret = Vec::with_capacity(self.len()); | |
452 | self.copy_to_enclave_vec(&mut ret); | |
453 | ret | |
454 | } | |
455 | ||
456 | /// Returns an iterator over the slice. | |
532ac7d7 | 457 | pub fn iter(&self) -> Iter<'_, T> |
60c5eb7d XL |
458 | where |
459 | T: UserSafe, // FIXME: should be implied by [T]: UserSafe? | |
0731742a | 460 | { |
60c5eb7d | 461 | unsafe { Iter((&*self.as_raw_ptr()).iter()) } |
0731742a XL |
462 | } |
463 | ||
464 | /// Returns an iterator that allows modifying each value. | |
532ac7d7 | 465 | pub fn iter_mut(&mut self) -> IterMut<'_, T> |
60c5eb7d XL |
466 | where |
467 | T: UserSafe, // FIXME: should be implied by [T]: UserSafe? | |
0731742a | 468 | { |
60c5eb7d | 469 | unsafe { IterMut((&mut *self.as_raw_mut_ptr()).iter_mut()) } |
0731742a XL |
470 | } |
471 | } | |
472 | ||
473 | /// Immutable user slice iterator | |
474 | /// | |
475 | /// This struct is created by the `iter` method on `UserRef<[T]>`. | |
476 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
477 | pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>); | |
478 | ||
479 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
480 | impl<'a, T: UserSafe> Iterator for Iter<'a, T> { | |
481 | type Item = &'a UserRef<T>; | |
482 | ||
483 | #[inline] | |
484 | fn next(&mut self) -> Option<Self::Item> { | |
60c5eb7d | 485 | unsafe { self.0.next().map(|e| UserRef::from_ptr(e)) } |
0731742a XL |
486 | } |
487 | } | |
488 | ||
489 | /// Mutable user slice iterator | |
490 | /// | |
491 | /// This struct is created by the `iter_mut` method on `UserRef<[T]>`. | |
492 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
493 | pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>); | |
494 | ||
495 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
496 | impl<'a, T: UserSafe> Iterator for IterMut<'a, T> { | |
497 | type Item = &'a mut UserRef<T>; | |
498 | ||
499 | #[inline] | |
500 | fn next(&mut self) -> Option<Self::Item> { | |
60c5eb7d | 501 | unsafe { self.0.next().map(|e| UserRef::from_mut_ptr(e)) } |
0731742a XL |
502 | } |
503 | } | |
504 | ||
505 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
506 | impl<T: ?Sized> Deref for User<T> |
507 | where | |
508 | T: UserSafe, | |
509 | { | |
0731742a XL |
510 | type Target = UserRef<T>; |
511 | ||
512 | fn deref(&self) -> &Self::Target { | |
513 | unsafe { &*self.0.as_ptr() } | |
514 | } | |
515 | } | |
516 | ||
517 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
518 | impl<T: ?Sized> DerefMut for User<T> |
519 | where | |
520 | T: UserSafe, | |
521 | { | |
0731742a | 522 | fn deref_mut(&mut self) -> &mut Self::Target { |
60c5eb7d | 523 | unsafe { &mut *self.0.as_ptr() } |
0731742a XL |
524 | } |
525 | } | |
526 | ||
527 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
528 | impl<T: ?Sized> Drop for User<T> |
529 | where | |
530 | T: UserSafe, | |
531 | { | |
0731742a XL |
532 | fn drop(&mut self) { |
533 | unsafe { | |
534 | let ptr = (*self.0.as_ptr()).0.get(); | |
60c5eb7d | 535 | super::free(ptr as _, mem::size_of_val(&mut *ptr), T::align_of()); |
0731742a XL |
536 | } |
537 | } | |
538 | } | |
539 | ||
540 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
541 | impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {} | |
542 | ||
543 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
416331ca XL |
544 | impl<T, I> Index<I> for UserRef<[T]> |
545 | where | |
546 | [T]: UserSafe, | |
547 | I: SliceIndex<[T], Output: UserSafe>, | |
548 | { | |
0731742a XL |
549 | type Output = UserRef<I::Output>; |
550 | ||
551 | #[inline] | |
552 | fn index(&self, index: I) -> &UserRef<I::Output> { | |
553 | unsafe { | |
48663c56 XL |
554 | if let Some(slice) = index.get(&*self.as_raw_ptr()) { |
555 | UserRef::from_ptr(slice) | |
556 | } else { | |
557 | rtabort!("index out of range for user slice"); | |
558 | } | |
0731742a XL |
559 | } |
560 | } | |
561 | } | |
562 | ||
563 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
416331ca XL |
564 | impl<T, I> IndexMut<I> for UserRef<[T]> |
565 | where | |
566 | [T]: UserSafe, | |
567 | I: SliceIndex<[T], Output: UserSafe>, | |
568 | { | |
0731742a XL |
569 | #[inline] |
570 | fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> { | |
571 | unsafe { | |
60c5eb7d | 572 | if let Some(slice) = index.get_mut(&mut *self.as_raw_mut_ptr()) { |
48663c56 XL |
573 | UserRef::from_mut_ptr(slice) |
574 | } else { | |
575 | rtabort!("index out of range for user slice"); | |
576 | } | |
0731742a XL |
577 | } |
578 | } | |
579 | } | |
580 | ||
581 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
582 | impl UserRef<super::raw::ByteBuffer> { | |
9fa01778 | 583 | /// Copies the user memory range pointed to by the user `ByteBuffer` to |
0731742a XL |
584 | /// enclave memory. |
585 | /// | |
586 | /// # Panics | |
48663c56 | 587 | /// This function panics if, in the user `ByteBuffer`: |
0731742a | 588 | /// |
48663c56 XL |
589 | /// * The pointer is null |
590 | /// * The pointed-to range does not fit in the address space | |
591 | /// * The pointed-to range is not in user memory | |
0731742a XL |
592 | pub fn copy_user_buffer(&self) -> Vec<u8> { |
593 | unsafe { | |
594 | let buf = self.to_enclave(); | |
9fa01778 XL |
595 | if buf.len > 0 { |
596 | User::from_raw_parts(buf.data as _, buf.len).to_enclave() | |
597 | } else { | |
598 | // Mustn't look at `data` or call `free` if `len` is `0`. | |
599 | Vec::with_capacity(0) | |
600 | } | |
0731742a XL |
601 | } |
602 | } | |
603 | } |