]> git.lizzy.rs Git - rust.git/commitdiff
SGX target: implement streams
authorJethro Beekman <jethro@fortanix.com>
Mon, 17 Sep 2018 23:22:59 +0000 (16:22 -0700)
committerJethro Beekman <jethro@fortanix.com>
Fri, 7 Dec 2018 05:56:51 +0000 (11:26 +0530)
src/libstd/sys/sgx/abi/usercalls/mod.rs
src/libstd/sys/sgx/fd.rs [new file with mode: 0644]
src/libstd/sys/sgx/mod.rs
src/libstd/sys/sgx/stdio.rs

index cf422e3e6aa1d402bbc220c4021db3b179a6290c..b8d739f4d2fa13ef2c1dc176acd9047025d989e7 100644 (file)
 
 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 (file)
index 0000000..31c4199
--- /dev/null
@@ -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)
+    }
+}
index 68f7479d7cd9f60bb7b5af99520978b133455596..dd6862e908e06950224afca1451053a8da18f113 100644 (file)
@@ -27,6 +27,7 @@
 pub mod cmath;
 pub mod condvar;
 pub mod env;
+pub mod fd;
 pub mod fs;
 pub mod memchr;
 pub mod mutex;
index 540599a35964cb2e33ddf48339f7e8f309f2ae8a..13c9119556929eedc08b62f9bc94bfb7a02a8951 100644 (file)
@@ -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> {