Merge pull request #318 from gwsystems/sigfpe-wasm-trap

feat: sigfpe and sigsegv wasm traps
master
Sean McBride 3 years ago committed by GitHub
commit cac0b32520
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -182,3 +182,7 @@ jobs:
run: |
make -f test.mk trap_divzero
if: success() || failure()
- name: Wasm Trap Stack Overflow
run: |
make -f test.mk stack_overflow
if: success() || failure()

@ -82,3 +82,6 @@ license_plate_detection.install: ../runtime/bin/license_plate_detection.wasm.so
.PHONY: trap_divzero.install
trap_divzero.install: ../runtime/bin/trap_divzero.wasm.so
.PHONY: stack_overflow.install
stack_overflow.install: ../runtime/bin/stack_overflow.wasm.so

@ -1 +1 @@
Subproject commit 8a97541b83373b5f30306f569515326dee4c1f2a
Subproject commit f6d07455676a1a5cb64b03276c9b4985ef721451

@ -19,11 +19,6 @@ get_f32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(float)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -32,11 +27,6 @@ get_f64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(double)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -45,11 +35,6 @@ get_i8(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int8_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -58,11 +43,6 @@ get_i16(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int16_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -71,11 +51,6 @@ get_i32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int32_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -84,11 +59,6 @@ get_i64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int64_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -98,11 +68,6 @@ set_f32(uint32_t offset, float value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(float)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -111,11 +76,6 @@ set_f64(uint32_t offset, double value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(double)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -124,11 +84,6 @@ set_i8(uint32_t offset, int8_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int8_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -137,11 +92,6 @@ set_i16(uint32_t offset, int16_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int16_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -150,11 +100,6 @@ set_i32(uint32_t offset, int32_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int32_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -163,11 +108,6 @@ set_i64(uint32_t offset, int64_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int64_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}

@ -54,60 +54,48 @@ rotr_u64(uint64_t n, uint64_t c_u64)
INLINE uint32_t
u32_div(uint32_t a, uint32_t b)
{
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE uint32_t
u32_rem(uint32_t a, uint32_t b)
{
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE int32_t
i32_div(int32_t a, int32_t b)
{
if (unlikely(b == 0 || (a == INT32_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE int32_t
i32_rem(int32_t a, int32_t b)
{
if (unlikely(b == 0 || (a == INT32_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE uint64_t
u64_div(uint64_t a, uint64_t b)
{
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE uint64_t
u64_rem(uint64_t a, uint64_t b)
{
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE int64_t
i64_div(int64_t a, int64_t b)
{
if (unlikely(b == 0 || (a == INT64_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE int64_t
i64_rem(int64_t a, int64_t b)
{
if (unlikely(b == 0 || (a == INT64_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}

@ -107,5 +107,5 @@ current_sandbox_trap(enum sledge_abi__wasm_trap trapno)
assert(sandbox != NULL);
assert(sandbox->state == SANDBOX_RUNNING_USER || sandbox->state == SANDBOX_RUNNING_SYS);
longjmp(sandbox->ctxt.start_buf, trapno);
siglongjmp(sandbox->ctxt.start_buf, trapno);
}

@ -31,7 +31,7 @@ software_interrupt_mask_signal(int signal)
sigset_t set;
int return_code;
assert(signal == SIGALRM || signal == SIGUSR1);
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV);
/* all threads created by the calling thread will have signal blocked */
sigemptyset(&set);
sigaddset(&set, signal);
@ -55,7 +55,7 @@ software_interrupt_unmask_signal(int signal)
sigset_t set;
int return_code;
assert(signal == SIGALRM || signal == SIGUSR1);
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV);
/* all threads created by the calling thread will have signal unblocked */
sigemptyset(&set);
sigaddset(&set, signal);

@ -10,6 +10,8 @@ extern _Atomic volatile sig_atomic_t *software_interrupt_counts_deferred_sigalrm
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_deferred_sigalrm_replay;
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_sigalrm_kernel;
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_sigalrm_thread;
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_sigfpe;
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_sigsegv;
extern _Atomic volatile sig_atomic_t *software_interrupt_counts_sigusr;
static inline void
@ -20,6 +22,8 @@ software_interrupt_counts_alloc()
software_interrupt_counts_deferred_sigalrm_replay = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
software_interrupt_counts_sigalrm_kernel = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
software_interrupt_counts_sigalrm_thread = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
software_interrupt_counts_sigfpe = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
software_interrupt_counts_sigsegv = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
software_interrupt_counts_sigusr = calloc(runtime_worker_threads_count, sizeof(sig_atomic_t));
#endif
}
@ -29,8 +33,11 @@ software_interrupt_counts_free()
{
#ifdef LOG_SOFTWARE_INTERRUPT_COUNTS
free((void *)software_interrupt_counts_deferred_sigalrm_max);
free((void *)software_interrupt_counts_deferred_sigalrm_replay);
free((void *)software_interrupt_counts_sigalrm_kernel);
free((void *)software_interrupt_counts_sigalrm_thread);
free((void *)software_interrupt_counts_sigfpe);
free((void *)software_interrupt_counts_sigsegv);
free((void *)software_interrupt_counts_sigusr);
#endif
}
@ -69,6 +76,22 @@ software_interrupt_counts_sigalrm_thread_increment()
#endif
}
static inline void
software_interrupt_counts_sigfpe_increment()
{
#ifdef LOG_SOFTWARE_INTERRUPT_COUNTS
atomic_fetch_add(&software_interrupt_counts_sigfpe[worker_thread_idx], 1);
#endif
}
static inline void
software_interrupt_counts_sigsegv_increment()
{
#ifdef LOG_SOFTWARE_INTERRUPT_COUNTS
atomic_fetch_add(&software_interrupt_counts_sigsegv[worker_thread_idx], 1);
#endif
}
static inline void
software_interrupt_counts_sigusr_increment()
{

@ -225,7 +225,7 @@ current_sandbox_start(void)
{
struct sandbox *sandbox = current_sandbox_init();
int rc = setjmp(sandbox->ctxt.start_buf);
int rc = sigsetjmp(sandbox->ctxt.start_buf, 1);
if (rc == 0) {
struct module *current_module = sandbox_get_module(sandbox);
sandbox->return_value = module_entrypoint(current_module);

@ -27,5 +27,5 @@ sledge_abi__current_wasm_module_instance_trap(enum sledge_abi__wasm_trap trapno)
assert(sandbox != NULL);
assert(sandbox->state == SANDBOX_RUNNING_USER || sandbox->state == SANDBOX_RUNNING_SYS);
longjmp(sandbox->ctxt.start_buf, trapno);
siglongjmp(sandbox->ctxt.start_buf, trapno);
}

@ -1066,7 +1066,7 @@ wasi_snapshot_preview1_backing_proc_exit(wasi_context_t *context, __wasi_exitcod
{
struct sandbox *s = current_sandbox_get();
s->return_value = exitcode;
longjmp(s->ctxt.start_buf, WASM_TRAP_EXIT);
siglongjmp(s->ctxt.start_buf, WASM_TRAP_EXIT);
}
/**

@ -103,9 +103,6 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
/* Only workers should receive signals */
assert(!listener_thread_is_running());
/* Signals should be masked if runtime has disabled them */
assert(runtime_preemption_enabled);
/* Signals should not nest */
assert(handler_depth == 0);
atomic_fetch_add(&handler_depth, 1);
@ -115,6 +112,8 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
switch (signal_type) {
case SIGALRM: {
assert(runtime_preemption_enabled);
if (worker_thread_is_running_cooperative_scheduler()) {
/* There is no benefit to deferring SIGALRMs that occur when we are already in the cooperative
* scheduler, so just propagate and return */
@ -135,6 +134,7 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
break;
}
case SIGUSR1: {
assert(runtime_preemption_enabled);
assert(current_sandbox);
assert(current_sandbox->state == SANDBOX_PREEMPTED);
assert(current_sandbox->ctxt.variant == ARCH_CONTEXT_VARIANT_SLOW);
@ -149,6 +149,30 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
break;
}
case SIGFPE: {
software_interrupt_counts_sigfpe_increment();
if (likely(current_sandbox && current_sandbox->state == SANDBOX_RUNNING_USER)) {
atomic_fetch_sub(&handler_depth, 1);
current_sandbox_trap(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
} else {
panic("Runtime SIGFPE\n");
}
break;
}
case SIGSEGV: {
software_interrupt_counts_sigsegv_increment();
if (likely(current_sandbox && current_sandbox->state == SANDBOX_RUNNING_USER)) {
atomic_fetch_sub(&handler_depth, 1);
current_sandbox_trap(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
} else {
panic("Runtime SIGSEGV\n");
}
break;
}
default: {
const char *signal_name = strsignal(signal_type);
switch (signal_info->si_code) {
@ -231,9 +255,11 @@ software_interrupt_initialize(void)
sigemptyset(&signal_action.sa_mask);
sigaddset(&signal_action.sa_mask, SIGALRM);
sigaddset(&signal_action.sa_mask, SIGUSR1);
sigaddset(&signal_action.sa_mask, SIGFPE);
sigaddset(&signal_action.sa_mask, SIGSEGV);
const int supported_signals[] = { SIGALRM, SIGUSR1 };
const size_t supported_signals_len = 2;
const int supported_signals[] = { SIGALRM, SIGUSR1, SIGFPE, SIGSEGV };
const size_t supported_signals_len = 4;
for (int i = 0; i < supported_signals_len; i++) {
int signal = supported_signals[i];

@ -59,6 +59,9 @@ worker_thread_main(void *argument)
worker_thread_epoll_file_descriptor = epoll_create1(0);
if (unlikely(worker_thread_epoll_file_descriptor < 0)) panic_err();
software_interrupt_unmask_signal(SIGFPE);
software_interrupt_unmask_signal(SIGSEGV);
/* Unmask signals, unless the runtime has disabled preemption */
if (runtime_preemption_enabled) {
software_interrupt_unmask_signal(SIGALRM);

@ -122,6 +122,13 @@ PHONY: trap_divzero
trap_divzero: ./runtime/bin/trap_divzero.wasm.so
cd ./tests/traps/ && ./run.sh
./runtime/bin/stack_overflow.wasm.so:
make stack_overflow.install -C ./applications
PHONY: stack_overflow
stack_overflow: ./runtime/bin/stack_overflow.wasm.so
cd ./tests/stack_overflow/ && ./run.sh
all: \
gocr__all \
ekf__all \

@ -0,0 +1,4 @@
*res.dat
rt.log
log.csv
res/*

@ -0,0 +1,38 @@
RUNTIME_DIR=../../runtime/
SLEDGE_BINARY_DIR=${RUNTIME_DIR}/bin
SLEDGE_TESTS_DIR=${RUNTIME_DIR}/tests
HOSTNAME=localhost
DURATION_SEC=15
all: run
clean:
make -C ${RUNTIME_DIR} clean
make -C ${SLEDGE_TESTS_DIR} clean
rm -f ${SLEDGE_BINARY_DIR}/stack_overflow.wasm.so
${SLEDGE_BINARY_DIR}/sledgert:
make -C ${RUNTIME_DIR} runtime
.PHONY: sledgert
sledgert: ${SLEDGE_BINARY_DIR}/sledgert
${SLEDGE_BINARY_DIR}/stack_overflow.wasm.so:
make -C ../../applications stack_overflow.install
.PHONY: stack_overflow
stack_overflow: ${SLEDGE_BINARY_DIR}/stack_overflow.wasm.so
run: sledgert stack_overflow
LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} ${SLEDGE_BINARY_DIR}/sledgert spec.json
debug: sledgert stack_overflow
SLEDGE_DISABLE_PREEMPTION=true SLEDGE_NWORKERS=1 \
LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} gdb ${SLEDGE_BINARY_DIR}/sledgert \
--eval-command="handle SIGUSR1 noprint nostop" \
--eval-command="handle SIGPIPE noprint nostop" \
--eval-command="set pagination off" \
--eval-command="run spec.json"
client:
http :10000

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,3 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=false
SLEDGE_SIGALRM_HANDLER=TRIAGED

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=false

@ -0,0 +1,28 @@
#!/bin/bash
__run_sh__base_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
__run_sh__bash_libraries_relative_path="../bash_libraries"
__run_sh__bash_libraries_absolute_path=$(cd "$__run_sh__base_path" && cd "$__run_sh__bash_libraries_relative_path" && pwd)
export PATH="$__run_sh__bash_libraries_absolute_path:$PATH"
source framework.sh || exit 1
source validate_dependencies.sh || exit 1
experiment_client() {
local -r hostname="$1"
for ((i = 1; i <= 10; i++)); do
http -p h "${hostname}:10000" | grep 500 || {
echo "FAIL"
return 1
}
done
echo "SUCCESS"
return 0
}
validate_dependencies http
framework_init "$@"

@ -0,0 +1,13 @@
[
{
"name": "stack_overflow",
"path": "stack_overflow.wasm.so",
"port": 10000,
"expected-execution-us": 10000000,
"admissions-percentile": 70,
"relative-deadline-us": 20000000,
"http-req-size": 1024,
"http-resp-size": 1024,
"http-resp-content-type": "text/plain"
}
]

@ -18,7 +18,7 @@ ${SLEDGE_BINARY_DIR}/sledgert:
sledgert: ${SLEDGE_BINARY_DIR}/sledgert
${SLEDGE_BINARY_DIR}/trap_divzero.wasm.so:
make -C ../../../applications trap_divzero.install
make -C ../../applications trap_divzero.install
.PHONY: trap_divzero
trap_divzero: ${SLEDGE_BINARY_DIR}/trap_divzero.wasm.so
@ -40,6 +40,9 @@ client-ok:
client-trap:
echo "0" | http :10000
client-trap2:
echo "-1" | http :10000
test:
echo "4" | http :10000
echo "0" | http :10000

Loading…
Cancel
Save