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