Skip to content

Commit b60598f

Browse files
authored
Rollup merge of rust-lang#137355 - thaliaarchi:io-optional-methods/sgx, r=ChrisDenton
Implement `read_buf` and vectored read/write for SGX stdio Implement `read_buf`, `read_vectored`, and `write_vectored` for the SGX stdio types. Additionally, extend `User<T>::copy_to_enclave` to work for copying to uninitialized values and fix unsoundness in `UserRef<[T]>::copy_to_enclave_vec`. cc ``@jethrogb`` Tracked in rust-lang#136756
2 parents 007b229 + 6e3424a commit b60598f

File tree

4 files changed

+97
-19
lines changed

4 files changed

+97
-19
lines changed

std/src/sys/pal/sgx/abi/usercalls/alloc.rs

+48-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::super::mem::{is_enclave_range, is_user_range};
66
use crate::arch::asm;
77
use crate::cell::UnsafeCell;
88
use crate::convert::TryInto;
9-
use crate::mem::{self, ManuallyDrop};
9+
use crate::mem::{self, ManuallyDrop, MaybeUninit};
1010
use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
1111
use crate::pin::PinCoerceUnsized;
1212
use crate::ptr::{self, NonNull};
@@ -209,6 +209,45 @@ impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
209209
}
210210
}
211211

212+
/// A type which can a destination for safely copying from userspace.
213+
///
214+
/// # Safety
215+
///
216+
/// Requires that `T` and `Self` have identical layouts.
217+
#[unstable(feature = "sgx_platform", issue = "56975")]
218+
pub unsafe trait UserSafeCopyDestination<T: ?Sized> {
219+
/// Returns a pointer for writing to the value.
220+
fn as_mut_ptr(&mut self) -> *mut T;
221+
}
222+
223+
#[unstable(feature = "sgx_platform", issue = "56975")]
224+
unsafe impl<T> UserSafeCopyDestination<T> for T {
225+
fn as_mut_ptr(&mut self) -> *mut T {
226+
self as _
227+
}
228+
}
229+
230+
#[unstable(feature = "sgx_platform", issue = "56975")]
231+
unsafe impl<T> UserSafeCopyDestination<[T]> for [T] {
232+
fn as_mut_ptr(&mut self) -> *mut [T] {
233+
self as _
234+
}
235+
}
236+
237+
#[unstable(feature = "sgx_platform", issue = "56975")]
238+
unsafe impl<T> UserSafeCopyDestination<T> for MaybeUninit<T> {
239+
fn as_mut_ptr(&mut self) -> *mut T {
240+
self as *mut Self as _
241+
}
242+
}
243+
244+
#[unstable(feature = "sgx_platform", issue = "56975")]
245+
unsafe impl<T> UserSafeCopyDestination<[T]> for [MaybeUninit<T>] {
246+
fn as_mut_ptr(&mut self) -> *mut [T] {
247+
self as *mut Self as _
248+
}
249+
}
250+
212251
#[unstable(feature = "sgx_platform", issue = "56975")]
213252
impl<T: ?Sized> User<T>
214253
where
@@ -544,12 +583,12 @@ where
544583
/// # Panics
545584
/// This function panics if the destination doesn't have the same size as
546585
/// the source. This can happen for dynamically-sized types such as slices.
547-
pub fn copy_to_enclave(&self, dest: &mut T) {
586+
pub fn copy_to_enclave<U: ?Sized + UserSafeCopyDestination<T>>(&self, dest: &mut U) {
548587
unsafe {
549588
assert_eq!(size_of_val(dest), size_of_val(&*self.0.get()));
550589
copy_from_userspace(
551590
self.0.get() as *const T as *const u8,
552-
dest as *mut T as *mut u8,
591+
dest.as_mut_ptr() as *mut u8,
553592
size_of_val(dest),
554593
);
555594
}
@@ -639,25 +678,18 @@ where
639678
unsafe { (*self.0.get()).len() }
640679
}
641680

642-
/// Copies the value from user memory and place it into `dest`. Afterwards,
643-
/// `dest` will contain exactly `self.len()` elements.
644-
///
645-
/// # Panics
646-
/// This function panics if the destination doesn't have the same size as
647-
/// the source. This can happen for dynamically-sized types such as slices.
648-
pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
649-
if let Some(missing) = self.len().checked_sub(dest.capacity()) {
650-
dest.reserve(missing)
651-
}
681+
/// Copies the value from user memory and appends it to `dest`.
682+
pub fn append_to_enclave_vec(&self, dest: &mut Vec<T>) {
683+
dest.reserve(self.len());
684+
self.copy_to_enclave(&mut dest.spare_capacity_mut()[..self.len()]);
652685
// SAFETY: We reserve enough space above.
653-
unsafe { dest.set_len(self.len()) };
654-
self.copy_to_enclave(&mut dest[..]);
686+
unsafe { dest.set_len(dest.len() + self.len()) };
655687
}
656688

657689
/// Copies the value from user memory into a vector in enclave memory.
658690
pub fn to_enclave(&self) -> Vec<T> {
659691
let mut ret = Vec::with_capacity(self.len());
660-
self.copy_to_enclave_vec(&mut ret);
692+
self.append_to_enclave_vec(&mut ret);
661693
ret
662694
}
663695

std/src/sys/pal/sgx/abi/usercalls/mod.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::cmp;
2-
use crate::io::{Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult};
2+
use crate::io::{
3+
BorrowedCursor, Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult,
4+
};
35
use crate::random::{DefaultRandomSource, Random};
46
use crate::time::{Duration, Instant};
57

@@ -36,6 +38,19 @@ pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
3638
}
3739
}
3840

