Skip to content

Commit a34e976

Browse files
committed
Support letting enclaves do time keeping
1 parent f3b05c8 commit a34e976

File tree

15 files changed

+103
-40
lines changed

15 files changed

+103
-40
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

intel-sgx/async-usercalls/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ categories = ["asynchronous"]
1717
[dependencies]
1818
# Project dependencies
1919
ipc-queue = { version = "0.3", path = "../../ipc-queue" }
20-
fortanix-sgx-abi = { version = "0.5.0", path = "../fortanix-sgx-abi" }
20+
fortanix-sgx-abi = { version = "0.6.0", path = "../fortanix-sgx-abi" }
2121

2222
# External dependencies
2323
lazy_static = "1.4.0" # MIT/Apache-2.0

intel-sgx/async-usercalls/src/callback.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use fortanix_sgx_abi::{invoke_with_usercalls, Fd, Result};
1+
use fortanix_sgx_abi::{invoke_with_usercalls, Fd, Result, InsecureTimeInfo};
22
use std::io;
33
use std::os::fortanix_sgx::usercalls::raw::{Return, ReturnValue};
44
use std::os::fortanix_sgx::usercalls::FromSgxResult;
@@ -21,21 +21,23 @@ impl<F, T> From<F> for CbFn<T>
2121
}
2222

2323
macro_rules! cbfn_type {
24-
( ) => { CbFn<()> };
25-
( -> ! ) => { () };
26-
( -> u64 ) => { CbFn<u64> };
27-
( -> (Result, usize) ) => { CbFn<io::Result<usize>> };
28-
( -> (Result, u64) ) => { CbFn<io::Result<u64>> };
29-
( -> (Result, Fd) ) => { CbFn<io::Result<Fd>> };
30-
( -> (Result, *mut u8) ) => { CbFn<io::Result<*mut u8>> };
31-
( -> Result ) => { CbFn<io::Result<()>> };
24+
( ) => { CbFn<()> };
25+
( -> ! ) => { () };
26+
( -> u64 ) => { CbFn<u64> };
27+
( -> (u64, *const InsecureTimeInfo) ) => { CbFn<(u64, *const InsecureTimeInfo)> };
28+
( -> (Result, usize) ) => { CbFn<io::Result<usize>> };
29+
( -> (Result, u64) ) => { CbFn<io::Result<u64>> };
30+
( -> (Result, Fd) ) => { CbFn<io::Result<Fd>> };
31+
( -> (Result, *mut u8) ) => { CbFn<io::Result<*mut u8>> };
32+
( -> Result ) => { CbFn<io::Result<()>> };
3233
}
3334

3435
macro_rules! call_cbfn {
35-
( $cb:ident, $rv:expr, ) => { let x: () = $rv; $cb.call(x); };
36-
( $cb:ident, $rv:expr, -> ! ) => { let _: ! = $rv; };
37-
( $cb:ident, $rv:expr, -> u64 ) => { let x: u64 = $rv; $cb.call(x); };
38-
( $cb:ident, $rv:expr, -> $t:ty ) => { let x: $t = $rv; $cb.call(x.from_sgx_result()); };
36+
( $cb:ident, $rv:expr, ) => { let x: () = $rv; $cb.call(x); };
37+
( $cb:ident, $rv:expr, -> ! ) => { let _: ! = $rv; };
38+
( $cb:ident, $rv:expr, -> u64 ) => { let x: u64 = $rv; $cb.call(x); };
39+
( $cb:ident, $rv:expr, -> (u64, *const InsecureTimeInfo) ) => { let x: (u64, *const InsecureTimeInfo) = $rv; $cb.call(x); };
40+
( $cb:ident, $rv:expr, -> $t:ty ) => { let x: $t = $rv; $cb.call(x.from_sgx_result()); };
3941
}
4042

4143
macro_rules! define_callback {

intel-sgx/async-usercalls/src/provider_api.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::io_bufs::UserBuf;
33
use crate::raw::RawApi;
44
use crate::utils::MakeSend;
55
use crate::{AsyncUsercallProvider, CancelHandle};
6-
use fortanix_sgx_abi::Fd;
6+
use fortanix_sgx_abi::{Fd, InsecureTimeInfo};
77
use std::io;
88
use std::mem::{self, ManuallyDrop};
99
use std::net::{TcpListener, TcpStream};
@@ -251,13 +251,15 @@ impl AsyncUsercallProvider {
251251
/// callbacks.
252252
pub fn insecure_time<F>(&self, callback: F)
253253
where
254-
F: FnOnce(SystemTime) + Send + 'static,
254+
F: FnOnce(SystemTime, *const InsecureTimeInfo) + Send + 'static,
255255
{
256-
let cb = move |nanos_since_epoch| {
256+
let cb = move |(nanos_since_epoch, insecure_time_info_ptr): (u64, *const InsecureTimeInfo)| {
257257
let t = UNIX_EPOCH + Duration::from_nanos(nanos_since_epoch);
258-
callback(t);
258+
callback(t, insecure_time_info_ptr);
259259
};
260260
unsafe {
261+
// TODO We could detect if we're able to handle insecure time within the enclave, and
262+
// avoid the async call
261263
self.raw_insecure_time(Some(cb.into()));
262264
}
263265
}
@@ -285,4 +287,4 @@ fn copy_user_buffer(buf: &UserRef<ByteBuffer>) -> Vec<u8> {
285287
Vec::new()
286288
}
287289
}
288-
}
290+
}

