mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 22:01:29 +00:00
[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:
committed by
Dmitrii Kuvaiskii
parent
16d90cfe12
commit
c4bcf4ae8c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user