- Make assert() a no-op in non-debug builds.
- Use static_assert for compile-time asserts.
- Fix assert() implementation (previous version didn't work for
expressions with types larger than long, it also always printed
`(value:0)`).
- Clean up calls to asserts.
This commit concerns web-server examples: Apache, Nginx, and Lighttpd.
Previously, benchmark-http.sh bash script was located under lighttpd
directory, and Apache and Nginx had symbolic links to it. This is
unintuitive. This commit moves benchmark-http.sh to a newly created
common_tools directory, and all web-server examples have symbolic links
to this new dir.
Previously, Linux PAL set SO_LINGER with a zero timeout before closing
the socket. Among other things, this led to ab (ApacheBench) reporting
failed requests when running nginx/lighttpd on Graphene, because the TCP
connection was not closed cleanly. This commit removes setting
SO_LINGER, similarly to Linux-SGX PAL.
In test_user_memory(), a memory range is tested via probing of each page
in the range. If the memory page was not allocated, it leads to a
segfault which is captured by the LibOS memfault_upcall() and reported
in the variable tcb.test_range.has_fault. However, the compiler may
optimize away accesses to this variable in test_user_memory(), believing
it is never updated anywhere else. This commit introduces a memory
barrier to prevent this compiler optimization (same for test_user_string()).
Previously, sgx.static_address was not recorded in generated
.manifest.sgx for PIE executables. The value is 0 by default, this
change only makes it explicit.
- Avoid opening manifest file twice
If the specified file is a manifest, its fd can be sent to load_enclave()
directly.
- Kill hard-coding constant
Use static_strlen(foo) instead.
- Add error handling
Check the return value of alloc_concat(), and use strendswith() to prevent
from buffer underflow caused by short base name of input file path.
- Enhance readability
Include renaming variables and comment changes.
After the Linux PAL frees the thread's signal stack and TCB but before
the thread is actually destroyed by Linux, an arriving async signal on
this thread will result in a segfault. This commit simply blocks all
async signals before proceeding with freeing thread's resources.
_DkVirtualMemoryAlloc() can allocate memory overlapping with
pal_control.user_address. In this case, thread stack could get corrupted
by LibOS, typically resulting in SEGV.
Previously, Graphene explicitly incremented refcount of a handle added
to/removed from epoll, in epoll_ctl(EPOLL_CTL_ADD/EPOLL_CTL_DEL).
However, according to epoll(7), closing a file descriptor causes the
FD (handle) to be removed from all epoll sets. In other words,
adding/removing a handle to/from epoll must not count towards refcount
of the handle. Otherwise the handle remains dangling in the epoll set
even if it was close()'d (this particular case led to Nginx segfault).
This commit removes get/put of handle during epoll add/remove.
Typically, listen() is called only once by the application, to mark the
socket as passive for listening for client connections. Thus, LibOS had
a state machine that forbade performing repeated listen() syscalls on
the same socket. However, at least Nginx issues repeated listen's to
adjust the backlog parameter. This commit allows such corner cases.
For detection of SGX/non-SGX (for example in regression tests) always
use the SGX environment variable. To generate launch/EINIT tokens use
the new 'sgx-tokens' Make target.
If we include dependencies in a Makefile for which a target exists
(currently this only affects the manifest.sgx.d targets) then Make will
generate them and then clean will delete them ... so just don't include
them on clean.
For this also add the user_address_hole memory range to pal_control.
This is needed to communicate (in a not SGX specific way) the reserved
memory range for the memory gaps around the exec area which can be
inside of the user_address range.
Before argv[0] was treated specially and was changed to a value
from manifest file. Now this happens only if binary was run as
a manifest i.e. `./pal_loader path_to_manifest_file`.
Previously, Makefile.rules specified the absolute path to pal-symbols
file via recursive assignment ("="). However, because Makefile.rules
is included from other Makefiles, this led to incorrect path
("graphene/Pal/src/host/Linux/Pal/src/pal-symbols"). This commit
replaces recursive assignment "=" with simple only-once ":=".
Previously, DkReceiveHandle() reset the file offset in the child after
fork(). This is incorrect behavior, since the child must retain the file
offset the same as in the parent. This commit removes the resetting logic.
Previously, read()/write() for both trusted and allowed files were
emulated in the same manner: using mmap/memcpy/munmap. This led to
insidious data races in multi-process applications like Apache: one
process would mmap a file and access it during read/write emulation,
while another process would ftruncate the same file (this leads to
SIGBUS as per mmap man page). This happens even for allowed files which
do not require the complicated mmap/memcpy/munmap emulation (this logic
was introduced primarily for trusted-file checksum verification).
This commit separates the emulation of trusted files and allowed files.
The former still use mmap/memcpy/munmap (slightly optimized for
performance), the latter use lseek+read/write (similar to Linux PAL).
This requires new OCALL ocall_lseek(). Also, writing to trusted files
is now explicitly disallowed.
This commit rewrites pal-sgx-get-token and pal-sgx-sign in Python3 and
performs a comprehensive cleanup of the code:
- Outputs are sent to separate files (otherwise they were intermixed
during parallel build)
- aesm_pb2.py is re-generated to Python3
- Numeric constants are replaced with symbolic ones
- Using argparse instead of home-grown argument parsing
- Replacing home-grown helper funcs int_to_bytes(), bytes_to_int(), etc.
with standard functions
Previously, ocall_write() and ocall_sock_send() disallowed to write/send
data from a buffer allocated in untrusted memory (as it was considered
an impossible scenario). However, sendfile() logic may write an allowed
regular file (which is mmapped in untrusted memory) directly to a socket.
Thus, this commit allows such writes/sends.
Previously, ocall_sock_recv() and ocall_sock_recv_fd() had a bug exposed
when the underlying host recv/recvmsg syscall returned 0. Return value
of 0 led to sgx_copy_to_enclave() to also return 0 which is treated as
EPERM error. This commit omits calls to sgx_copy_to_enclave() when
return value is 0 (since there is nothing to copy anyway).
The parser logic checks the arguments of syscalls and prints strings in
debug output. Previously, our code base only contained "const char *" as
strings. Recently, we started migration to "const char*" (no-space) style.
This broke the parser logic, so this commit adds an additional check on
what it means for a C type to be a string.