Skip to content

Commit c77e370

Browse files
committed
Provide read_buf and vectored read/write for SGX stdio
1 parent bb09262 commit c77e370

File tree

4 files changed

+99
-13
lines changed

4 files changed

+99
-13
lines changed

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

+18-2
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};
@@ -651,13 +651,29 @@ where
651651
/// the source. This can happen for dynamically-sized types such as slices.
652652
pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
653653
if let Some(missing) = self.len().checked_sub(dest.capacity()) {
654-
dest.reserve(missing)
654+
dest.reserve(missing);
655655
}
656656
// SAFETY: We reserve enough space above.
657657
unsafe { dest.set_len(self.len()) };
658658
self.copy_to_enclave(&mut dest[..]);
659659
}
660660

661+
/// Copies the value from user memory and place it into `dest`.
662+
///
663+
/// # Panics
664+
/// This function panics if the destination doesn't have the same length as
665+
/// the source.
666+
pub fn copy_to_enclave_uninit(&self, dest: &mut [MaybeUninit<T>]) {
667+
unsafe {
668+
assert_eq!(self.len(), dest.len());
669+
copy_from_userspace(
670+
self.0.get() as *const [T] as *const u8,
671+
dest.as_mut_ptr() as *mut u8,
672+
mem::size_of_val(dest),
673+
);
674+
}
675+
}
676+
661677
/// Copies the value from user memory into a vector in enclave memory.
662678
pub fn to_enclave(&self) -> Vec<T> {
663679
let mut ret = Vec::with_capacity(self.len());

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

+39-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::cmp;
22
use crate::io::{Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult};
3+
use crate::mem::MaybeUninit;
34
use crate::random::{DefaultRandomSource, Random};
45
use crate::time::{Duration, Instant};
56

@@ -12,11 +13,35 @@ mod tests;
1213
use self::raw::*;
1314

1415
/// Usercall `read`. See the ABI documentation for more information.
16+
#[unstable(feature = "sgx_platform", issue = "56975")]
17+
pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
18+
unsafe {
19+
let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
20+
let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
21+
userbuf[..len].copy_to_enclave(&mut buf[..len]);
22+
Ok(len)
23+
}
24+
}
25+
26+
/// Usercall `read` with an uninitialized buffer. See the ABI documentation for
27+
/// more information.
28+
#[unstable(feature = "sgx_platform", issue = "56975")]
29+
pub fn read_uninit(fd: Fd, buf: &mut [MaybeUninit<u8>]) -> IoResult<usize> {
30+
unsafe {
31+
let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
32+
let len = raw::read(fd, userbuf.as_mut_ptr().cast(), userbuf.len()).from_sgx_result()?;
33+
userbuf[..len].copy_to_enclave_uninit(&mut buf[..len]);
34+
Ok(len)
35+
}
36+
}
37+
38+
/// Usercall `read` with a slice of buffers. See the ABI documentation for more
39+
/// information.
1540
///
1641
/// This will do a single `read` usercall and scatter the read data among
17-
/// `bufs`. To read to a single buffer, just pass a slice of length one.
42+
/// `bufs`.
1843
#[unstable(feature = "sgx_platform", issue = "56975")]
19-
pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
44+
pub fn read_vectored(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
2045
unsafe {
2146
let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
2247
let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
@@ -48,11 +73,21 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
4873
}
4974

5075
/// Usercall `write`. See the ABI documentation for more information.
76+
#[unstable(feature = "sgx_platform", issue = "56975")]
77+
pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
78+
unsafe {
79+
let userbuf = alloc::User::new_from_enclave(buf);
80+
raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
81+
}
82+
}
83+
84+
/// Usercall `write` with a slice of buffers. See the ABI documentation for more
85+
/// information.
5186
///
5287
/// This will do a single `write` usercall and gather the written data from
53-
/// `bufs`. To write from a single buffer, just pass a slice of length one.
88+
/// `bufs`.
5489
#[unstable(feature = "sgx_platform", issue = "56975")]
55-
pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
90+
pub fn write_vectored(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
5691
unsafe {
5792
let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
5893
let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);

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

+10-6
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,19 @@ impl FileDesc {
2525
}
2626

2727
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
28-
usercalls::read(self.fd, &mut [IoSliceMut::new(buf)])
28+
usercalls::read(self.fd, buf)
2929
}
3030

31-
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
32-
crate::io::default_read_buf(|b| self.read(b), buf)
31+
pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> {
32+
unsafe {
33+
let len = usercalls::read_uninit(self.fd, buf.as_mut())?;
34+
buf.advance_unchecked(len);
35+
Ok(())
36+
}
3337
}
3438

3539
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
36-
usercalls::read(self.fd, bufs)
40+
usercalls::read_vectored(self.fd, bufs)
3741
}
3842

3943
#[inline]
@@ -42,11 +46,11 @@ impl FileDesc {
4246
}
4347

4448
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
45-
usercalls::write(self.fd, &[IoSlice::new(buf)])
49+
usercalls::write(self.fd, buf)
4650
}
4751

4852
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
49-
usercalls::write(self.fd, bufs)
53+
usercalls::write_vectored(self.fd, bufs)
5054
}
5155

5256
#[inline]

library/std/src/sys/pal/sgx/stdio.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
#[cfg(not(test))]
55
use crate::slice;
66
#[cfg(not(test))]
@@ -28,6 +28,19 @@ impl io::Read for Stdin {
2828
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2929
with_std_fd(abi::FD_STDIN, |fd| fd.read(buf))
3030
}
31+
32+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
33+
with_std_fd(abi::FD_STDIN, |fd| fd.read_buf(buf))
34+
}
35+
36+
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
37+
with_std_fd(abi::FD_STDIN, |fd| fd.read_vectored(bufs))
38+
}
39+
40+
#[inline]
41+
fn is_read_vectored(&self) -> bool {
42+
true
43+
}
3144
}
3245

3346
impl Stdout {
@@ -44,6 +57,15 @@ impl io::Write for Stdout {
4457
fn flush(&mut self) -> io::Result<()> {
4558
with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
4659
}
60+
61+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
62+
with_std_fd(abi::FD_STDOUT, |fd| fd.write_vectored(bufs))
63+
}
64+
65+
#[inline]
66+
fn is_write_vectored(&self) -> bool {
67+
true
68+
}
4769
}
4870

4971
impl Stderr {
@@ -60,6 +82,15 @@ impl io::Write for Stderr {
6082
fn flush(&mut self) -> io::Result<()> {
6183
with_std_fd(abi::FD_STDERR, |fd| fd.flush())
6284
}
85+
86+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
87+
with_std_fd(abi::FD_STDERR, |fd| fd.write_vectored(bufs))
88+
}
89+
90+
#[inline]
91+
fn is_write_vectored(&self) -> bool {
92+
true
93+
}
6394
}
6495

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

0 commit comments

Comments
 (0)