feat: linear memory OOB via SIGSEGV handler

master
Sean McBride 3 years ago
parent 7ce17ffae1
commit 7a9b2ce938

@ -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;
}

@ -31,7 +31,7 @@ software_interrupt_mask_signal(int signal)
sigset_t set;
int return_code;
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE);
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 || signal == SIGFPE);
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);

@ -11,6 +11,7 @@ extern _Atomic volatile sig_atomic_t *software_interrupt_counts_deferred_sigalrm
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
@ -22,6 +23,7 @@ software_interrupt_counts_alloc()
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
}
@ -35,6 +37,7 @@ software_interrupt_counts_free()
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
}
@ -81,6 +84,14 @@ software_interrupt_counts_sigfpe_increment()
#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()
{

@ -156,12 +156,23 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
atomic_fetch_sub(&handler_depth, 1);
current_sandbox_trap(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
} else {
// Runtime FPE
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) {
@ -245,9 +256,10 @@ software_interrupt_initialize(void)
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, SIGFPE };
const size_t supported_signals_len = 3;
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];

@ -60,6 +60,7 @@ worker_thread_main(void *argument)
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) {

@ -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"
}
]
Loading…
Cancel
Save