Skip to content

Commit 2fb7b67

Browse files
Merge #396
396: Refactor `ipc_queue` crate r=jethrogb a=raoulstrackx Co-authored-by: Raoul Strackx <[email protected]>
2 parents 5a4adba + b82cc1b commit 2fb7b67

File tree

7 files changed

+128
-43
lines changed

7 files changed

+128
-43
lines changed

Cargo.lock

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

intel-sgx/enclave-runner/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ exclude = ["fake-vdso/.gitignore", "fake-vdso/Makefile", "fake-vdso/main.S"]
2323
sgxs = { version = "0.7.2", path = "../sgxs" }
2424
fortanix-sgx-abi = { version = "0.4.0", path = "../fortanix-sgx-abi" }
2525
sgx-isa = { version = "0.4.0", path = "../sgx-isa" }
26-
ipc-queue = { version = "0.1.0", path = "../../ipc-queue" }
26+
ipc-queue = { version = "0.2.0", path = "../../ipc-queue" }
2727

2828
# External dependencies
2929
failure = "0.1.1" # MIT/Apache-2.0

ipc-queue/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ipc-queue"
3-
version = "0.1.1"
3+
version = "0.2.0"
44
authors = ["Fortanix, Inc."]
55
license = "MPL-2.0"
66
edition = "2018"

ipc-queue/src/fifo.rs

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,48 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
66

77
use std::cell::UnsafeCell;
8+
use std::marker::PhantomData;
89
use std::mem;
9-
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering, Ordering::SeqCst};
10-
use std::sync::Arc;
10+
#[cfg(not(target_env = "sgx"))]
11+
use {
12+
std::sync::atomic::AtomicU64,
13+
std::sync::Arc,
14+
};
15+
use std::sync::atomic::{AtomicUsize, Ordering, Ordering::SeqCst};
1116

1217
use fortanix_sgx_abi::{FifoDescriptor, WithId};
1318

1419
use super::*;
1520

21+
// `fortanix_sgx_abi::WithId` is not `Copy` because it contains an `AtomicU64`.
22+
// This type has the same memory layout but is `Copy` and can be marked as
23+
// `UserSafeSized` which is needed for the `User::from_raw_parts()` below.
24+
#[cfg(target_env = "sgx")]
25+
#[repr(C)]
26+
#[derive(Default, Clone, Copy)]
27+
struct UserSafeWithId<T> {
28+
pub id: u64,
29+
pub data: T,
30+
}
31+
32+
#[cfg(target_env = "sgx")]
33+
unsafe impl<T: UserSafeSized> UserSafeSized for UserSafeWithId<T> {}
34+
35+
#[cfg(target_env = "sgx")]
36+
unsafe fn _sanity_check_with_id() {
37+
use std::mem::size_of;
38+
let _: [u8; size_of::<fortanix_sgx_abi::WithId<()>>()] = [0u8; size_of::<UserSafeWithId<()>>()];
39+
}
40+
41+
#[cfg(target_env = "sgx")]
42+
#[repr(transparent)]
43+
#[derive(Copy, Clone)]
44+
struct WrapUsize(usize);
45+
46+
#[cfg(target_env = "sgx")]
47+
unsafe impl UserSafeSized for WrapUsize{}
48+
49+
#[cfg(not(target_env = "sgx"))]
1650
pub fn bounded<T, S>(len: usize, s: S) -> (Sender<T, S>, Receiver<T, S>)
1751
where
1852
T: Transmittable,
@@ -25,6 +59,7 @@ where
2559
(tx, rx)
2660
}
2761

62+
#[cfg(not(target_env = "sgx"))]
2863
pub fn bounded_async<T, S>(len: usize, s: S) -> (AsyncSender<T, S>, AsyncReceiver<T, S>)
2964
where
3065
T: Transmittable,
@@ -37,11 +72,43 @@ where
3772
(tx, rx)
3873
}
3974

