]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/mod.rs
SGX target: simplify usercall internals
[rust.git] / src / libstd / sys / sgx / abi / usercalls / mod.rs
1 use io::{Error as IoError, Result as IoResult};
2 use time::Duration;
3
4 pub(crate) mod alloc;
5 #[macro_use]
6 pub(crate) mod raw;
7
8 use self::raw::*;
9
10 /// Usercall `read`. See the ABI documentation for more information.
11 #[unstable(feature = "sgx_platform", issue = "56975")]
12 pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
13     unsafe {
14         let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
15         let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
16         userbuf[..len].copy_to_enclave(&mut buf[..len]);
17         Ok(len)
18     }
19 }
20
21 /// Usercall `read_alloc`. See the ABI documentation for more information.
22 #[unstable(feature = "sgx_platform", issue = "56975")]
23 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
24     unsafe {
25         let userbuf = ByteBuffer { data: ::ptr::null_mut(), len: 0 };
26         let mut userbuf = alloc::User::new_from_enclave(&userbuf);
27         raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
28         Ok(userbuf.copy_user_buffer())
29     }
30 }
31
32 /// Usercall `write`. See the ABI documentation for more information.
33 #[unstable(feature = "sgx_platform", issue = "56975")]
34 pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
35     unsafe {
36         let userbuf = alloc::User::new_from_enclave(buf);
37         raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
38     }
39 }
40
41 /// Usercall `flush`. See the ABI documentation for more information.
42 #[unstable(feature = "sgx_platform", issue = "56975")]
43 pub fn flush(fd: Fd) -> IoResult<()> {
44     unsafe { raw::flush(fd).from_sgx_result() }
45 }
46
47 /// Usercall `close`. See the ABI documentation for more information.
48 #[unstable(feature = "sgx_platform", issue = "56975")]
49 pub fn close(fd: Fd) {
50     unsafe { raw::close(fd) }
51 }
52
53 fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
54     String::from_utf8(buf.copy_user_buffer())
55         .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
56 }
57
58 /// Usercall `bind_stream`. See the ABI documentation for more information.
59 #[unstable(feature = "sgx_platform", issue = "56975")]
60 pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> {
61     unsafe {
62         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
63         let mut local = alloc::User::<ByteBuffer>::uninitialized();
64         let fd = raw::bind_stream(
65             addr_user.as_ptr(),
66             addr_user.len(),
67             local.as_raw_mut_ptr()
68         ).from_sgx_result()?;
69         let local = string_from_bytebuffer(&local, "bind_stream", "local_addr");
70         Ok((fd, local))
71     }
72 }
73
74 /// Usercall `accept_stream`. See the ABI documentation for more information.
75 #[unstable(feature = "sgx_platform", issue = "56975")]
76 pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> {
77     unsafe {
78         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
79         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
80                                                                // without forcing coercion?
81         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
82         let fd = raw::accept_stream(
83             fd,
84             local.as_raw_mut_ptr(),
85             peer.as_raw_mut_ptr()
86         ).from_sgx_result()?;
87         let local = string_from_bytebuffer(&local, "accept_stream", "local_addr");
88         let peer = string_from_bytebuffer(&peer, "accept_stream", "peer_addr");
89         Ok((fd, local, peer))
90     }
91 }
92
93 /// Usercall `connect_stream`. See the ABI documentation for more information.
94 #[unstable(feature = "sgx_platform", issue = "56975")]
95 pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> {
96     unsafe {
97         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
98         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
99         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
100                                                                // without forcing coercion?
101         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
102         let fd = raw::connect_stream(
103             addr_user.as_ptr(),
104             addr_user.len(),
105             local.as_raw_mut_ptr(),
106             peer.as_raw_mut_ptr()
107         ).from_sgx_result()?;
108         let local = string_from_bytebuffer(&local, "connect_stream", "local_addr");
109         let peer = string_from_bytebuffer(&peer, "connect_stream", "peer_addr");
110         Ok((fd, local, peer))
111     }
112 }
113
114 /// Usercall `launch_thread`. See the ABI documentation for more information.
115 #[unstable(feature = "sgx_platform", issue = "56975")]
116 pub unsafe fn launch_thread() -> IoResult<()> {
117     raw::launch_thread().from_sgx_result()
118 }
119
120 /// Usercall `exit`. See the ABI documentation for more information.
121 #[unstable(feature = "sgx_platform", issue = "56975")]
122 pub fn exit(panic: bool) -> ! {
123     unsafe { raw::exit(panic) }
124 }
125
126 /// Usercall `wait`. See the ABI documentation for more information.
127 #[unstable(feature = "sgx_platform", issue = "56975")]
128 pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
129     unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
130 }
131
132 /// Usercall `send`. See the ABI documentation for more information.
133 #[unstable(feature = "sgx_platform", issue = "56975")]
134 pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
135     unsafe { raw::send(event_set, tcs).from_sgx_result() }
136 }
137
138 /// Usercall `insecure_time`. See the ABI documentation for more information.
139 #[unstable(feature = "sgx_platform", issue = "56975")]
140 pub fn insecure_time() -> Duration {
141     let t = unsafe { raw::insecure_time() };
142     Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _)
143 }
144
145 /// Usercall `alloc`. See the ABI documentation for more information.
146 #[unstable(feature = "sgx_platform", issue = "56975")]
147 pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
148     unsafe { raw::alloc(size, alignment).from_sgx_result() }
149 }
150
151 #[unstable(feature = "sgx_platform", issue = "56975")]
152 #[doc(inline)]
153 pub use self::raw::free;
154
155 fn check_os_error(err: Result) -> i32 {
156     // FIXME: not sure how to make sure all variants of Error are covered
157     if err == Error::NotFound as _ ||
158        err == Error::PermissionDenied as _ ||
159        err == Error::ConnectionRefused as _ ||
160        err == Error::ConnectionReset as _ ||
161        err == Error::ConnectionAborted as _ ||
162        err == Error::NotConnected as _ ||
163        err == Error::AddrInUse as _ ||
164        err == Error::AddrNotAvailable as _ ||
165        err == Error::BrokenPipe as _ ||
166        err == Error::AlreadyExists as _ ||
167        err == Error::WouldBlock as _ ||
168        err == Error::InvalidInput as _ ||
169        err == Error::InvalidData as _ ||
170        err == Error::TimedOut as _ ||
171        err == Error::WriteZero as _ ||
172        err == Error::Interrupted as _ ||
173        err == Error::Other as _ ||
174        err == Error::UnexpectedEof as _ ||
175        ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
176     {
177         err
178     } else {
179         panic!("Usercall: returned invalid error value {}", err)
180     }
181 }
182
183 trait FromSgxResult {
184     type Return;
185
186     fn from_sgx_result(self) -> IoResult<Self::Return>;
187 }
188
189 impl<T> FromSgxResult for (Result, T) {
190     type Return = T;
191
192     fn from_sgx_result(self) -> IoResult<Self::Return> {
193         if self.0 == RESULT_SUCCESS {
194             Ok(self.1)
195         } else {
196             Err(IoError::from_raw_os_error(check_os_error(self.0)))
197         }
198     }
199 }
200
201 impl FromSgxResult for Result {
202     type Return = ();
203
204     fn from_sgx_result(self) -> IoResult<Self::Return> {
205         if self == RESULT_SUCCESS {
206             Ok(())
207         } else {
208             Err(IoError::from_raw_os_error(check_os_error(self)))
209         }
210     }
211 }