Skip to content

Commit 976f41c

Browse files
committed
Giving enclaves control over their own TCSes
1 parent 78fdbf3 commit 976f41c

File tree

10 files changed

+53
-32
lines changed

10 files changed

+53
-32
lines changed

Cargo.lock

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

enclave-runner/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "enclave-runner"
3-
version = "0.5.0"
3+
version = "0.6.0"
44
authors = ["Fortanix, Inc."]
55
license = "MPL-2.0"
66
edition = "2018"
@@ -19,7 +19,7 @@ categories = ["os", "hardware-support"]
1919
[dependencies]
2020
# Project dependencies
2121
sgxs = { version = "0.7.2", path = "../sgxs" }
22-
fortanix-sgx-abi = { version = "0.4.0", path = "../fortanix-sgx-abi" }
22+
fortanix-sgx-abi = { version = "0.5.0", path = "../fortanix-sgx-abi" }
2323
sgx-isa = { version = "0.3.0", path = "../sgx-isa" }
2424
ipc-queue = { version = "0.1.0", path = "../ipc-queue" }
2525

enclave-runner/src/usercalls/interface.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,10 @@ impl<'future, 'ioinput: 'future, 'tcs: 'ioinput> Usercalls<'future> for Handler<
171171

172172
fn launch_thread(
173173
self,
174+
tcs: usize,
174175
) -> std::pin::Pin<Box<dyn Future<Output = (Self, UsercallResult<Result>)> + 'future>> {
175176
async move {
176-
let ret = Ok(self.0.launch_thread().to_sgx_result());
177+
let ret = Ok(self.0.launch_thread(tcs).to_sgx_result());
177178
return (self, ret);
178179
}.boxed_local()
179180
}

enclave-runner/src/usercalls/mod.rs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use std::{cmp, fmt, str};
1919

