Skip to content

Commit d298697

Browse files
committed
Auto merge of #57119 - jethrogb:jb/sgx-os-mod2, r=joshtriplett
Add `io` and `arch` modules to `std::os::fortanix_sgx` This PR adds two more (unstable) modules to `std::os::fortanix_sgx` for the `x86_64-fortanix-unknown-sgx` target. ### io `io` allows conversion between raw file descriptors and Rust types, similar to `std::os::unix::io`. ### arch `arch` exposes the `ENCLU[EREPORT]` and `ENCLU[EGETKEY]` instructions. The current functions are very likely not going to be the final form of these functions (see also fortanix/rust-sgx#15), but this should be sufficient to enable experimentation in libraries. I tried using the actual types (from the [`sgx-isa` crate](https://crates.io/crates/sgx-isa)) instead of byte arrays, but that would make `std` dependent on the `bitflags` crate which I didn't want to do at this time.
2 parents 39bc8f5 + be56561 commit d298697

File tree

8 files changed

+307
-11
lines changed

8 files changed

+307
-11
lines changed

src/libstd/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@
304304
#![feature(alloc_layout_extra)]
305305
#![feature(maybe_uninit)]
306306
#![cfg_attr(target_env = "sgx", feature(global_asm, range_contains, slice_index_methods,
307-
decl_macro, coerce_unsized, sgx_platform))]
307+
decl_macro, coerce_unsized, sgx_platform,
308+
min_const_unsafe_fn))]
308309

309310
#![default_lib_allocator]
310311

src/libstd/os/fortanix_sgx/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@ pub mod usercalls {
5555
pub mod mem {
5656
pub use sys::abi::mem::*;
5757
}
58+
59+
pub use sys::ext::{io, arch};

src/libstd/sys/sgx/ext/arch.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! SGX-specific access to architectural features.
12+
//!
13+
//! The functionality in this module is further documented in the Intel
14+
//! Software Developer's Manual, Volume 3, Chapter 40.
15+
#![unstable(feature = "sgx_platform", issue = "56975")]
16+
17+
use mem::MaybeUninit;
18+
19+
/// Wrapper struct to force 16-byte alignment.
20+
#[repr(align(16))]
21+
#[unstable(feature = "sgx_platform", issue = "56975")]
22+
pub struct Align16<T>(pub T);
23+
24+
/// Wrapper struct to force 128-byte alignment.
25+
#[repr(align(128))]
26+
#[unstable(feature = "sgx_platform", issue = "56975")]
27+
pub struct Align128<T>(pub T);
28+
29+
/// Wrapper struct to force 512-byte alignment.
30+
#[repr(align(512))]
31+
#[unstable(feature = "sgx_platform", issue = "56975")]
32+
pub struct Align512<T>(pub T);
33+
34+
const ENCLU_EREPORT: u32 = 0;
35+
const ENCLU_EGETKEY: u32 = 1;
36+
37+
/// Call the `EGETKEY` instruction to obtain a 128-bit secret key.
38+
#[unstable(feature = "sgx_platform", issue = "56975")]
39+
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
40+
unsafe {
41+
let mut out = MaybeUninit::uninitialized();
42+
let error;
43+
44+
asm!(
45+
"enclu"
46+
: "={eax}"(error)
47+
: "{eax}"(ENCLU_EGETKEY),
48+
"{rbx}"(request),
49+
"{rcx}"(out.get_mut())
50+
: "flags"
51+
);
52+
53+
match error {
54+
0 => Ok(out.into_inner()),
55+
err => Err(err),
56+
}
57+
}
58+
}
59+
60+
/// Call the `EREPORT` instruction.
61+
///
62+
/// This creates a cryptographic report describing the contents of the current
63+
/// enclave. The report may be verified by the enclave described in
64+
/// `targetinfo`.
65+
#[unstable(feature = "sgx_platform", issue = "56975")]
66+
pub fn ereport(
67+
targetinfo: &Align512<[u8; 512]>,
68+
reportdata: &Align128<[u8; 64]>,
69+
) -> Align512<[u8; 432]> {
70+
unsafe {
71+
let mut report = MaybeUninit::uninitialized();
72+
73+
asm!(
74+
"enclu"
75+
: /* no output registers */
76+
: "{eax}"(ENCLU_EREPORT),
77+
"{rbx}"(targetinfo),
78+
"{rcx}"(reportdata),
79+
"{rdx}"(report.get_mut())
80+
);
81+
82+
report.into_inner()
83+
}
84+
}

