enable stack protector for Pal/Linux.
for other Pal, enabling stack protector results in error.
Signed-off-by: Isaku Yamahata <isaku.yamahata@gmail.com>
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.
chroot_readdir() tried to allocate a buffer big enough to hold all
entries, by calling DkStreamRead until it succeeded (increasing buffer
size otherwise). However, DkStreamRead could return partial results,
which was never handled (partial result means here it could return
just some objects, not a part of individual object). This commit fixes
this issue and refactors this function.
SGX PAL-level functions like _DkSystemTimeQuery() assume that
ocall_gettime() does not return EINTR. Thus, this commit forces
this ocall to loop on EINTR.
Disallow user program to mmap outside the allowed user address range.
This is especially important for Linux-SGX PAL, since all user-program
memory must be allocated inside of the enclave range (ELRANGE). For
other PALs like Linux and FreeBSD, we probably should enhance PAL
interface (pal_control.user_address) to specify a more meaningful range
(currently the range is from minimal allowed address to address of the
code segment of the PAL library).
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, sigsuspend(), pause(), and nanosleep() syscalls did not
check for pending signals before waiting on signals. This commit adds
this logic, similar to how this is implemented in Linux. This fixes data
races in regression tests relying on these syscalls (killXX in ltp).
Previous implementation of vfork() was both buggy (worked only in simple
cases) and not compatible with the new IPC implementation. We take a
shortcut for now and emulate vfork() via fork(); this is allowed by
POSIX. This commit also adds LibOS regression test for vfork().
Sometimes apps are built with the ELF header containing OS ABI ==
ELFOSABI_LINUX (GCC is one example). Previously, LibOS dynamic loader
only allowed OS ABI == ELFOSABI_SYSV (most apps are built with it) and
failed on ELFOSABI_LINUX. This commit teaches LibOS loader to accept
ELFOSABI_LINUX binaries and removes some redundant checks on ELF header.
New implementation is now in line with dynamic loader of PAL.
Previously, Graphene incorrectly treated execve() under SGX PAL:
Graphene would emulate execve() as fork + execve, and the new forked
process didn't try to "assume" the identity of its parent (which
violated execve specification "all process attributes are preserved").
This commit reworks the implementations of clone/fork and execve. In
particular, the IPC subsystem clearly distinguishes between the two
cases: clone/fork works as before whereas execve forks new "real"
process (which starts executing the requested program) and silently
exits the now-useless "temporary" process. New "real" process assumes
the identity of "temporary" process by inheriting its VMID (ID of
process for IPC purposes) and IPC-info objects with their PAL handles.
This commit also cleans up initialization of four IPC-info objects: self
(creates process-unique server pipe for IPC), parent (holds pipe for IPC
with parent process), and two namespace leaders (hold pipes for IPC with
leader processes). To correctly identify new-process server pipe, the
implementation of create_pipe() now allows to create VMID-based pipe URI.
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).
This commit adds default signal dispositions (as per Linux) to all 32
standard signals. It also adds WCOREDUMP bit to correctly inform wait4()
status word.
This commit updates graphene-tests submodules to enable new killXX LTP
regression tests, as well as fix the waitpid05 LTP test. It is important
to update this submodule reference in this commit because otherwise
waitpid05 tests will fail Graphene's CI.
This commit adds additional logic around DkStreamWrite() and
DkStreamRead() in send_ipc_message() and receive_ipc_message()
respectively: interrupts and partial reads/writes are handled correctly.
Previously, when a thread exited via thread_exit(), it could send two
identical IPC_CLD_EXIT messages under certain conditions. This commit
fixes this bug and forces thread_exit() to send IPC_CLD_EXIT at most once.
Previously, the IPC subsystem incorrectly sent IPC_PID_KILL message
(generated as part of kill() syscall) as a duplex message, i.e., the
sender thread (the one issuing kill()) was paused until the receiving
child process handled IPC_PID_KILL callback and sent the acknowledgement
reply message back to sender.
This incorrect logic created a data race between the IPC_PID_KILL ack
message and the exiting child process. In particular, the child could
exit and all its resources (including IPC port to communicate with
parent) could be reclaimed by host OS. This could lead to IPC_PID_KILL
ack message being lost (because of the closed IPC port), and the paused
parent thread would wake up with -ECONNRESET instead of the ack message.
This would lead the kill() implementation to believe that child process
never existed in the first place and to return -ESRCH.
The fix to this data race is to send IPC_PID_KILL without waiting for
acknowledgement. Specification of kill() syscall does not require it to
be synchronous (indeed it is not on Linux), so this fix is correct. This
fix also enabled to merge broadcast_signal() into ipc_pid_kill_send().
Previously, there was an incorrect corner case during discovering of the
current namespace leader. If the parent process would exit before the
child, the child process would fail on sending FINDNS message to the
parent (because of closed parent socket). The previous code logic would
assume that since NS_LEADER is set to some value, the leader process
exists. In reality, the child loses the only source of information about
the leader process (note that FINDNS is sent only to the parent), so the
only meaningful action is to set myself as the new leader.
- Changed type of shim_ipc_msg.size from int to size_t.
- Renamed shim_ipc_msg_obj to shim_ipc_msg_duplex for readability.
- Simplified function signatures and changed to better names.
- Removed unused IPC_FINDURI & IPC_TELLURI and corresponding functions.
- Replaced macros IPC_MSG_SIZE & IPC_MSGOBJ_SIZE with inline functions.
- Removed dangerous create_xxx_on_stack() functions and changed all
invocations to have explicit __alloca's. Those functions relied on
being inlined in the callers otherwise their created objects would
become corrupted. Explicit __alloca's avoid this brittle
implementation and make object ownership clear.
- Removed unnecessary wrapper function do_ipc_duplex(), replacing it
with send_ipc_message_duplex().
- Removed unnecessary macros (IPC_PORT_IFPOLL, DEBUG_REF, etc).
- Simplified function signatures and changed to better names.
- Removed unused functions (del_ipc_port, del_ipc_port_by_id).
- Malloc instead of huge stack allocations.
- Removed complex logic of exit_with_ipc_helper(), now IPC thread exits
similarly to Async helper thread.
- Removed ipc_port_pool hash list (used as perf optimization but
providing no tangible benefit at the cost of high complexity).
- Simplified IPC helper thread states to only ALIVE & NOTALIVE.
- Removed unused broadcast_port.
- Reworked IPC helper thread's while-loop similarly to Async helper
thread; removed perf optimization of keeping the same list of ports to
listen on DkObjectsWaitAny(), instead simply repopulate this list
every time (may become too slow if lots of IPC on hundreds of ports).
Compilation of bookkeep/shim_signal.c:__handle_one_signal() under GCC8
failed with cast-function-type error on k_sa_handler assignment to
handler. This commit fixes this error via cast to void*.
This commit adds vDSO support: creates vDSO memory region which contains
necessary symbols __vdso_{gettimeofday, clock_getime, time, getcpu} with
wrappers to call function pointers with actual LibOS implementation.
On startup, function pointers are setup to point to actual functions.
With this commit, the Glibc modification to not use vDSO can be removed.
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.