This is the minimalistic implementation of the remote attestation
framework. The framework conducts the following steps during
start-up to verify the authenticity of the SGX platform:
1. Connect to aesmd service to retrieve platform info (targetinfo)
of the Quoting Enclave (QE) before enclave creation.
2. Prepare the SGX report inside enclave (during initialization):
- Read SPID (service provider ID) from sgx.ra_client_spid in
manifest.
- Get an SGX report for local attestation to QE.
- Generate a random 16-byte nonce for freshness.
- Perform an OCALL for retrieving the quote.
3. Gather attestation data (QE report, QE quote, IAS report, signature,
certificate chain) outside of enclave:
- Connect to aesmd to retrieve the QE quote; aesmd also returns
QE report.
- Connect to Intel Attestation Service using curl. A client
subscription key (specified via sgx.ra_client_key in manifest)
is required to authenticate the HTTPS connection.
- Get the IAS report, signature, and certificate chain from IAS.
Print out the attestation result.
- Return all this attestation data back to the enclave.
Do not declare the result of the recursive Make call as "phony" to avoid
unnecessary rebuilds. Due to the missing dependency information we of
course still need to always recurse.
Previous implementation had a few bugs in path-normalization functions,
e.g., in get_norm_path(): "../..a/" -> "....a" and "/../a" -> "../a",
and in get_base_name(): "/" -> garbage (buffer overflow).
Internal LibOS and PAL interfaces use microseconds (us) for timeout
values. However, Linux epoll_wait/epoll_pwait syscalls use milliseconds
(ms) for timeout. Previously, there was a bug in timeout resolution
because epoll_wait() emulation did not convert from ms to us. This
commit fixes this bug and also adds suffixes "_ms" and "_us" to make the
time units used explicit.
Previously, setup_pal_map() instructed GDB to load symbols for the PAL
shared library using incorrectly formatted string with "0x%p". This led
to addresses of the form "0x0xdeadbeef" which could not be parsed by
GDB. This commit fixes this via "%p" and thus enables SGX-GDB again.
If the path of allowed directory in a manifest file ended with a '/'
e.g. "sgx.allowed_files.tmp_dir = file:tmp/" anything inside it was
disallowed due to a buggy subdirectory check
Introduce PAL_TCB common structure for Linux and Linux-SGX PALs such
that LibOS can stash its tcb into PAL_TCB. This commit is a preparation
for statically-linked binary support where the LibOS tcb can be embedded
into per-application-thread structure.
Additionally, SHIM_TCB_USE_GS is introduced as a compile-time option to
enable/disable this feature.
This commit removes the following from the master Graphene branch (this
is now moved to the EXPERIMENTAL/linux-reference-monitor branch):
- Remove reference monitor loader code
- Remove sandboxing code and dependency to reference monitor code
- Remove Linux kernel changes for reference monitor
- Remove README instructions and scripts regarding reference monitor
dir_read() never updated handle->dir.ptr and handle->dir.end which
effectively disallowed multipart responses. This commit rewrites
this function to handle multiple reads from one handle and also
use less memory.
SGX PAL-level functions like _DkSystemTimeQuery() assume that
ocall_gettime() does not return EINTR. Thus, this commit forces
this ocall to loop on EINTR.
To avoid vfork child from corrupting parent's memory, block async
signal before vfork(). Children unblock async signal after execve in
{sgx_}signal_setup().
Previously, both DkProcessExit() and DkThreadExit() used SGX OCALL
ocall_exit(exitcode), which finally issued exit() syscall. This is
incorrect because DkProcessExit() must exit the whole process and not
just a single thread. This led to abandoned IPC/Async helper threads
in some Graphene-SGX corner cases. This commit forces DkProcessExit()
to result in exit_group() syscall, achieved by adding a new argument
to ocall_exit(exitcode, is_exitgroup).
OCALL functions should return -ERRNO on errors:
- on signals/interrupts, return -EINTR instead of -PAL_ERROR_INTERRUPTED;
- on host-OS syscalls, return -ERRNO(ret) instead of -PAL_ERROR_DENIED;
- on no-available-threads, return -EINVAL instead of -PAL_ERROR_INVAL.
With vfork(), parent and child share the same stack. The child must not
modify the parent's stack frame (otherwise parent's local variables are
corrupted). To circumvent this, this commit introduces a dedicated noinline
function to have a stack frame local to the child. (This bug was hit on
GCC 8 which reuses the same stack location for local variables with disjoint
lifetimes.)
With vfork(), parent and child share the same stack. The child must not
modify the parent's stack frame (otherwise parent's local variables are
corrupted). To circumvent this, this commit introduces a dedicated noinline
function to have a stack frame local to the child. (This bug was hit on
GCC 8 which reuses the same stack location for local variables with disjoint
lifetimes.)
Tiny bug fixes in enclave_entry.S to clear registers:
- Do not clear %r11 twice before EEXIT
- Simulate CLD (by manually clearing DF flag stored in SGX_GPR_RFLAGS)
on interrupt just after EENTER returning from ocall
- Simulate CLD (by manually clearing DF flag stored in SGX_GPR_RFLAGS)
on preparation for exception handler _DkExceptionHandler()