src/libstd/sys/sgx/ext/io.rs

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! SGX-specific extensions to general I/O primitives
12+
//!
13+
//! SGX file descriptors behave differently from Unix file descriptors. See the
14+
//! description of [`TryIntoRawFd`](trait.TryIntoRawFd.html) for more details.
15+
#![unstable(feature = "sgx_platform", issue = "56975")]
16+
17+
pub use sys::abi::usercalls::raw::Fd as RawFd;
18+
use net;
19+
use sys::{self, AsInner, FromInner, IntoInner, TryIntoInner};
20+
21+
/// A trait to extract the raw SGX file descriptor from an underlying
22+
/// object.
23+
#[unstable(feature = "sgx_platform", issue = "56975")]
24+
pub trait AsRawFd {
25+
/// Extracts the raw file descriptor.
26+
///
27+
/// This method does **not** pass ownership of the raw file descriptor
28+
/// to the caller. The descriptor is only guaranteed to be valid while
29+
/// the original object has not yet been destroyed.
30+
#[unstable(feature = "sgx_platform", issue = "56975")]
31+
fn as_raw_fd(&self) -> RawFd;
32+
}
33+
34+
/// A trait to express the ability to construct an object from a raw file
35+
/// descriptor.
36+
#[unstable(feature = "sgx_platform", issue = "56975")]
37+
pub trait FromRawFd {
38+
/// Constructs a new instance of `Self` from the given raw file
39+
/// descriptor.
40+
///
41+
/// This function **consumes ownership** of the specified file
42+
/// descriptor. The returned object will take responsibility for closing
43+
/// it when the object goes out of scope.
44+
///
45+
/// This function is also unsafe as the primitives currently returned
46+
/// have the contract that they are the sole owner of the file
47+
/// descriptor they are wrapping. Usage of this function could
48+
/// accidentally allow violating this contract which can cause memory
49+
/// unsafety in code that relies on it being true.
50+
#[unstable(feature = "sgx_platform", issue = "56975")]
51+
unsafe fn from_raw_fd(fd: RawFd) -> Self;
52+
}
53+
54+
/// A trait to express the ability to consume an object and acquire ownership of
55+
/// its raw file descriptor.
56+
#[unstable(feature = "sgx_platform", issue = "56975")]
57+
pub trait TryIntoRawFd: Sized {
58+
/// Consumes this object, returning the raw underlying file descriptor, if
59+
/// this object is not cloned.
60+
///
61+
/// This function **transfers ownership** of the underlying file descriptor
62+
/// to the caller. Callers are then the unique owners of the file descriptor
63+
/// and must close the descriptor once it's no longer needed.
64+
///
65+
/// Unlike other platforms, on SGX, the file descriptor is shared between
66+
/// all clones of an object. To avoid race conditions, this function will
67+
/// only return `Ok` when called on the final clone.
68+
#[unstable(feature = "sgx_platform", issue = "56975")]
69+
fn try_into_raw_fd(self) -> Result<RawFd, Self>;
70+
}
71+
72+
impl AsRawFd for net::TcpStream {
73+
fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() }
74+
}
75+
76+
impl AsRawFd for net::TcpListener {
77+
fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() }
78+
}
79+
80+
impl FromRawFd for net::TcpStream {
81+
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
82+
let fd = sys::fd::FileDesc::from_inner(fd);
83+
let socket = sys::net::Socket::from_inner(fd);
84+
net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, None)))
85+
}
86+
}
87+
88+
impl FromRawFd for net::TcpListener {
89+
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
90+
let fd = sys::fd::FileDesc::from_inner(fd);
91+
let socket = sys::net::Socket::from_inner(fd);
92+
net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket))
93+
}
94+
}
95+
96+
impl TryIntoRawFd for net::TcpStream {
97+
fn try_into_raw_fd(self) -> Result<RawFd, Self> {
98+
let (socket, peer_addr) = self.into_inner().into_inner();
99+
match socket.try_into_inner() {
100+
Ok(fd) => Ok(fd.into_inner()),
101+
Err(socket) => {
102+
let sys = sys::net::TcpStream::from_inner((socket, peer_addr));
103+
Err(net::TcpStream::from_inner(sys))
104+
}
105+
}
106+
}
107+
}
108+
109+
impl TryIntoRawFd for net::TcpListener {
110+
fn try_into_raw_fd(self) -> Result<RawFd, Self> {
111+
match self.into_inner().into_inner().try_into_inner() {
112+
Ok(fd) => Ok(fd.into_inner()),
113+
Err(socket) => {
114+
let sys = sys::net::TcpListener::from_inner(socket);
115+
Err(net::TcpListener::from_inner(sys))
116+
}
117+
}
118+
}
119+
}

src/libstd/sys/sgx/ext/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![unstable(feature = "sgx_platform", issue = "56975")]
12+
13+
pub mod arch;
14+
pub mod io;

src/libstd/sys/sgx/fd.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use fortanix_sgx_abi::Fd;
22

33
use io;
44
use mem;
5-
use sys_common::AsInner;
5+
use sys::{AsInner, FromInner, IntoInner};
66
use super::abi::usercalls;
77

88
#[derive(Debug)]
@@ -41,6 +41,20 @@ impl AsInner<Fd> for FileDesc {
4141
fn as_inner(&self) -> &Fd { &self.fd }
4242
}
4343

44+
impl IntoInner<Fd> for FileDesc {
45+
fn into_inner(self) -> Fd {
46+
let fd = self.fd;
47+
mem::forget(self);
48+
fd
49+
}
50+
}
51+
52+
impl FromInner<Fd> for FileDesc {
53+
fn from_inner(fd: Fd) -> FileDesc {
54+
FileDesc { fd }
55+
}
56+
}
57+
4458
impl Drop for FileDesc {
4559
fn drop(&mut self) {
4660
usercalls::close(self.fd)

src/libstd/sys/sgx/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod backtrace;
1717
pub mod cmath;
1818
pub mod condvar;
1919
pub mod env;
20+
pub mod ext;
2021
pub mod fd;
2122
pub mod fs;
2223
pub mod memchr;
@@ -141,3 +142,9 @@ pub fn hashmap_random_keys() -> (u64, u64) {
141142
}
142143
(rdrand64(), rdrand64())
143144
}
145+
146+
pub use sys_common::{AsInner, FromInner, IntoInner};
147+
148+
pub trait TryIntoInner<Inner>: Sized {
149+
fn try_into_inner(self) -> Result<Inner, Self>;
150+
}

0 commit comments

Comments
 (0)