75+
#[cfg(all(test, target_env = "sgx"))]
76+
pub(crate) fn bounded<T, S>(len: usize, s: S) -> (Sender<T, S>, Receiver<T, S>)
77+
where
78+
T: Transmittable,
79+
S: Synchronizer,
80+
{
81+
use std::ops::DerefMut;
82+
use std::os::fortanix_sgx::usercalls::alloc::User;
83+
84+
// Allocate [WithId<T>; len] in userspace
85+
// WARNING: This creates dangling memory in userspace, use in tests only!
86+
let mut data = User::<[UserSafeWithId<T>]>::uninitialized(len);
87+
data.deref_mut().iter_mut().for_each(|v| v.copy_from_enclave(&UserSafeWithId::default()));
88+
89+
// WARNING: This creates dangling memory in userspace, use in tests only!
90+
let offsets = User::<WrapUsize>::new_from_enclave(&WrapUsize(0));
91+
let offsets = offsets.into_raw() as *const AtomicUsize;
92+
93+
let descriptor = FifoDescriptor {
94+
data: data.into_raw() as _,
95+
len,
96+
offsets,
97+
};
98+
99+
let inner = unsafe { Fifo::from_descriptor(descriptor) };
100+
let tx = Sender { inner: inner.clone(), synchronizer: s.clone() };
101+
let rx = Receiver { inner, synchronizer: s };
102+
(tx, rx)
103+
}
104+
105+
#[cfg(not(target_env = "sgx"))]
40106
pub(crate) struct FifoBuffer<T> {
41107
data: Box<[WithId<T>]>,
42108
offsets: Box<AtomicUsize>,
43109
}
44110