2020
use failure::{self, bail};
2121
use fnv::FnvHashMap;
22+
use futures::executor;
2223
use futures::future::{poll_fn, Either, Future, FutureExt};
2324
use futures::lock::Mutex;
2425
use futures::StreamExt;
@@ -596,7 +597,7 @@ pub(crate) struct EnclaveState {
596597
last_fd: AtomicUsize,
597598
exiting: AtomicBool,
598599
usercall_ext: Box<dyn UsercallExtension>,
599-
threads_queue: crossbeam::queue::SegQueue<StoppedTcs>,
600+
available_enclave_threads: Mutex<FnvHashMap<TcsAddress, StoppedTcs>>,
600601
forward_panics: bool,
601602
// Once set to Some, the guards should not be dropped for the lifetime of the enclave.
602603
fifo_guards: Mutex<Option<FifoGuards>>,
@@ -677,10 +678,10 @@ impl EnclaveState {
677678

678679
let usercall_ext = usercall_ext.unwrap_or_else(|| Box::new(UsercallExtensionDefault));
679680

680-
let threads_queue = crossbeam::queue::SegQueue::new();
681+
let mut available_enclave_threads = FnvHashMap::default();
681682

682683
for thread in threads_vector {
683-
threads_queue.push(Self::event_queue_add_tcs(&mut event_queues, thread));
684+
available_enclave_threads.insert(thread.address(), Self::event_queue_add_tcs(&mut event_queues, thread));
684685
}
685686

686687
Arc::new(EnclaveState {
@@ -690,7 +691,7 @@ impl EnclaveState {
690691
last_fd,
691692
exiting: AtomicBool::new(false),
692693
usercall_ext,
693-
threads_queue,
694+
available_enclave_threads: Mutex::new(available_enclave_threads),
694695
forward_panics,
695696
fifo_guards: Mutex::new(None),
696697
return_queue_tx: Mutex::new(None),
@@ -860,7 +861,7 @@ impl EnclaveState {
860861
let fut = async move {
861862
let ret = match state.mode {
862863
EnclaveEntry::Library => {
863-
enclave_clone.threads_queue.push(StoppedTcs {
864+
enclave_clone.available_enclave_threads.lock().await.insert(tcs.address(), StoppedTcs {
864865
tcs,
865866
event_queue: state.event_queue,
866867
});
@@ -876,7 +877,7 @@ impl EnclaveState {
876877
// If the enclave is in the exit-state, threads are no
877878
// longer able to be launched
878879
if !enclave_clone.exiting.load(Ordering::SeqCst) {
879-
enclave_clone.threads_queue.push(StoppedTcs {
880+
enclave_clone.available_enclave_threads.lock().await.insert(tcs.address(), StoppedTcs {
880881
tcs,
881882
event_queue: state.event_queue,
882883
});
@@ -1008,8 +1009,7 @@ impl EnclaveState {
10081009

10091010
rt.block_on(async move {
10101011
enclave.abort_all_threads();
1011-
//clear the threads_queue
1012-
while enclave.threads_queue.pop().is_ok() {}
1012+
enclave.available_enclave_threads.lock().await.clear();
10131013

10141014
let cmd = enclave.kind.as_command().unwrap();
10151015
let mut cmddata = cmd.panic_reason.lock().await;
@@ -1058,7 +1058,11 @@ impl EnclaveState {
10581058
p4: u64,
10591059
p5: u64,
10601060
) -> StdResult<(u64, u64), failure::Error> {
1061-
let thread = enclave.threads_queue.pop().expect("threads queue empty");
1061+
let thread = executor::block_on(async {
1062+
let mut available_enclave_threads = enclave.available_enclave_threads.lock().await;
1063+
let k = available_enclave_threads.keys().next()?.to_owned();
1064+
available_enclave_threads.remove(&k)
1065+
}).expect("out of enclave threads");
10621066
let work = Work {
10631067
tcs: RunningTcs {
10641068
event_queue: thread.event_queue,
@@ -1389,18 +1393,32 @@ impl<'tcs> IOHandlerInput<'tcs> {
13891393
}
13901394

13911395
#[inline(always)]
1392-
fn launch_thread(&self) -> IoResult<()> {
1396+
fn launch_thread(&self, tcs_address: usize) -> IoResult<()> {
13931397
// check if enclave is of type command
13941398
self.enclave
13951399
.kind
13961400
.as_command()
13971401
.ok_or(IoErrorKind::InvalidInput)?;
1398-
let new_tcs = match self.enclave.threads_queue.pop() {
1399-
Ok(tcs) => tcs,
1400-
Err(_) => {
1401-
return Err(IoErrorKind::WouldBlock.into());
1402-
}
1403-
};
1402+
let tcs_address = TcsAddress(tcs_address);
1403+
let new_tcs = executor::block_on(async {
1404+
loop {
1405+
let mut guard = self.enclave.available_enclave_threads.lock().await;
1406+
match guard.remove(&tcs_address) {
1407+
Some(tcs) => break tcs,
1408+
None => {
1409+
// Release lock and try again. The enclave is in charge of its own TCS
1410+
// structs. Unfortunately, there is a small issue recording terminated
1411+
// TCSs; when a thread has finished with the task it was assigned, it
1412+
// marks its own TCS as available for new threads, while in fact it is
1413+
// still executing (see `Task::run()` in `std/src/sys/sgx/thread.rs`).
1414+
// When that TCS is subsequently selected to run a new thread, it may
1415+
// still not have terminated yet and thus may not yet be present in this
1416+
// `available_enclave_threads`. We need to wait for it to become ready.
1417+
drop(guard);
1418+
}
1419+
}
1420+
}
1421+
});
14041422

14051423
let ret = self.work_sender.send(Work {
14061424
tcs: RunningTcs {
@@ -1417,10 +1435,12 @@ impl<'tcs> IOHandlerInput<'tcs> {
14171435
let entry = e.0.entry;
14181436
match entry {
14191437
CoEntry::Initial(tcs, _, _ ,_, _, _) => {
1420-
self.enclave.threads_queue.push(StoppedTcs {
1421-
tcs,
1422-
event_queue,
1423-
});
1438+
executor::block_on(async {
1439+
self.enclave.available_enclave_threads.lock().await.insert(tcs.address(), StoppedTcs {
1440+
tcs,
1441+
event_queue,
1442+
});
1443+
})
14241444
},
14251445
_ => unreachable!(),
14261446
};

fortanix-sgx-abi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fortanix-sgx-abi"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
authors = ["Fortanix, Inc."]
55
license = "MPL-2.0"
66
description = """

fortanix-sgx-abi/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ impl Usercalls {
488488
/// [`thread_entry`]: entry/executable/fn.thread_entry.html
489489
/// [libraries]: entry/library/index.html
490490
/// [`library`]: entry/library/index.html
491-
pub fn launch_thread() -> Result { unimplemented!() }
491+
pub fn launch_thread(tcs: usize) -> Result { unimplemented!() }
492492

493493
/// Signals to userspace that this enclave needs to be destroyed.
494494
///

fortanix-sgx-tools/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ edition = "2018"
2121
# Project dependencies
2222
aesm-client = { version = "0.5.0", path = "../aesm-client", features = ["sgxs"] }
2323
sgxs-loaders = { version = "0.3.0", path = "../sgxs-loaders" }
24-
enclave-runner = { version = "0.5.0", path = "../enclave-runner" }
24+
enclave-runner = { version = "0.6.0", path = "../enclave-runner" }
2525
sgxs = { version = "0.7.0", path = "../sgxs" }
2626
sgx-isa = { version = "0.3.0", path = "../sgx-isa" }
2727

ipc-queue/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ keywords = ["sgx", "fifo", "queue", "ipc"]
1414
categories = ["asynchronous"]
1515

1616
[dependencies]
17-
fortanix-sgx-abi = { version = "0.4.0", path = "../fortanix-sgx-abi" }
17+
fortanix-sgx-abi = { version = "0.5.0", path = "../fortanix-sgx-abi" }
1818

1919
[dev-dependencies]
2020
static_assertions = "1.1.0"

report-test/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ categories = ["development-tools"]
1616

1717
[dependencies]
1818
# Project dependencies
19-
"enclave-runner" = { version = "0.5.0", path = "../enclave-runner" }
19+
"enclave-runner" = { version = "0.6.0", path = "../enclave-runner" }
2020
"sgxs" = { version = "0.7.0", path = "../sgxs" }
2121
"sgx-isa" = { version = "0.3.0", path = "../sgx-isa" }
2222

sgxs-tools/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ path = "src/sgx_detect/main.rs"
3434
"aesm-client" = { version = "0.5.0", path = "../aesm-client", features = ["sgxs"] }
3535
"sgx-isa" = { version = "0.3.0", path = "../sgx-isa" }
3636
"report-test" = { version = "0.3.1", path = "../report-test" }
37-
"enclave-runner" = { version = "0.5.0", path = "../enclave-runner" }
37+
"enclave-runner" = { version = "0.6.0", path = "../enclave-runner" }
3838

3939
# External dependencies
4040
lazy_static = "1" # MIT/Apache-2.0

0 commit comments

Comments
 (0)