[LibOS] Add logic for SS_DISABLE and SS_ONSTACK in sigaltstack()

This commit also adds LibOS regression test for sigaltstack(). This
test is currently disabled (signal delivery on sigaltstack is not yet
implemented).
This commit is contained in:
Isaku Yamahata
2019-05-23 16:25:06 -07:00
committed by Dmitrii Kuvaiskii
parent 16d90cfe12
commit c4bcf4ae8c
5 changed files with 177 additions and 11 deletions
+4
View File
@@ -34,6 +34,8 @@
#include <pal.h>
#include <list.h>
#include <linux/signal.h>
static IDTYPE tid_alloc_idx __attribute_migratable = 0;
static LISTP_TYPE(shim_thread) thread_list = LISTP_INIT;
@@ -163,6 +165,8 @@ struct shim_thread * alloc_new_thread (void)
INIT_LIST_HEAD(thread, siblings);
INIT_LISTP(&thread->exited_children);
INIT_LIST_HEAD(thread, list);
/* default value as sigalt stack isn't specified yet */
thread->signal_altstack.ss_flags = SS_DISABLE;
return thread;
}
+27 -6
View File
@@ -160,16 +160,37 @@ int shim_do_sigaltstack (const stack_t * ss, stack_t * oss)
struct shim_thread * cur = get_cur_thread();
lock(&cur->lock);
stack_t * cur_ss = &cur->signal_altstack;
if (oss)
*oss = cur->signal_altstack;
*oss = *cur_ss;
void * sp = shim_get_tls()->context.sp;
/* check if thread is currently executing on an active altstack */
if (!(cur_ss->ss_flags & SS_DISABLE) &&
sp &&
cur_ss->ss_sp <= sp &&
sp < cur_ss->ss_sp + cur_ss->ss_size) {
if (oss)
oss->ss_flags |= SS_ONSTACK;
if (ss) {
unlock(&cur->lock);
return -EPERM;
}
}
if (ss) {
if (ss->ss_size < MINSIGSTKSZ) {
unlock(&cur->lock);
return -ENOMEM;
}
if (ss->ss_flags & SS_DISABLE) {
memset(cur_ss, 0, sizeof(*cur_ss));
cur_ss->ss_flags = SS_DISABLE;
} else {
if (ss->ss_size < MINSIGSTKSZ) {
unlock(&cur->lock);
return -ENOMEM;
}
cur->signal_altstack = *ss;
*cur_ss = *ss;
}
}
unlock(&cur->lock);
@@ -0,0 +1,29 @@
import sys
from regression import Regression
loader = sys.argv[1]
# Running sigaltstack
regression = Regression(loader, "sigaltstack")
messages = (
"OK on sigaltstack in main thread before alarm",
"&act == 0x",
"sig 14 count 1 goes off with sp=0x",
"OK on signal stack",
"OK on sigaltstack in handler",
"sig 14 count 2 goes off with sp=0x",
"OK on signal stack",
"OK on sigaltstack in handler",
"sig 14 count 3 goes off with sp=0x",
"OK on signal stack",
"OK on sigaltstack in handler",
"OK on sigaltstack in main thread",
"done exiting",
)
regression.add_check(name="Sigaltstack Test",
check=lambda res: all([x in res[0].out for x in messages]))
rv = regression.run_checks()
if rv: sys.exit(rv)
+9 -5
View File
@@ -52,18 +52,22 @@ ifeq ($(SGX_RUN),1)
PYTHONENV += "TIMEOUT=20000"
endif
# 30_sigaltstack.py fails because sigaltstack isn't correctly implemented.
BLOCKED_TESTS = \
30_sigaltstack.py
get_tests = $(filter-out $(BLOCKED_TESTS),$(wildcard $(1)))
.PHONY: regression
regression: $(target)
@echo "\n\nBasic Bootstrapping:"
@for f in $(wildcard 00_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@for f in $(call get_tests,00_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@echo "\n\nSyscall Support:"
@for f in $(wildcard 30_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@for f in $(call get_tests,30_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@echo "\n\nFile System Support:"
@for f in $(wildcard 40_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@for f in $(call get_tests,40_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@echo "\n\nSocket Support:"
@for f in $(wildcard 80_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@for f in $(call get_tests,80_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@echo "\n\nLarge File Support:"
@for f in $(wildcard 90_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
@for f in $(call get_tests,90_*.py); do env $(PYTHONENV) python3 $$f $(RUNTIME)/pal-$(PAL_HOST) || exit $$?; done
.PHONY: clean-tmp
clean-tmp:
+108
View File
@@ -0,0 +1,108 @@
#include <err.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
uint8_t* sig_stack;
size_t sig_stack_size = SIGSTKSZ;
_Atomic int count = 0;
void handler(int signal, siginfo_t* info, void* ucontext) {
int ret;
count++;
uint8_t a;
printf("sig %d count %d goes off with sp=%p, sig_stack: [%p, %p)\n", signal, count, &a,
sig_stack, sig_stack + sig_stack_size);
if (sig_stack <= &a && &a < sig_stack + sig_stack_size) {
printf("OK on signal stack\n");
} else {
printf("FAIL out of signal stack\n");
}
fflush(stdout);
stack_t old;
memset(&old, 0, sizeof(old));
ret = sigaltstack(NULL, &old);
if (ret < 0) {
err(EXIT_FAILURE, "sigaltstack in handler");
}
if (old.ss_flags & SS_ONSTACK) {
printf("OK on sigaltstack in handler\n");
} else {
printf("FAIL on sigaltstack in handler\n");
}
/*
* raise SIGALRM during signal handling to test nested signals
* (three-levels deep nesting just to be sure)
*/
if (count <= 2) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
ret = sigprocmask(SIG_UNBLOCK, &set, NULL);
if (ret) {
err(EXIT_FAILURE, "sigprocmask");
}
raise(SIGALRM);
}
count--;
}
int main(int argc, char** argv) {
int ret;
sig_stack = malloc(sig_stack_size);
if (sig_stack == NULL) {
err(EXIT_FAILURE, "malloc");
}
stack_t ss = {
.ss_sp = sig_stack,
.ss_flags = 0,
.ss_size = sig_stack_size,
};
stack_t old;
memset(&old, 0xff, sizeof(old));
ret = sigaltstack(&ss, &old);
if (ret < 0) {
err(EXIT_FAILURE, "sigaltstack");
}
if (old.ss_flags & SS_ONSTACK) {
printf("FAIL on sigaltstack in main thread before alarm\n");
} else {
printf("OK on sigaltstack in main thread before alarm\n");
}
struct sigaction act;
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
ret = sigaction(SIGALRM, &act, NULL);
if (ret < 0) {
err(EXIT_FAILURE, "sigaction");
}
printf("&act == %p\n", &act);
fflush(stdout);
alarm(1);
pause();
memset(&old, 0xff, sizeof(old));
ret = sigaltstack(NULL, &old);
if (ret < 0) {
err(EXIT_FAILURE, "sigaltstack");
}
if (old.ss_flags & SS_ONSTACK) {
printf("FAIL on sigaltstack in main thread\n");
} else {
printf("OK on sigaltstack in main thread\n");
}
printf("done exiting\n");
fflush(stdout);
return 0;
}