intel-sgx/async-usercalls/src/raw.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::callback::*;
22
use crate::{AsyncUsercallProvider, CancelHandle};
3-
use fortanix_sgx_abi::Fd;
3+
use fortanix_sgx_abi::{Fd, InsecureTimeInfo};
44
use std::io;
55
use std::os::fortanix_sgx::usercalls::raw::ByteBuffer;
66
use std::os::fortanix_sgx::usercalls::raw::{Usercall, UsercallNrs};
@@ -51,7 +51,7 @@ pub trait RawApi {
5151
callback: Option<CbFn<io::Result<Fd>>>,
5252
) -> CancelHandle;
5353

54-
unsafe fn raw_insecure_time(&self, callback: Option<CbFn<u64>>);
54+
unsafe fn raw_insecure_time(&self, callback: Option<CbFn<(u64, *const InsecureTimeInfo)>>);
5555

5656
unsafe fn raw_alloc(&self, size: usize, alignment: usize, callback: Option<CbFn<io::Result<*mut u8>>>);
5757

@@ -137,7 +137,7 @@ impl RawApi for AsyncUsercallProvider {
137137
self.send_usercall(u, callback.map(|cb| Callback::connect_stream(cb)))
138138
}
139139

140-
unsafe fn raw_insecure_time(&self, callback: Option<CbFn<u64>>) {
140+
unsafe fn raw_insecure_time(&self, callback: Option<CbFn<(u64, *const InsecureTimeInfo)>>) {
141141
let u = Usercall(UsercallNrs::insecure_time as _, 0, 0, 0, 0);
142142
self.send_usercall(u, callback.map(|cb| Callback::insecure_time(cb)));
143143
}
@@ -172,7 +172,7 @@ mod tests {
172172
let (tx, rx) = mpmc::bounded(N);
173173
for _ in 0..N {
174174
let tx = tx.clone();
175-
let cb = move |d| {
175+
let cb = move |(d, _)| {
176176
let system_time = UNIX_EPOCH + Duration::from_nanos(d);
177177
tx.send(system_time).unwrap();
178178
};

intel-sgx/async-usercalls/src/test_support.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Drop for AutoPollingProvider {
4141
fn drop(&mut self) {
4242
self.shutdown.store(true, Ordering::Relaxed);
4343
// send a usercall to ensure thread wakes up
44-
self.provider.insecure_time(|_| {});
44+
self.provider.insecure_time(|_, _| {});
4545
self.join_handle.take().unwrap().join().unwrap();
4646
}
4747
}

intel-sgx/enclave-runner/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ exclude = ["fake-vdso/.gitignore", "fake-vdso/Makefile", "fake-vdso/main.S"]
2121
[dependencies]
2222
# Project dependencies
2323
sgxs = { version = "0.8.0", path = "../sgxs" }
24-
fortanix-sgx-abi = { version = "0.5.0", path = "../fortanix-sgx-abi" }
24+
fortanix-sgx-abi = { version = "0.6.0", path = "../fortanix-sgx-abi" }
2525
sgx-isa = { version = "0.4.0", path = "../sgx-isa" }
26+
insecure-time = { version = "0.1", path = "../insecure-time", features = ["estimate_crystal_clock_freq"] }
2627
ipc-queue = { version = "0.3.0", path = "../../ipc-queue" }
2728

2829
# External dependencies

intel-sgx/enclave-runner/src/command.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct Command {
2222
size: usize,
2323
usercall_ext: Option<Box<dyn UsercallExtension>>,
2424
forward_panics: bool,
25+
force_time_usercalls: bool,
2526
cmd_args: Vec<Vec<u8>>,
2627
}
2728

@@ -44,6 +45,7 @@ impl Command {
4445
size: usize,
4546
usercall_ext: Option<Box<dyn UsercallExtension>>,
4647
forward_panics: bool,
48+
force_time_usercalls: bool,
4749
cmd_args: Vec<Vec<u8>>,
4850
) -> Command {
4951
let main = tcss.remove(0);
@@ -54,6 +56,7 @@ impl Command {
5456
size,
5557
usercall_ext,
5658
forward_panics,
59+
force_time_usercalls,
5760
cmd_args,
5861
}
5962
}
@@ -63,6 +66,6 @@ impl Command {
6366
}
6467

6568
pub fn run(self) -> Result<(), Error> {
66-
EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.cmd_args)
69+
EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.force_time_usercalls, self.cmd_args)
6770
}
6871
}

intel-sgx/enclave-runner/src/library.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ impl Library {
4848
size: usize,
4949
usercall_ext: Option<Box<dyn UsercallExtension>>,
5050
forward_panics: bool,
51+
force_time_usercalls: bool,
5152
) -> Library {
5253
Library {
53-
enclave: EnclaveState::library(tcss, usercall_ext, forward_panics),
54+
enclave: EnclaveState::library(tcss, usercall_ext, forward_panics, force_time_usercalls),
5455
address,
5556
size,
5657
}

intel-sgx/enclave-runner/src/loader.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub struct EnclaveBuilder<'a> {
6868
load_and_sign: Option<Box<dyn FnOnce(Signer) -> Result<Sigstruct, anyhow::Error>>>,
6969
hash_enclave: Option<Box<dyn FnOnce(&mut EnclaveSource<'_>) -> Result<EnclaveHash, anyhow::Error>>>,
7070
forward_panics: bool,
71+
force_time_usercalls: bool,
7172
cmd_args: Option<Vec<Vec<u8>>>,
7273
}
7374

@@ -145,6 +146,7 @@ impl<'a> EnclaveBuilder<'a> {
145146
load_and_sign: None,
146147
hash_enclave: None,
147148
forward_panics: false,
149+
force_time_usercalls: true, // By default, keep the old behavior of always doing a usercall on an insecure_time call
148150
cmd_args: None,
149151
};
150152

@@ -266,6 +268,16 @@ impl<'a> EnclaveBuilder<'a> {
266268
self
267269
}
268270

271+
/// SGXv2 platforms allow enclaves to use the `rdtsc` instruction. This can speed up
272+
/// performance significantly as enclave no longer need to call out to userspace to request the
273+
/// current time. Unfortunately, older enclaves are not compatible with new enclave runners.
274+
/// Also, sometimes the behavior of enclaves always calling out the userspace needs to be
275+
/// simulated. This setting enforces the old behavior.
276+
pub fn force_insecure_time_usercalls(&mut self, force_time_usercalls: bool) -> &mut Self {
277+
self.force_time_usercalls = force_time_usercalls;
278+
self
279+
}
280+
269281
fn initialized_args_mut(&mut self) -> &mut Vec<Vec<u8>> {
270282
self.cmd_args.get_or_insert_with(|| vec![b"enclave".to_vec()])
271283
}
@@ -309,7 +321,7 @@ impl<'a> EnclaveBuilder<'a> {
309321
fn load<T: Load>(
310322
mut self,
311323
loader: &mut T,
312-
) -> Result<(Vec<ErasedTcs>, *mut c_void, usize, bool), anyhow::Error> {
324+
) -> Result<(Vec<ErasedTcs>, *mut c_void, usize, bool, bool), anyhow::Error> {
313325
let signature = match self.signature {
314326
Some(sig) => sig,
315327
None => self
@@ -320,6 +332,7 @@ impl<'a> EnclaveBuilder<'a> {
320332
let miscselect = self.miscselect.unwrap_or(signature.miscselect);
321333
let mapping = loader.load(&mut self.enclave, &signature, attributes, miscselect)?;
322334
let forward_panics = self.forward_panics;
335+
let force_time_usercalls = self.force_time_usercalls;
323336
if mapping.tcss.is_empty() {
324337
unimplemented!()
325338
}
@@ -328,6 +341,7 @@ impl<'a> EnclaveBuilder<'a> {
328341
mapping.info.address(),
329342
mapping.info.size(),
330343
forward_panics,
344+
force_time_usercalls,
331345
))
332346
}
333347

@@ -336,7 +350,7 @@ impl<'a> EnclaveBuilder<'a> {
336350
let args = self.cmd_args.take().unwrap_or_default();
337351
let c = self.usercall_ext.take();
338352
self.load(loader)
339-
.map(|(t, a, s, fp)| Command::internal_new(t, a, s, c, fp, args))
353+
.map(|(t, a, s, fp, dti)| Command::internal_new(t, a, s, c, fp, dti, args))
340354
}
341355

342356
/// Panics if you have previously called [`arg`] or [`args`].
@@ -349,6 +363,6 @@ impl<'a> EnclaveBuilder<'a> {
349363
}
350364
let c = self.usercall_ext.take();
351365
self.load(loader)
352-
.map(|(t, a, s, fp)| Library::internal_new(t, a, s, c, fp))
366+
.map(|(t, a, s, fp, dti)| Library::internal_new(t, a, s, c, fp, dti))
353367
}
354368
}

0 commit comments

Comments
 (0)