about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorJethro Beekman <jethro@fortanix.com>2018-12-25 13:11:04 +0530
committerJethro Beekman <jethro@fortanix.com>2018-12-25 13:11:04 +0530
commitbe565615dbed87a0d3fcdb7f62b2080b3dc288fa (patch)
treefd49ea1e8e61dc68a7e081caf509021cbdff0c31 /src/libstd/sys
parent505167d7c58f68170118f96436c85e0587e6d3f5 (diff)
downloadrust-be565615dbed87a0d3fcdb7f62b2080b3dc288fa.tar.gz
rust-be565615dbed87a0d3fcdb7f62b2080b3dc288fa.zip
Add `io` and `arch` modules to `std::os::fortanix_sgx`
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/sgx/ext/arch.rs84
-rw-r--r--src/libstd/sys/sgx/ext/io.rs119
-rw-r--r--src/libstd/sys/sgx/ext/mod.rs14
-rw-r--r--src/libstd/sys/sgx/fd.rs16
-rw-r--r--src/libstd/sys/sgx/mod.rs7
-rw-r--r--src/libstd/sys/sgx/net.rs73
6 files changed, 303 insertions, 10 deletions
diff --git a/src/libstd/sys/sgx/ext/arch.rs b/src/libstd/sys/sgx/ext/arch.rs
new file mode 100644
index 00000000000..377210f5d69
--- /dev/null
+++ b/src/libstd/sys/sgx/ext/arch.rs
@@ -0,0 +1,84 @@
+// Copyright 2018 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.
+
+//! SGX-specific access to architectural features.
+//!
+//! The functionality in this module is further documented in the Intel
+//! Software Developer's Manual, Volume 3, Chapter 40.
+#![unstable(feature = "sgx_platform", issue = "56975")]
+
+use mem::MaybeUninit;
+
+/// Wrapper struct to force 16-byte alignment.
+#[repr(align(16))]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct Align16<T>(pub T);
+
+/// Wrapper struct to force 128-byte alignment.
+#[repr(align(128))]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct Align128<T>(pub T);
+
+/// Wrapper struct to force 512-byte alignment.
+#[repr(align(512))]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct Align512<T>(pub T);
+
+const ENCLU_EREPORT: u32 = 0;
+const ENCLU_EGETKEY: u32 = 1;
+
+/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
+    unsafe {
+        let mut out = MaybeUninit::uninitialized();
+        let error;
+
+        asm!(
+            "enclu"
+            : "={eax}"(error)
+            : "{eax}"(ENCLU_EGETKEY),
+              "{rbx}"(request),
+              "{rcx}"(out.get_mut())
+            : "flags"
+        );
+
+        match error {
+            0 => Ok(out.into_inner()),
+            err => Err(err),
+        }
+    }
+}
+
+/// Call the `EREPORT` instruction.
+///
+/// This creates a cryptographic report describing the contents of the current
+/// enclave. The report may be verified by the enclave described in
+/// `targetinfo`.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub fn ereport(
+    targetinfo: &Align512<[u8; 512]>,
+    reportdata: &Align128<[u8; 64]>,
+) -> Align512<[u8; 432]> {
+    unsafe {
+        let mut report = MaybeUninit::uninitialized();
+
+        asm!(
+            "enclu"
+            : /* no output registers */
+            : "{eax}"(ENCLU_EREPORT),
+              "{rbx}"(targetinfo),
+              "{rcx}"(reportdata),
+              "{rdx}"(report.get_mut())
+        );
+
+        report.into_inner()
+    }
+}
diff --git a/src/libstd/sys/sgx/ext/io.rs b/src/libstd/sys/sgx/ext/io.rs
new file mode 100644
index 00000000000..55cc4c9ba1f
--- /dev/null
+++ b/src/libstd/sys/sgx/ext/io.rs
@@ -0,0 +1,119 @@
+// Copyright 2018 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.
+
+//! SGX-specific extensions to general I/O primitives
+//!
+//! SGX file descriptors behave differently from Unix file descriptors. See the
+//! description of [`TryIntoRawFd`](trait.TryIntoRawFd.html) for more details.
+#![unstable(feature = "sgx_platform", issue = "56975")]
+
+pub use sys::abi::usercalls::raw::Fd as RawFd;
+use net;
+use sys::{self, AsInner, FromInner, IntoInner, TryIntoInner};
+
+/// A trait to extract the raw SGX file descriptor from an underlying
+/// object.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait AsRawFd {
+    /// Extracts the raw file descriptor.
+    ///
+    /// This method does **not** pass ownership of the raw file descriptor
+    /// to the caller. The descriptor is only guaranteed to be valid while
+    /// the original object has not yet been destroyed.
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait FromRawFd {
+    /// Constructs a new instance of `Self` from the given raw file
+    /// descriptor.
+    ///
+    /// This function **consumes ownership** of the specified file
+    /// descriptor. The returned object will take responsibility for closing
+    /// it when the object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait TryIntoRawFd: Sized {
+    /// Consumes this object, returning the raw underlying file descriptor, if
+    /// this object is not cloned.
+    ///
+    /// This function **transfers ownership** of the underlying file descriptor
+    /// to the caller. Callers are then the unique owners of the file descriptor
+    /// and must close the descriptor once it's no longer needed.
+    ///
+    /// Unlike other platforms, on SGX, the file descriptor is shared between
+    /// all clones of an object. To avoid race conditions, this function will
+    /// only return `Ok` when called on the final clone.
+    #[unstable(feature = "sgx_platform", issue = "56975")]
+    fn try_into_raw_fd(self) -> Result<RawFd, Self>;
+}
+
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() }
+}
+
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() }
+}
+
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let fd = sys::fd::FileDesc::from_inner(fd);
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, None)))
+    }
+}
+
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let fd = sys::fd::FileDesc::from_inner(fd);
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket))
+    }
+}
+
+impl TryIntoRawFd for net::TcpStream {
+    fn try_into_raw_fd(self) -> Result<RawFd, Self> {
+        let (socket, peer_addr) = self.into_inner().into_inner();
+        match socket.try_into_inner() {
+            Ok(fd) => Ok(fd.into_inner()),
+            Err(socket) => {
+                let sys = sys::net::TcpStream::from_inner((socket, peer_addr));
+                Err(net::TcpStream::from_inner(sys))
+            }
+        }
+    }
+}
+
+impl TryIntoRawFd for net::TcpListener {
+    fn try_into_raw_fd(self) -> Result<RawFd, Self> {
+        match self.into_inner().into_inner().try_into_inner() {
+            Ok(fd) => Ok(fd.into_inner()),
+            Err(socket) => {
+                let sys = sys::net::TcpListener::from_inner(socket);
+                Err(net::TcpListener::from_inner(sys))
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/sgx/ext/mod.rs b/src/libstd/sys/sgx/ext/mod.rs
new file mode 100644
index 00000000000..8e505a23c42
--- /dev/null
+++ b/src/libstd/sys/sgx/ext/mod.rs
@@ -0,0 +1,14 @@
+// Copyright 2018 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.
+
+#![unstable(feature = "sgx_platform", issue = "56975")]
+
+pub mod arch;
+pub mod io;
diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs
index 31c4199c6cd..1f7024b2c46 100644
--- a/src/libstd/sys/sgx/fd.rs
+++ b/src/libstd/sys/sgx/fd.rs
@@ -12,7 +12,7 @@ use fortanix_sgx_abi::Fd;
 
 use io;
 use mem;
-use sys_common::AsInner;
+use sys::{AsInner, FromInner, IntoInner};
 use super::abi::usercalls;
 
 #[derive(Debug)]
@@ -51,6 +51,20 @@ impl AsInner<Fd> for FileDesc {
     fn as_inner(&self) -> &Fd { &self.fd }
 }
 
+impl IntoInner<Fd> for FileDesc {
+    fn into_inner(self) -> Fd {
+        let fd = self.fd;
+        mem::forget(self);
+        fd
+    }
+}
+
+impl FromInner<Fd> for FileDesc {
+    fn from_inner(fd: Fd) -> FileDesc {
+        FileDesc { 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 dd6862e908e..f2b569e1766 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 ext;
 pub mod fd;
 pub mod fs;
 pub mod memchr;
@@ -151,3 +152,9 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     }
     (rdrand64(), rdrand64())
 }
+
+pub use sys_common::{AsInner, FromInner, IntoInner};
+
+pub trait TryIntoInner<Inner>: Sized {
+    fn try_into_inner(self) -> Result<Inner, Self>;
+}
diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs
index 9cfe821fe51..bb33a8aca79 100644
--- a/src/libstd/sys/sgx/net.rs
+++ b/src/libstd/sys/sgx/net.rs
@@ -12,7 +12,7 @@ use fmt;
 use io;
 use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
 use time::Duration;
-use sys::{unsupported, Void, sgx_ineffective};
+use sys::{unsupported, Void, sgx_ineffective, AsInner, FromInner, IntoInner, TryIntoInner};
 use sys::fd::FileDesc;
 use convert::TryFrom;
 use error;
@@ -23,21 +23,38 @@ use super::abi::usercalls;
 const DEFAULT_FAKE_TTL: u32 = 64;
 
 #[derive(Debug, Clone)]
-struct Socket {
+pub struct Socket {
     inner: Arc<FileDesc>,
-    local_addr: String,
+    local_addr: Option<String>,
 }
 
 impl Socket {
     fn new(fd: usercalls::raw::Fd, local_addr: String) -> Socket {
-        Socket { inner: Arc::new(FileDesc::new(fd)), local_addr }
+        Socket { inner: Arc::new(FileDesc::new(fd)), local_addr: Some(local_addr) }
+    }
+}
+
+impl AsInner<FileDesc> for Socket {
+    fn as_inner(&self) -> &FileDesc { &self.inner }
+}
+
+impl TryIntoInner<FileDesc> for Socket {
+    fn try_into_inner(self) -> Result<FileDesc, Socket> {
+        let Socket { inner, local_addr } = self;
+        Arc::try_unwrap(inner).map_err(|inner| Socket { inner, local_addr } )
+    }
+}
+
+impl FromInner<FileDesc> for Socket {
+    fn from_inner(inner: FileDesc) -> Socket {
+        Socket { inner: Arc::new(inner), local_addr: None }
     }
 }
 
 #[derive(Debug, Clone)]
 pub struct TcpStream {
     inner: Socket,
-    peer_addr: String,
+    peer_addr: Option<String>,
 }
 
 fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
@@ -53,16 +70,19 @@ fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
     }
 }
 
-fn addr_to_sockaddr(addr: &str) -> io::Result<SocketAddr> {
-    // unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry
-    addr.to_socket_addrs().map(|mut it| it.next().unwrap())
+fn addr_to_sockaddr(addr: &Option<String>) -> io::Result<SocketAddr> {
+    addr.as_ref()
+        .ok_or(io::ErrorKind::AddrNotAvailable)?
+        .to_socket_addrs()
+        // unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry
+        .map(|mut it| it.next().unwrap())
 }
 
 impl TcpStream {
     pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
         let addr = io_err_to_addr(addr)?;
         let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?;
-        Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr })
+        Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
     }
 
     pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
@@ -138,6 +158,24 @@ impl TcpStream {
     }
 }
 
+impl AsInner<Socket> for TcpStream {
+    fn as_inner(&self) -> &Socket { &self.inner }
+}
+
+// `Inner` includes `peer_addr` so that a `TcpStream` maybe correctly
+// reconstructed if `Socket::try_into_inner` fails.
+impl IntoInner<(Socket, Option<String>)> for TcpStream {
+    fn into_inner(self) -> (Socket, Option<String>) {
+        (self.inner, self.peer_addr)
+    }
+}
+
+impl FromInner<(Socket, Option<String>)> for TcpStream {
+    fn from_inner((inner, peer_addr): (Socket, Option<String>)) -> TcpStream {
+        TcpStream { inner, peer_addr }
+    }
+}
+
 #[derive(Debug, Clone)]
 pub struct TcpListener {
     inner: Socket,
@@ -156,6 +194,7 @@ impl TcpListener {
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
         let (fd, local_addr, peer_addr) = usercalls::accept_stream(self.inner.inner.raw())?;
+        let peer_addr = Some(peer_addr);
         let ret_peer = addr_to_sockaddr(&peer_addr).unwrap_or_else(|_| ([0; 4], 0).into());
         Ok((TcpStream { inner: Socket::new(fd, local_addr), peer_addr }, ret_peer))
     }
@@ -189,6 +228,22 @@ impl TcpListener {
     }
 }
 
+impl AsInner<Socket> for TcpListener {
+    fn as_inner(&self) -> &Socket { &self.inner }
+}
+
+impl IntoInner<Socket> for TcpListener {
+    fn into_inner(self) -> Socket {
+        self.inner
+    }
+}
+
+impl FromInner<Socket> for TcpListener {
+    fn from_inner(inner: Socket) -> TcpListener {
+        TcpListener { inner }
+    }
+}
+
 pub struct UdpSocket(Void);
 
 impl UdpSocket {