Skip to content

Commit c530abd

Browse files
committed
Generate valid xfrm when required
1 parent f476bb5 commit c530abd

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

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

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
66

7+
use std::arch::x86_64::{self, CpuidResult};
78
use std::fs::File;
89
use std::io::{Error as IoError, ErrorKind, Read, Result as IoResult};
910
use std::ops::RangeInclusive;
@@ -21,6 +22,7 @@ use openssl::{
2122
};
2223

2324
use sgx_isa::{Attributes, AttributesFlags, Miscselect, Sigstruct};
25+
use sgxs::sgxs::PageReader;
2426
use sgxs::crypto::{SgxHashOps, SgxRsaOps};
2527
use sgxs::loader::{Load, MappingInfo, Tcs};
2628
use sgxs::sigstruct::{self, EnclaveHash, Signer};
@@ -163,11 +165,67 @@ impl<'a> EnclaveBuilder<'a> {
163165
ret
164166
}
165167

166-
fn generate_dummy_signature(&mut self) -> Result<Sigstruct, anyhow::Error> {
168+
fn cpuid(eax: u32, ecx: u32) -> Option<CpuidResult> {
169+
unsafe {
170+
if eax <= x86_64::__get_cpuid_max(0).0 {
171+
Some(x86_64::__cpuid_count(eax, ecx))
172+
} else {
173+
None
174+
}
175+
}
176+
}
177+
178+
fn generate_xfrm(max_ssaframesize_in_pages: u32) -> u64 {
167179
fn xgetbv0() -> u64 {
168180
unsafe { arch::x86_64::_xgetbv(0) }
169181
}
170182

183+
debug_assert!(0 < max_ssaframesize_in_pages);
184+
let xcr0 = xgetbv0();
185+
186+
// See allorithm of Intel dev manual Chpt 40.7.2.2
187+
let xfrm = (0..64)
188+
.map(|bit| {
189+
let select = 0x1 << bit;
190+
match bit {
191+
0 | 1 => select, // Bit 0 and 1 always need to be set
192+
_ => {
193+
if xcr0 & select == 0 {
194+
return 0;
195+
}
196+
197+
let (base, size) = {
198+
let cpuid = Self::cpuid(0x0d, bit);
199+
let base = cpuid.map_or(0, |c| c.ebx);
200+
let size = cpuid.map_or(0, |c| c.eax);
201+
(base, size)
202+
};
203+
if max_ssaframesize_in_pages * 0x1000 <= base + size {
204+
return 0;
205+
}
206+
207+
select
208+
}
209+
}
210+
})
211+
.fold(0, |xfrm, b| xfrm | b);
212+
213+
// Intel x86 manual Vol 3 Chpt 13.3:
214+
// "Executing the XSETBV instruction causes a general-protection fault (#GP) if ECX = 0
215+
// and EAX[17] ≠ EAX[18] (TILECFG and TILEDATA must be enabled together). This implies
216+
// that the value of XCR0[18:17] is always either 00b or 11b."
217+
// The enclave entry code executes xrstor, and we may have just cleared bit 18, so we
218+
// need to correct the invariant
219+
if (xfrm & (0x1 << 17)) != (xfrm & (0x1 << 18)) {
220+
xfrm & !(0x11 << 17)
221+
} else {
222+
xfrm
223+
}
224+
}
225+
226+
fn generate_dummy_signature(&mut self) -> Result<Sigstruct, anyhow::Error> {
227+
let mut enclave = self.enclave.try_clone().unwrap();
228+
let create_info = PageReader::new(&mut enclave)?;
171229
let mut enclave = self.enclave.try_clone().unwrap();
172230
let hash = match self.hash_enclave.take() {
173231
Some(f) => f(&mut enclave)?,
@@ -177,7 +235,7 @@ impl<'a> EnclaveBuilder<'a> {
177235

178236
let attributes = self.attributes.unwrap_or_else(|| Attributes {
179237
flags: AttributesFlags::DEBUG | AttributesFlags::MODE64BIT,
180-
xfrm: xgetbv0(),
238+
xfrm: Self::generate_xfrm(create_info.0.ecreate.ssaframesize),
181239
});
182240
signer
183241
.attributes_flags(attributes.flags, !0)

intel-sgx/sgxs-loaders/src/isgx/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ impl EnclaveLoad for InnerDevice {
198198
..Default::default()
199199
};
200200
let createdata = ioctl::CreateData { secs: &secs };
201+
201202
ioctl_unsafe!(
202203
Create,
203204
ioctl::create(mapping.device.fd.as_raw_fd(), &createdata)

0 commit comments

Comments
 (0)