111+
#[cfg(not(target_env = "sgx"))]
45112
impl<T: Transmittable> FifoBuffer<T> {
46113
fn new(len: usize) -> Self {
47114
assert!(
@@ -57,16 +124,18 @@ impl<T: Transmittable> FifoBuffer<T> {
57124
}
58125
}
59126

60-
enum Storage<T> {
127+
enum Storage<T: 'static> {
128+
#[cfg(not(target_env = "sgx"))]
61129
Shared(Arc<FifoBuffer<T>>),
62-
Static,
130+
Static(PhantomData<&'static T>),
63131
}
64132

65133
impl<T> Clone for Storage<T> {
66134
fn clone(&self) -> Self {
67135
match self {
136+
#[cfg(not(target_env = "sgx"))]
68137
Storage::Shared(arc) => Storage::Shared(arc.clone()),
69-
Storage::Static => Storage::Static,
138+
Storage::Static(p) => Storage::Static(*p),
70139
}
71140
}
72141
}
@@ -94,42 +163,23 @@ impl<T: Transmittable> Fifo<T> {
94163
"Fifo len should be a power of two"
95164
);
96165
#[cfg(target_env = "sgx")] {
97-
use std::os::fortanix_sgx::usercalls::alloc::{User, UserRef};
98-
99-
// `fortanix_sgx_abi::WithId` is not `Copy` because it contains an `AtomicU64`.
100-
// This type has the same memory layout but is `Copy` and can be marked as
101-
// `UserSafeSized` which is needed for the `User::from_raw_parts()` below.
102-
#[repr(C)]
103-
#[derive(Clone, Copy)]
104-
pub struct WithId<T> {
105-
pub id: u64,
106-
pub data: T,
107-
}
108-
unsafe impl<T: UserSafeSized> UserSafeSized for WithId<T> {}
109-
110-
unsafe fn _sanity_check_with_id() {
111-
use std::mem::size_of;
112-
let _: [u8; size_of::<fortanix_sgx_abi::WithId<()>>()] = [0u8; size_of::<WithId<()>>()];
113-
}
114-
115-
#[repr(transparent)]
116-
#[derive(Copy, Clone)]
117-
struct WrapUsize(usize);
118-
unsafe impl UserSafeSized for WrapUsize{}
166+
use std::os::fortanix_sgx::usercalls::alloc::User;
119167

120168
// check pointers are outside enclave range, etc.
121-
let data = User::<[WithId<T>]>::from_raw_parts(descriptor.data as _, descriptor.len);
169+
let data = User::<[UserSafeWithId<T>]>::from_raw_parts(descriptor.data as _, descriptor.len);
122170
mem::forget(data);
123171
UserRef::from_ptr(descriptor.offsets as *const WrapUsize);
172+
124173
}
125174
let data_slice = std::slice::from_raw_parts(descriptor.data, descriptor.len);
126175
Self {
127176
data: &*(data_slice as *const [WithId<T>] as *const [UnsafeCell<WithId<T>>]),
128177
offsets: &*descriptor.offsets,
129-
storage: Storage::Static,
178+
storage: Storage::Static(PhantomData::default()),
130179
}
131180
}
132181

182+
#[cfg(not(target_env = "sgx"))]
133183
fn from_arc(fifo: Arc<FifoBuffer<T>>) -> Self {
134184
unsafe {
135185
Self {
@@ -142,10 +192,11 @@ impl<T: Transmittable> Fifo<T> {
142192

143193
/// Consumes `self` and returns a DescriptorGuard.
144194
/// Panics if `self` was created using `from_descriptor`.
195+
#[cfg(not(target_env = "sgx"))]
145196
pub(crate) fn into_descriptor_guard(self) -> DescriptorGuard<T> {
146197
let arc = match self.storage {
147198
Storage::Shared(arc) => arc,
148-
Storage::Static => panic!("Sender/Receiver created using `from_descriptor()` cannot be turned into DescriptorGuard."),
199+
Storage::Static(_) => panic!("Sender/Receiver created using `from_descriptor()` cannot be turned into DescriptorGuard."),
149200
};
150201
let descriptor = FifoDescriptor {
151202
data: self.data.as_ptr() as _,
@@ -176,9 +227,11 @@ impl<T: Transmittable> Fifo<T> {
176227
};
177228

178229
// 4. Write the data, then the `id`.
179-
let slot = unsafe { &mut *self.data[new.write_offset()].get() };
180-
slot.data = val.data;
181-
slot.id.store(val.id, SeqCst);
230+
unsafe {
231+
let slot = &mut *self.data[new.write_offset()].get();
232+
T::write(&mut slot.data, &val.data);
233+
slot.id.store(val.id, SeqCst);
234+
}
182235

183236
// 5. If the queue was empty in step 1, signal the reader to wake up.
184237
Ok(was_empty)
@@ -209,7 +262,8 @@ impl<T: Transmittable> Fifo<T> {
209262
};
210263

211264
// 6. Read the data, then store `0` in the `id`.
212-
let val = Identified { id, data: slot.data };
265+
let data = unsafe { T::read(&slot.data) };
266+
let val = Identified { id, data };
213267
slot.id.store(0, SeqCst);
214268

215269
// 7. Store the new read offset, retrieving the old offsets.

ipc-queue/src/interface_async.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl<T: Transmittable, S: AsyncSynchronizer> AsyncSender<T, S> {
4141
/// Consumes `self` and returns a DescriptorGuard.
4242
/// The returned guard can be used to make `FifoDescriptor`s that remain
4343
/// valid as long as the guard is not dropped.
44+
#[cfg(not(target_env = "sgx"))]
4445
pub fn into_descriptor_guard(self) -> DescriptorGuard<T> {
4546
self.inner.into_descriptor_guard()
4647
}
@@ -71,6 +72,7 @@ impl<T: Transmittable, S: AsyncSynchronizer> AsyncReceiver<T, S> {
7172
/// Consumes `self` and returns a DescriptorGuard.
7273
/// The returned guard can be used to make `FifoDescriptor`s that remain
7374
/// valid as long as the guard is not dropped.
75+
#[cfg(not(target_env = "sgx"))]
7476
pub fn into_descriptor_guard(self) -> DescriptorGuard<T> {
7577
self.inner.into_descriptor_guard()
7678
}

ipc-queue/src/interface_sync.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ impl<'r, T: Transmittable, S: Synchronizer> Iterator for TryIter<'r, T, S> {
156156

157157
#[cfg(test)]
158158
mod tests {
159+
use crate::fifo::bounded;
159160
use crate::test_support::pubsub::{Channel, Subscription};
160161
use crate::test_support::TestValue;
161162
use crate::*;

ipc-queue/src/lib.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@
99
#![cfg_attr(target_env = "sgx", feature(sgx_platform))]
1010

1111
use std::future::Future;
12-
#[cfg(target_env = "sgx")]
13-
use std::os::fortanix_sgx::usercalls::alloc::UserSafeSized;
1412
use std::pin::Pin;
15-
use std::sync::Arc;
1613

1714
use fortanix_sgx_abi::FifoDescriptor;
1815

19-
use self::fifo::{Fifo, FifoBuffer};
16+
use self::fifo::Fifo;
17+
18+
#[cfg(target_env = "sgx")]
19+
use std::os::fortanix_sgx::usercalls::alloc::{UserRef, UserSafeSized};
20+
21+
#[cfg(not(target_env = "sgx"))]
22+
use {
23+
std::ptr,
24+
std::sync::Arc,
25+
self::fifo::FifoBuffer,
26+
};
2027

2128
mod fifo;
2229
mod interface_sync;
@@ -25,17 +32,36 @@ mod interface_async;
2532
mod test_support;
2633

2734
#[cfg(target_env = "sgx")]
28-
pub trait Transmittable: UserSafeSized + Default {}
35+
pub trait Transmittable: UserSafeSized + Default {
36+
unsafe fn write(ptr: *mut Self, val: &Self) {
37+
UserRef::<Self>::from_mut_ptr(ptr).copy_from_enclave(val)
38+
}
39+
40+
unsafe fn read(ptr: *const Self) -> Self {
41+
let mut data = Default::default();
42+
UserRef::<Self>::from_ptr(ptr).copy_to_enclave(&mut data);
43+
data
44+
}
45+
}
2946

3047
#[cfg(target_env = "sgx")]
3148
impl<T> Transmittable for T where T: UserSafeSized + Default {}
3249

3350
#[cfg(not(target_env = "sgx"))]
34-
pub trait Transmittable: Copy + Sized + Default {}
51+
pub trait Transmittable: Copy + Sized + Default {
52+
unsafe fn write(ptr: *mut Self, val: &Self) {
53+
ptr::write(ptr, *val);
54+
}
55+
56+
unsafe fn read(ptr: *const Self) -> Self {
57+
ptr::read(ptr)
58+
}
59+
}
3560

3661
#[cfg(not(target_env = "sgx"))]
3762
impl<T> Transmittable for T where T: Copy + Sized + Default {}
3863

64+
#[cfg(not(target_env = "sgx"))]
3965
pub fn bounded<T, S>(len: usize, s: S) -> (Sender<T, S>, Receiver<T, S>)
4066
where
4167
T: Transmittable,
@@ -44,6 +70,7 @@ where
4470
self::fifo::bounded(len, s)
4571
}
4672

73+
#[cfg(not(target_env = "sgx"))]
4774
pub fn bounded_async<T, S>(len: usize, s: S) -> (AsyncSender<T, S>, AsyncReceiver<T, S>)
4875
where
4976
T: Transmittable,
@@ -131,6 +158,7 @@ pub struct AsyncReceiver<T: 'static, S> {
131158
/// to remain valid as long as the DescriptorGuard is not dropped.
132159
pub struct DescriptorGuard<T> {
133160
descriptor: FifoDescriptor<T>,
161+
#[cfg(not(target_env = "sgx"))]
134162
_fifo: Arc<FifoBuffer<T>>,
135163
}
136164

0 commit comments

Comments
 (0)