xref: /drstd/src/std/sys/sgx/mod.rs (revision 9670759b785600bf6315e4173e46a602f16add7a)
1 //! System bindings for the Fortanix SGX platform
2 //!
3 //! This module contains the facade (aka platform-specific) implementations of
4 //! OS level functionality for Fortanix SGX.
5 #![deny(unsafe_op_in_unsafe_fn)]
6 #![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers
7 
8 use crate::std::io::ErrorKind;
9 use crate::std::sync::atomic::{AtomicBool, Ordering};
10 
11 pub mod abi;
12 mod waitqueue;
13 
14 pub mod alloc;
15 pub mod args;
16 #[path = "../unix/cmath.rs"]
17 pub mod cmath;
18 pub mod env;
19 pub mod fd;
20 #[path = "../unsupported/fs.rs"]
21 pub mod fs;
22 #[path = "../unsupported/io.rs"]
23 pub mod io;
24 pub mod memchr;
25 pub mod net;
26 pub mod os;
27 #[path = "../unix/os_str.rs"]
28 pub mod os_str;
29 pub mod path;
30 #[path = "../unsupported/pipe.rs"]
31 pub mod pipe;
32 #[path = "../unsupported/process.rs"]
33 pub mod process;
34 pub mod stdio;
35 pub mod thread;
36 pub mod thread_local_key;
37 pub mod thread_parking;
38 pub mod time;
39 
40 mod condvar;
41 mod mutex;
42 mod rwlock;
43 
44 pub mod locks {
45     pub use super::condvar::*;
46     pub use super::mutex::*;
47     pub use super::rwlock::*;
48 }
49 
50 // SAFETY: must be called only once during runtime initialization.
51 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
init(argc: isize, argv: *const *const u8, _sigpipe: u8)52 pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
53     unsafe {
54         args::init(argc, argv);
55     }
56 }
57 
58 // SAFETY: must be called only once during runtime cleanup.
59 // NOTE: this is not guaranteed to run, for example when the program aborts.
cleanup()60 pub unsafe fn cleanup() {}
61 
62 /// This function is used to implement functionality that simply doesn't exist.
63 /// Programs relying on this functionality will need to deal with the error.
unsupported<T>() -> crate::std::io::Result<T>64 pub fn unsupported<T>() -> crate::std::io::Result<T> {
65     Err(unsupported_err())
66 }
67 
unsupported_err() -> crate::std::io::Error68 pub fn unsupported_err() -> crate::std::io::Error {
69     crate::std::io::const_io_error!(ErrorKind::Unsupported, "operation not supported on SGX yet")
70 }
71 
72 /// This function is used to implement various functions that doesn't exist,
73 /// but the lack of which might not be reason for error. If no error is
74 /// returned, the program might very well be able to function normally. This is
75 /// what happens when `SGX_INEFFECTIVE_ERROR` is set to `true`. If it is
76 /// `false`, the behavior is the same as `unsupported`.
sgx_ineffective<T>(v: T) -> crate::std::io::Result<T>77 pub fn sgx_ineffective<T>(v: T) -> crate::std::io::Result<T> {
78     static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
79     if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
80         Err(crate::std::io::const_io_error!(
81             ErrorKind::Uncategorized,
82             "operation can't be trusted to have any effect on SGX",
83         ))
84     } else {
85         Ok(v)
86     }
87 }
88 
89 #[inline]
is_interrupted(code: i32) -> bool90 pub fn is_interrupted(code: i32) -> bool {
91     use fortanix_sgx_abi::Error;
92     code == Error::Interrupted as _
93 }
94 
decode_error_kind(code: i32) -> ErrorKind95 pub fn decode_error_kind(code: i32) -> ErrorKind {
96     use fortanix_sgx_abi::Error;
97 
98     // FIXME: not sure how to make sure all variants of Error are covered
99     if code == Error::NotFound as _ {
100         ErrorKind::NotFound
101     } else if code == Error::PermissionDenied as _ {
102         ErrorKind::PermissionDenied
103     } else if code == Error::ConnectionRefused as _ {
104         ErrorKind::ConnectionRefused
105     } else if code == Error::ConnectionReset as _ {
106         ErrorKind::ConnectionReset
107     } else if code == Error::ConnectionAborted as _ {
108         ErrorKind::ConnectionAborted
109     } else if code == Error::NotConnected as _ {
110         ErrorKind::NotConnected
111     } else if code == Error::AddrInUse as _ {
112         ErrorKind::AddrInUse
113     } else if code == Error::AddrNotAvailable as _ {
114         ErrorKind::AddrNotAvailable
115     } else if code == Error::BrokenPipe as _ {
116         ErrorKind::BrokenPipe
117     } else if code == Error::AlreadyExists as _ {
118         ErrorKind::AlreadyExists
119     } else if code == Error::WouldBlock as _ {
120         ErrorKind::WouldBlock
121     } else if code == Error::InvalidInput as _ {
122         ErrorKind::InvalidInput
123     } else if code == Error::InvalidData as _ {
124         ErrorKind::InvalidData
125     } else if code == Error::TimedOut as _ {
126         ErrorKind::TimedOut
127     } else if code == Error::WriteZero as _ {
128         ErrorKind::WriteZero
129     } else if code == Error::Interrupted as _ {
130         ErrorKind::Interrupted
131     } else if code == Error::Other as _ {
132         ErrorKind::Uncategorized
133     } else if code == Error::UnexpectedEof as _ {
134         ErrorKind::UnexpectedEof
135     } else {
136         ErrorKind::Uncategorized
137     }
138 }
139 
abort_internal() -> !140 pub fn abort_internal() -> ! {
141     abi::usercalls::exit(true)
142 }
143 
144 // This function is needed by the panic runtime. The symbol is named in
145 // pre-link args for the target specification, so keep that in sync.
146 #[cfg(not(test))]
147 #[no_mangle]
148 // NB. used by both libunwind and libpanic_abort
__rust_abort()149 pub extern "C" fn __rust_abort() {
150     abort_internal();
151 }
152 
153 pub mod rand {
rdrand64() -> u64154     pub fn rdrand64() -> u64 {
155         unsafe {
156             let mut ret: u64 = 0;
157             for _ in 0..10 {
158                 if crate::std::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
159                     return ret;
160                 }
161             }
162             rtabort!("Failed to obtain random data");
163         }
164     }
165 }
166 
hashmap_random_keys() -> (u64, u64)167 pub fn hashmap_random_keys() -> (u64, u64) {
168     (self::rand::rdrand64(), self::rand::rdrand64())
169 }
170 
171 pub use crate::std::sys_common::{AsInner, FromInner, IntoInner};
172 
173 pub trait TryIntoInner<Inner>: Sized {
try_into_inner(self) -> Result<Inner, Self>174     fn try_into_inner(self) -> Result<Inner, Self>;
175 }
176