about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJethro Beekman <jethro@fortanix.com>2018-09-17 16:22:59 -0700
committerJethro Beekman <jethro@fortanix.com>2018-12-07 11:26:51 +0530
commit1a894f135e972c30e79b4d7f836d69dbe49e7ead (patch)
treea4ce9e705c1fd543c12f5726bc01a3a74e35e810
parent8d6edc9f8f71075c55fad3c5ca5a7e28b5e01400 (diff)
downloadrust-1a894f135e972c30e79b4d7f836d69dbe49e7ead.tar.gz
rust-1a894f135e972c30e79b4d7f836d69dbe49e7ead.zip
SGX target: implement streams
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/mod.rs41
-rw-r--r--src/libstd/sys/sgx/fd.rs58
-rw-r--r--src/libstd/sys/sgx/mod.rs1
-rw-r--r--src/libstd/sys/sgx/stdio.rs62
4 files changed, 134 insertions, 28 deletions
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index cf422e3e6aa..b8d739f4d2f 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -12,10 +12,49 @@ pub use fortanix_sgx_abi::*;
 
 use io::{Error as IoError, Result as IoResult};
 
-mod alloc;
+pub mod alloc;
 #[macro_use]
 mod raw;
 
+pub(crate) fn copy_user_buffer(buf: &alloc::UserRef<ByteBuffer>) -> Vec<u8> {
+    unsafe {
+        let buf = buf.to_enclave();
+        alloc::User::from_raw_parts(buf.data as _, buf.len).to_enclave()
+    }
+}
+
+pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
+    unsafe {
+        let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
+        let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
+        userbuf[..len].copy_to_enclave(&mut buf[..len]);
+        Ok(len)
+    }
+}
+
+pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
+    unsafe {
+        let mut userbuf = alloc::User::<ByteBuffer>::uninitialized();
+        raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
+        Ok(copy_user_buffer(&userbuf))
+    }
+}
+
+pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
+    unsafe {
+        let userbuf = alloc::User::new_from_enclave(buf);
+        raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
+    }
+}
+
+pub fn flush(fd: Fd) -> IoResult<()> {
+    unsafe { raw::flush(fd).from_sgx_result() }
+}
+
+pub fn close(fd: Fd) {
+    unsafe { raw::close(fd) }
+}
+
 pub fn launch_thread() -> IoResult<()> {
     unsafe { raw::launch_thread().from_sgx_result() }
 }
diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs
new file mode 100644
index 00000000000..31c4199c6cd
--- /dev/null
+++ b/src/libstd/sys/sgx/fd.rs
@@ -0,0 +1,58 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fortanix_sgx_abi::Fd;
+
+use io;
+use mem;
+use sys_common::AsInner;
+use super::abi::usercalls;
+
+#[derive(Debug)]
+pub struct FileDesc {
+    fd: Fd,
+}
+
+impl FileDesc {
+    pub fn new(fd: Fd) -> FileDesc {
+        FileDesc { fd: fd }
+    }
+
+    pub fn raw(&self) -> Fd { self.fd }
+
+    /// Extracts the actual filedescriptor without closing it.
+    pub fn into_raw(self) -> Fd {
+        let fd = self.fd;
+        mem::forget(self);
+        fd
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        usercalls::read(self.fd, buf)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        usercalls::write(self.fd, buf)
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        usercalls::flush(self.fd)
+    }
+}
+
+impl AsInner<Fd> for FileDesc {
+    fn as_inner(&self) -> &Fd { &self.fd }
+}
+
+impl Drop for FileDesc {
+    fn drop(&mut self) {
+        usercalls::close(self.fd)
+    }
+}
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index 68f7479d7cd..dd6862e908e 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -27,6 +27,7 @@ pub mod backtrace;
 pub mod cmath;
 pub mod condvar;
 pub mod env;
+pub mod fd;
 pub mod fs;
 pub mod memchr;
 pub mod mutex;
diff --git a/src/libstd/sys/sgx/stdio.rs b/src/libstd/sys/sgx/stdio.rs
index 540599a3596..13c91195569 100644
--- a/src/libstd/sys/sgx/stdio.rs
+++ b/src/libstd/sys/sgx/stdio.rs
@@ -1,4 +1,4 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,64 +8,72 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use fortanix_sgx_abi as abi;
+
 use io;
-use sys::unsupported;
+use sys::fd::FileDesc;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
 
-pub struct Stdin;
-pub struct Stdout;
-pub struct Stderr;
+fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
+    let fd = FileDesc::new(fd);
+    let ret = f(&fd);
+    fd.into_raw();
+    ret
+}
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
-    }
+    pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
 
-    pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
-        unsupported()
+    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDIN, |fd| fd.read(data))
     }
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
-    }
+    pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
 
-    pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
-        unsupported()
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDOUT, |fd| fd.write(data))
     }
 
     pub fn flush(&self) -> io::Result<()> {
-        Ok(())
+        with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
     }
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
-    }
+    pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
 
-    pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
-        unsupported()
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        with_std_fd(abi::FD_STDERR, |fd| fd.write(data))
     }
 
     pub fn flush(&self) -> io::Result<()> {
-        Ok(())
+        with_std_fd(abi::FD_STDERR, |fd| fd.flush())
     }
 }
 
+// FIXME: right now this raw stderr handle is used in a few places because
+//        std::io::stderr_raw isn't exposed, but once that's exposed this impl
+//        should go away
 impl io::Write for Stderr {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-        (&*self).write(data)
+        Stderr::write(self, data)
     }
+
     fn flush(&mut self) -> io::Result<()> {
-        (&*self).flush()
+        Stderr::flush(self)
     }
 }
 
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
 
-pub fn is_ebadf(_err: &io::Error) -> bool {
-    true
+pub fn is_ebadf(err: &io::Error) -> bool {
+    // FIXME: Rust normally maps Unix EBADF to `Other`
+    err.raw_os_error() == Some(abi::Error::BrokenPipe as _)
 }
 
 pub fn panic_output() -> Option<impl io::Write> {