]>
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); |
29967ef6 XL |
92 | // SAFETY: The caller has guaranteed the pointer is valid |
93 | let ret = unsafe { Self::from_raw_sized_unchecked(ptr, size) }; | |
94 | unsafe { | |
95 | Self::check_ptr(ret); | |
96 | NonNull::new_unchecked(ret as _) | |
97 | } | |
0731742a XL |
98 | } |
99 | ||
9fa01778 | 100 | /// Checks if a pointer may point to `Self` in user memory. |
0731742a XL |
101 | /// |
102 | /// # Safety | |
9fa01778 | 103 | /// |
0731742a XL |
104 | /// The caller must ensure the memory range points to the correct type and |
105 | /// length (if this is a slice). | |
106 | /// | |
107 | /// # Panics | |
9fa01778 | 108 | /// |
0731742a XL |
109 | /// This function panics if: |
110 | /// | |
9fa01778 XL |
111 | /// * the pointer is not aligned. |
112 | /// * the pointer is null. | |
113 | /// * the pointed-to range is not in user memory. | |
0731742a | 114 | unsafe fn check_ptr(ptr: *const Self) { |
60c5eb7d | 115 | let is_aligned = |p| -> bool { 0 == (p as usize) & (Self::align_of() - 1) }; |
0731742a XL |
116 | |
117 | assert!(is_aligned(ptr as *const u8)); | |
29967ef6 | 118 | assert!(is_user_range(ptr as _, mem::size_of_val(unsafe { &*ptr }))); |
0731742a XL |
119 | assert!(!ptr.is_null()); |
120 | } | |
121 | } | |
122 | ||
123 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
124 | unsafe impl<T: UserSafeSized> UserSafe for T { | |
125 | fn align_of() -> usize { | |
126 | mem::align_of::<T>() | |
127 | } | |
128 | ||
129 | unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self { | |
130 | assert_eq!(size, mem::size_of::<T>()); | |
131 | ptr as _ | |
132 | } | |
133 | } | |
134 | ||
135 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
136 | unsafe impl<T: UserSafeSized> UserSafe for [T] { | |
137 | fn align_of() -> usize { | |
138 | mem::align_of::<T>() | |
139 | } | |
140 | ||
29967ef6 XL |
141 | /// # Safety |
142 | /// Behavior is undefined if any of these conditions are violated: | |
143 | /// * `ptr` must be [valid] for writes of `size` many bytes, and it must be | |
144 | /// properly aligned. | |
145 | /// | |
146 | /// [valid]: core::ptr#safety | |
147 | /// # Panics | |
148 | /// | |
149 | /// This function panics if: | |
150 | /// | |
151 | /// * the element size is not a factor of the size | |
0731742a XL |
152 | unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self { |
153 | let elem_size = mem::size_of::<T>(); | |
154 | assert_eq!(size % elem_size, 0); | |
155 | let len = size / elem_size; | |
29967ef6 XL |
156 | // SAFETY: The caller must uphold the safety contract for `from_raw_sized_unchecked` |
157 | unsafe { slice::from_raw_parts_mut(ptr as _, len) } | |
0731742a XL |
158 | } |
159 | } | |
160 | ||
161 | /// A reference to some type in userspace memory. `&UserRef<T>` is equivalent | |
162 | /// to `&T` in enclave memory. Access to the memory is only allowed by copying | |
163 | /// to avoid TOCTTOU issues. After copying, code should make sure to completely | |
164 | /// check the value before use. | |
165 | /// | |
166 | /// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike | |
167 | /// regular mutable references, these are not exclusive. Userspace may always | |
168 | /// write to the backing memory at any time, so it can't be assumed that there | |
74b04a01 | 169 | /// the pointed-to memory is uniquely borrowed. The two different reference types |
0731742a XL |
170 | /// are used solely to indicate intent: a mutable reference is for writing to |
171 | /// user memory, an immutable reference for reading from user memory. | |
172 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
173 | pub struct UserRef<T: ?Sized>(UnsafeCell<T>); | |
174 | /// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in | |
175 | /// enclave memory. Access to the memory is only allowed by copying to avoid | |
176 | /// TOCTTOU issues. The user memory will be freed when the value is dropped. | |
177 | /// After copying, code should make sure to completely check the value before | |
178 | /// use. | |
179 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
180 | pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>); | |
181 | ||
182 | trait NewUserRef<T: ?Sized> { | |
183 | unsafe fn new_userref(v: T) -> Self; | |
184 | } | |
185 | ||
186 | impl<T: ?Sized> NewUserRef<*mut T> for NonNull<UserRef<T>> { | |
187 | unsafe fn new_userref(v: *mut T) -> Self { | |
29967ef6 XL |
188 | // SAFETY: The caller has guaranteed the pointer is valid |
189 | unsafe { NonNull::new_unchecked(v as _) } | |
0731742a XL |
190 | } |
191 | } | |
192 | ||
193 | impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> { | |
194 | unsafe fn new_userref(v: NonNull<T>) -> Self { | |
29967ef6 XL |
195 | // SAFETY: The caller has guaranteed the pointer is valid |
196 | unsafe { NonNull::new_userref(v.as_ptr()) } | |
0731742a XL |
197 | } |
198 | } | |
199 | ||
200 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
201 | impl<T: ?Sized> User<T> |
202 | where | |
203 | T: UserSafe, | |
204 | { | |
0731742a XL |
205 | // This function returns memory that is practically uninitialized, but is |
206 | // not considered "unspecified" or "undefined" for purposes of an | |
207 | // optimizing compiler. This is achieved by returning a pointer from | |
208 | // from outside as obtained by `super::alloc`. | |
209 | fn new_uninit_bytes(size: usize) -> Self { | |
210 | unsafe { | |
532ac7d7 XL |
211 | // Mustn't call alloc with size 0. |
212 | let ptr = if size > 0 { | |
213 | rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ | |
214 | } else { | |
215 | T::align_of() as _ // dangling pointer ok for size 0 | |
216 | }; | |
217 | if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) { | |
218 | User(NonNull::new_userref(v)) | |
219 | } else { | |
220 | rtabort!("Got invalid pointer from alloc() usercall") | |
221 | } | |
0731742a XL |
222 | } |
223 | } | |
224 | ||
9fa01778 | 225 | /// Copies `val` into freshly allocated space in user memory. |
0731742a XL |
226 | pub fn new_from_enclave(val: &T) -> Self { |
227 | unsafe { | |
228 | let ret = Self::new_uninit_bytes(mem::size_of_val(val)); | |
229 | ptr::copy( | |
230 | val as *const T as *const u8, | |
231 | ret.0.as_ptr() as *mut u8, | |
60c5eb7d | 232 | mem::size_of_val(val), |
0731742a XL |
233 | ); |
234 | ret | |
235 | } | |
236 | } | |
237 | ||
9fa01778 | 238 | /// Creates an owned `User<T>` from a raw pointer. |
0731742a XL |
239 | /// |
240 | /// # Safety | |
241 | /// The caller must ensure `ptr` points to `T`, is freeable with the `free` | |
242 | /// usercall and the alignment of `T`, and is uniquely owned. | |
243 | /// | |
244 | /// # Panics | |
245 | /// This function panics if: | |
246 | /// | |
247 | /// * The pointer is not aligned | |
248 | /// * The pointer is null | |
249 | /// * The pointed-to range is not in user memory | |
250 | pub unsafe fn from_raw(ptr: *mut T) -> Self { | |
29967ef6 XL |
251 | // SAFETY: the caller must uphold the safety contract for `from_raw`. |
252 | unsafe { T::check_ptr(ptr) }; | |
253 | User(unsafe { NonNull::new_userref(ptr) }) | |
0731742a XL |
254 | } |
255 | ||
9fa01778 | 256 | /// Converts this value into a raw pointer. The value will no longer be |
0731742a XL |
257 | /// automatically freed. |
258 | pub fn into_raw(self) -> *mut T { | |
259 | let ret = self.0; | |
260 | mem::forget(self); | |
261 | ret.as_ptr() as _ | |
262 | } | |
263 | } | |
264 | ||
265 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
266 | impl<T> User<T> |
267 | where | |
268 | T: UserSafe, | |
269 | { | |
0731742a XL |
270 | /// Allocate space for `T` in user memory. |
271 | pub fn uninitialized() -> Self { | |
272 | Self::new_uninit_bytes(mem::size_of::<T>()) | |
273 | } | |
274 | } | |
275 | ||
276 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
277 | impl<T> User<[T]> |
278 | where | |
279 | [T]: UserSafe, | |
280 | { | |
0731742a XL |
281 | /// Allocate space for a `[T]` of `n` elements in user memory. |
282 | pub fn uninitialized(n: usize) -> Self { | |
283 | Self::new_uninit_bytes(n * mem::size_of::<T>()) | |
284 | } | |
285 | ||
9fa01778 | 286 | /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
287 | /// |
288 | /// # Safety | |
289 | /// The caller must ensure `ptr` points to `len` elements of `T`, is | |
290 | /// freeable with the `free` usercall and the alignment of `T`, and is | |
291 | /// uniquely owned. | |
292 | /// | |
293 | /// # Panics | |
294 | /// This function panics if: | |
295 | /// | |
296 | /// * The pointer is not aligned | |
297 | /// * The pointer is null | |
48663c56 | 298 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
299 | /// * The pointed-to range is not in user memory |
300 | pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { | |
29967ef6 XL |
301 | User(unsafe { |
302 | NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())) | |
303 | }) | |
0731742a XL |
304 | } |
305 | } | |
306 | ||
307 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
308 | impl<T: ?Sized> UserRef<T> |
309 | where | |
310 | T: UserSafe, | |
311 | { | |
9fa01778 | 312 | /// Creates a `&UserRef<[T]>` from a raw pointer. |
0731742a XL |
313 | /// |
314 | /// # Safety | |
315 | /// The caller must ensure `ptr` points to `T`. | |
316 | /// | |
317 | /// # Panics | |
318 | /// This function panics if: | |
319 | /// | |
320 | /// * The pointer is not aligned | |
321 | /// * The pointer is null | |
322 | /// * The pointed-to range is not in user memory | |
323 | pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self { | |
29967ef6 XL |
324 | // SAFETY: The caller must uphold the safety contract for `from_ptr`. |
325 | unsafe { T::check_ptr(ptr) }; | |
326 | unsafe { &*(ptr as *const Self) } | |
0731742a XL |
327 | } |
328 | ||
9fa01778 | 329 | /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct |
0731742a XL |
330 | /// documentation for the nuances regarding a `&mut UserRef<T>`. |
331 | /// | |
332 | /// # Safety | |
333 | /// The caller must ensure `ptr` points to `T`. | |
334 | /// | |
335 | /// # Panics | |
336 | /// This function panics if: | |
337 | /// | |
338 | /// * The pointer is not aligned | |
339 | /// * The pointer is null | |
340 | /// * The pointed-to range is not in user memory | |
341 | pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self { | |
29967ef6 XL |
342 | // SAFETY: The caller must uphold the safety contract for `from_mut_ptr`. |
343 | unsafe { T::check_ptr(ptr) }; | |
344 | unsafe { &mut *(ptr as *mut Self) } | |
0731742a XL |
345 | } |
346 | ||
9fa01778 | 347 | /// Copies `val` into user memory. |
0731742a XL |
348 | /// |
349 | /// # Panics | |
350 | /// This function panics if the destination doesn't have the same size as | |
351 | /// the source. This can happen for dynamically-sized types such as slices. | |
352 | pub fn copy_from_enclave(&mut self, val: &T) { | |
353 | unsafe { | |
60c5eb7d | 354 | assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get())); |
0731742a XL |
355 | ptr::copy( |
356 | val as *const T as *const u8, | |
357 | self.0.get() as *mut T as *mut u8, | |
60c5eb7d | 358 | mem::size_of_val(val), |
0731742a XL |
359 | ); |
360 | } | |
361 | } | |
362 | ||
9fa01778 | 363 | /// Copies the value from user memory and place it into `dest`. |
0731742a XL |
364 | /// |
365 | /// # Panics | |
366 | /// This function panics if the destination doesn't have the same size as | |
367 | /// the source. This can happen for dynamically-sized types such as slices. | |
368 | pub fn copy_to_enclave(&self, dest: &mut T) { | |
369 | unsafe { | |
60c5eb7d | 370 | assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get())); |
0731742a XL |
371 | ptr::copy( |
372 | self.0.get() as *const T as *const u8, | |
373 | dest as *mut T as *mut u8, | |
60c5eb7d | 374 | mem::size_of_val(dest), |
0731742a XL |
375 | ); |
376 | } | |
377 | } | |
378 | ||
379 | /// Obtain a raw pointer from this reference. | |
380 | pub fn as_raw_ptr(&self) -> *const T { | |
381 | self as *const _ as _ | |
382 | } | |
383 | ||
384 | /// Obtain a raw pointer from this reference. | |
385 | pub fn as_raw_mut_ptr(&mut self) -> *mut T { | |
386 | self as *mut _ as _ | |
387 | } | |
388 | } | |
389 | ||
390 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
391 | impl<T> UserRef<T> |
392 | where | |
393 | T: UserSafe, | |
394 | { | |
9fa01778 | 395 | /// Copies the value from user memory into enclave memory. |
0731742a XL |
396 | pub fn to_enclave(&self) -> T { |
397 | unsafe { ptr::read(self.0.get()) } | |
398 | } | |
399 | } | |
400 | ||
401 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
402 | impl<T> UserRef<[T]> |
403 | where | |
404 | [T]: UserSafe, | |
405 | { | |
9fa01778 | 406 | /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
407 | /// |
408 | /// # Safety | |
409 | /// The caller must ensure `ptr` points to `n` elements of `T`. | |
410 | /// | |
411 | /// # Panics | |
412 | /// This function panics if: | |
413 | /// | |
414 | /// * The pointer is not aligned | |
415 | /// * The pointer is null | |
48663c56 | 416 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
417 | /// * The pointed-to range is not in user memory |
418 | pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self { | |
29967ef6 XL |
419 | // SAFETY: The caller must uphold the safety contract for `from_raw_parts`. |
420 | unsafe { | |
421 | &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self) | |
422 | } | |
0731742a XL |
423 | } |
424 | ||
9fa01778 | 425 | /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length. |
0731742a XL |
426 | /// See the struct documentation for the nuances regarding a |
427 | /// `&mut UserRef<T>`. | |
428 | /// | |
429 | /// # Safety | |
430 | /// The caller must ensure `ptr` points to `n` elements of `T`. | |
431 | /// | |
432 | /// # Panics | |
433 | /// This function panics if: | |
434 | /// | |
435 | /// * The pointer is not aligned | |
436 | /// * The pointer is null | |
48663c56 | 437 | /// * The pointed-to range does not fit in the address space |
0731742a XL |
438 | /// * The pointed-to range is not in user memory |
439 | pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self { | |
29967ef6 XL |
440 | // SAFETY: The caller must uphold the safety contract for `from_raw_parts_mut`. |
441 | unsafe { | |
442 | &mut *(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self) | |
443 | } | |
0731742a XL |
444 | } |
445 | ||
446 | /// Obtain a raw pointer to the first element of this user slice. | |
447 | pub fn as_ptr(&self) -> *const T { | |
448 | self.0.get() as _ | |
449 | } | |
450 | ||
451 | /// Obtain a raw pointer to the first element of this user slice. | |
452 | pub fn as_mut_ptr(&mut self) -> *mut T { | |
453 | self.0.get() as _ | |
454 | } | |
455 | ||
456 | /// Obtain the number of elements in this user slice. | |
457 | pub fn len(&self) -> usize { | |
458 | unsafe { (*self.0.get()).len() } | |
459 | } | |
460 | ||
9fa01778 | 461 | /// Copies the value from user memory and place it into `dest`. Afterwards, |
0731742a XL |
462 | /// `dest` will contain exactly `self.len()` elements. |
463 | /// | |
464 | /// # Panics | |
465 | /// This function panics if the destination doesn't have the same size as | |
466 | /// the source. This can happen for dynamically-sized types such as slices. | |
467 | pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) { | |
29967ef6 XL |
468 | if let Some(missing) = self.len().checked_sub(dest.capacity()) { |
469 | dest.reserve(missing) | |
0731742a | 470 | } |
29967ef6 XL |
471 | // SAFETY: We reserve enough space above. |
472 | unsafe { dest.set_len(self.len()) }; | |
473 | self.copy_to_enclave(&mut dest[..]); | |
0731742a XL |
474 | } |
475 | ||
9fa01778 | 476 | /// Copies the value from user memory into a vector in enclave memory. |
0731742a XL |
477 | pub fn to_enclave(&self) -> Vec<T> { |
478 | let mut ret = Vec::with_capacity(self.len()); | |
479 | self.copy_to_enclave_vec(&mut ret); | |
480 | ret | |
481 | } | |
482 | ||
483 | /// Returns an iterator over the slice. | |
532ac7d7 | 484 | pub fn iter(&self) -> Iter<'_, T> |
60c5eb7d XL |
485 | where |
486 | T: UserSafe, // FIXME: should be implied by [T]: UserSafe? | |
0731742a | 487 | { |
60c5eb7d | 488 | unsafe { Iter((&*self.as_raw_ptr()).iter()) } |
0731742a XL |
489 | } |
490 | ||
491 | /// Returns an iterator that allows modifying each value. | |
532ac7d7 | 492 | pub fn iter_mut(&mut self) -> IterMut<'_, T> |
60c5eb7d XL |
493 | where |
494 | T: UserSafe, // FIXME: should be implied by [T]: UserSafe? | |
0731742a | 495 | { |
60c5eb7d | 496 | unsafe { IterMut((&mut *self.as_raw_mut_ptr()).iter_mut()) } |
0731742a XL |
497 | } |
498 | } | |
499 | ||
500 | /// Immutable user slice iterator | |
501 | /// | |
502 | /// This struct is created by the `iter` method on `UserRef<[T]>`. | |
503 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
504 | pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>); | |
505 | ||
506 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
507 | impl<'a, T: UserSafe> Iterator for Iter<'a, T> { | |
508 | type Item = &'a UserRef<T>; | |
509 | ||
510 | #[inline] | |
511 | fn next(&mut self) -> Option<Self::Item> { | |
60c5eb7d | 512 | unsafe { self.0.next().map(|e| UserRef::from_ptr(e)) } |
0731742a XL |
513 | } |
514 | } | |
515 | ||
516 | /// Mutable user slice iterator | |
517 | /// | |
518 | /// This struct is created by the `iter_mut` method on `UserRef<[T]>`. | |
519 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
520 | pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>); | |
521 | ||
522 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
523 | impl<'a, T: UserSafe> Iterator for IterMut<'a, T> { | |
524 | type Item = &'a mut UserRef<T>; | |
525 | ||
526 | #[inline] | |
527 | fn next(&mut self) -> Option<Self::Item> { | |
60c5eb7d | 528 | unsafe { self.0.next().map(|e| UserRef::from_mut_ptr(e)) } |
0731742a XL |
529 | } |
530 | } | |
531 | ||
532 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
533 | impl<T: ?Sized> Deref for User<T> |
534 | where | |
535 | T: UserSafe, | |
536 | { | |
0731742a XL |
537 | type Target = UserRef<T>; |
538 | ||
539 | fn deref(&self) -> &Self::Target { | |
540 | unsafe { &*self.0.as_ptr() } | |
541 | } | |
542 | } | |
543 | ||
544 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
545 | impl<T: ?Sized> DerefMut for User<T> |
546 | where | |
547 | T: UserSafe, | |
548 | { | |
0731742a | 549 | fn deref_mut(&mut self) -> &mut Self::Target { |
60c5eb7d | 550 | unsafe { &mut *self.0.as_ptr() } |
0731742a XL |
551 | } |
552 | } | |
553 | ||
554 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
60c5eb7d XL |
555 | impl<T: ?Sized> Drop for User<T> |
556 | where | |
557 | T: UserSafe, | |
558 | { | |
0731742a XL |
559 | fn drop(&mut self) { |
560 | unsafe { | |
561 | let ptr = (*self.0.as_ptr()).0.get(); | |
60c5eb7d | 562 | super::free(ptr as _, mem::size_of_val(&mut *ptr), T::align_of()); |
0731742a XL |
563 | } |
564 | } | |
565 | } | |
566 | ||
567 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
568 | impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {} | |
569 | ||
570 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
416331ca XL |
571 | impl<T, I> Index<I> for UserRef<[T]> |
572 | where | |
573 | [T]: UserSafe, | |
ee023bcb FG |
574 | I: SliceIndex<[T]>, |
575 | I::Output: UserSafe, | |
416331ca | 576 | { |
0731742a XL |
577 | type Output = UserRef<I::Output>; |
578 | ||
579 | #[inline] | |
580 | fn index(&self, index: I) -> &UserRef<I::Output> { | |
581 | unsafe { | |
48663c56 XL |
582 | if let Some(slice) = index.get(&*self.as_raw_ptr()) { |
583 | UserRef::from_ptr(slice) | |
584 | } else { | |
585 | rtabort!("index out of range for user slice"); | |
586 | } | |
0731742a XL |
587 | } |
588 | } | |
589 | } | |
590 | ||
591 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
416331ca XL |
592 | impl<T, I> IndexMut<I> for UserRef<[T]> |
593 | where | |
594 | [T]: UserSafe, | |
ee023bcb FG |
595 | I: SliceIndex<[T]>, |
596 | I::Output: UserSafe, | |
416331ca | 597 | { |
0731742a XL |
598 | #[inline] |
599 | fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> { | |
600 | unsafe { | |
60c5eb7d | 601 | if let Some(slice) = index.get_mut(&mut *self.as_raw_mut_ptr()) { |
48663c56 XL |
602 | UserRef::from_mut_ptr(slice) |
603 | } else { | |
604 | rtabort!("index out of range for user slice"); | |
605 | } | |
0731742a XL |
606 | } |
607 | } | |
608 | } | |
609 | ||
610 | #[unstable(feature = "sgx_platform", issue = "56975")] | |
611 | impl UserRef<super::raw::ByteBuffer> { | |
9fa01778 | 612 | /// Copies the user memory range pointed to by the user `ByteBuffer` to |
0731742a XL |
613 | /// enclave memory. |
614 | /// | |
615 | /// # Panics | |
48663c56 | 616 | /// This function panics if, in the user `ByteBuffer`: |
0731742a | 617 | /// |
48663c56 XL |
618 | /// * The pointer is null |
619 | /// * The pointed-to range does not fit in the address space | |
620 | /// * The pointed-to range is not in user memory | |
0731742a XL |
621 | pub fn copy_user_buffer(&self) -> Vec<u8> { |
622 | unsafe { | |
623 | let buf = self.to_enclave(); | |
9fa01778 XL |
624 | if buf.len > 0 { |
625 | User::from_raw_parts(buf.data as _, buf.len).to_enclave() | |
626 | } else { | |
627 | // Mustn't look at `data` or call `free` if `len` is `0`. | |
628 | Vec::with_capacity(0) | |
629 | } | |
0731742a XL |
630 | } |
631 | } | |
632 | } |