41+
/// Usercall `read` with an uninitialized buffer. See the ABI documentation for
42+
/// more information.
43+
#[unstable(feature = "sgx_platform", issue = "56975")]
44+
pub fn read_buf(fd: Fd, mut buf: BorrowedCursor<'_>) -> IoResult<()> {
45+
unsafe {
46+
let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.capacity());
47+
let len = raw::read(fd, userbuf.as_mut_ptr().cast(), userbuf.len()).from_sgx_result()?;
48+
userbuf[..len].copy_to_enclave(&mut buf.as_mut()[..len]);
49+
buf.advance_unchecked(len);
50+
Ok(())
51+
}
52+
}
53+
3954
/// Usercall `read_alloc`. See the ABI documentation for more information.
4055
#[unstable(feature = "sgx_platform", issue = "56975")]
4156
pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {

std/src/sys/pal/sgx/fd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl FileDesc {
2929
}
3030

3131
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
32-
crate::io::default_read_buf(|b| self.read(b), buf)
32+
usercalls::read_buf(self.fd, buf)
3333
}
3434

3535
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {

std/src/sys/stdio/sgx.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use fortanix_sgx_abi as abi;
22

3-
use crate::io;
3+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
44
use crate::sys::fd::FileDesc;
55

66
pub struct Stdin(());
@@ -24,6 +24,19 @@ impl io::Read for Stdin {
2424
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2525
with_std_fd(abi::FD_STDIN, |fd| fd.read(buf))
2626
}
27+
28+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
29+
with_std_fd(abi::FD_STDIN, |fd| fd.read_buf(buf))
30+
}
31+
32+
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
33+
with_std_fd(abi::FD_STDIN, |fd| fd.read_vectored(bufs))
34+
}
35+
36+
#[inline]
37+
fn is_read_vectored(&self) -> bool {
38+
true
39+
}
2740
}
2841

2942
impl Stdout {
@@ -40,6 +53,15 @@ impl io::Write for Stdout {
4053
fn flush(&mut self) -> io::Result<()> {
4154
with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
4255
}
56+
57+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
58+
with_std_fd(abi::FD_STDOUT, |fd| fd.write_vectored(bufs))
59+
}
60+
61+
#[inline]
62+
fn is_write_vectored(&self) -> bool {
63+
true
64+
}
4365
}
4466

4567
impl Stderr {
@@ -56,6 +78,15 @@ impl io::Write for Stderr {
5678
fn flush(&mut self) -> io::Result<()> {
5779
with_std_fd(abi::FD_STDERR, |fd| fd.flush())
5880
}
81+
82+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
83+
with_std_fd(abi::FD_STDERR, |fd| fd.write_vectored(bufs))
84+
}
85+
86+
#[inline]
87+
fn is_write_vectored(&self) -> bool {
88+
true
89+
}
5990
}
6091

6192
pub const STDIN_BUF_SIZE: usize = crate::sys::io::DEFAULT_BUF_SIZE;

0 commit comments

Comments
 (0)