Messages in this thread Patch in this message | | | Subject | [PATCH 1/4] selftests: Add test for sigaltstack(SS_DISABLE) inside sighandler | From | Stas Sergeev <> | Date | Sun, 31 Jan 2016 19:18:31 +0300 |
| |
sigaltstack needs to be disabled before the signal handler can safely use swapcontext(). Unfortunately linux implementation of sigaltstack() returns EPERM in that case. Re-enabling is also needed and tested.
CC: Shuah Khan <shuahkh@osg.samsung.com> CC: linux-kernel@vger.kernel.org CC: linux-api@vger.kernel.org CC: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net> --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/sigaltstack/Makefile | 8 ++ tools/testing/selftests/sigaltstack/sas.c | 132 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 tools/testing/selftests/sigaltstack/Makefile create mode 100644 tools/testing/selftests/sigaltstack/sas.c
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index c8edff6..d5b2005 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -17,6 +17,7 @@ TARGETS += powerpc TARGETS += pstore TARGETS += ptrace TARGETS += seccomp +TARGETS += sigaltstack TARGETS += size TARGETS += static_keys TARGETS += sysctl diff --git a/tools/testing/selftests/sigaltstack/Makefile b/tools/testing/selftests/sigaltstack/Makefile new file mode 100644 index 0000000..56af56e --- /dev/null +++ b/tools/testing/selftests/sigaltstack/Makefile @@ -0,0 +1,8 @@ +CFLAGS = -Wall +BINARIES = sas +all: $(BINARIES) + +include ../lib.mk + +clean: + rm -rf $(BINARIES) diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c new file mode 100644 index 0000000..5d9aabd --- /dev/null +++ b/tools/testing/selftests/sigaltstack/sas.c @@ -0,0 +1,132 @@ +/* + * Stas Sergeev <stsp@users.sourceforge.net> + * + * test sigcontext(SS_DISABLE) inside signal handler + * If that succeeds, then swapcontext() can be used safely. + * + */ + +#define _GNU_SOURCE +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <ucontext.h> +#include <alloca.h> +#include <string.h> +#include <assert.h> + +static void *sstack, *ustack; +static ucontext_t uc, sc; +static const char *msg = "[OK]\tStack preserved"; +static const char *msg2 = "[FAIL]\tStack corrupted"; + +void my_usr1(int sig) +{ + char *aa, *p; + int *i, err; + stack_t stk = { }; + + aa = alloca(1024); + assert(aa); + p = aa + 512; + strcpy(p, msg); + i = (int *) (p + 128); + *i = 1; + printf("[RUN]\tsignal USR1\n"); + stk.ss_flags = SS_DISABLE; + err = sigaltstack(&stk, &stk); + if (err) { + perror("[FAIL]\tsigaltstack(SS_DISABLE)"); + /* don't exit to demonstrate the breakage */ + /* exit(EXIT_FAILURE); */ + } + swapcontext(&sc, &uc); + printf("%s\n", p); + if (!*i) { + printf("[RUN]\tAborting\n"); + exit(EXIT_FAILURE); + } + + if (stk.ss_flags != SS_ONSTACK) { + printf("[FAIL]\tsigaltstack() returned wrong ss_flags %i\n", + stk.ss_flags); + stk.ss_flags = SS_ONSTACK; + } + err = sigaltstack(&stk, NULL); + if (err) + printf("[OK]\tsigaltstack(SS_ONSTACK) failed for non_zero " + "size\n"); + /* but don't fail otherwise, as this is unspecified */ + stk.ss_size = 0; + err = sigaltstack(&stk, NULL); + if (err) + perror("[FAIL]\tsigaltstack(SS_ONSTACK)"); +} + +void my_usr2(int sig) +{ + char *aa, *p; + int *i; + + printf("[RUN]\tsignal USR2\n"); + aa = alloca(1024); + /* dont run valgrind on this */ + p = memmem(aa, 1024, msg, strlen(msg)); + if (p) { + printf("[FAIL]\tsigaltstack re-used\n"); + strcpy(p, msg2); + i = (int *) (p + 128); + *i = 0; + } +} + +static void switch_fn(void) +{ + printf("[RUN]\tswitched to user ctx\n"); + raise(SIGUSR2); + setcontext(&sc); +} + +int main(void) +{ + struct sigaction act; + stack_t stk; + int err; + + sigemptyset(&act.sa_mask); + act.sa_flags = SA_ONSTACK; + act.sa_handler = my_usr1; + sigaction(SIGUSR1, &act, NULL); + act.sa_handler = my_usr2; + sigaction(SIGUSR2, &act, NULL); + sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (sstack == MAP_FAILED) { + perror("mmap()"); + return EXIT_FAILURE; + } + stk.ss_sp = sstack; + stk.ss_size = SIGSTKSZ; + stk.ss_flags = SS_ONSTACK; + err = sigaltstack(&stk, NULL); + if (err) { + perror("sigaltstack()"); + return EXIT_FAILURE; + } + + ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (ustack == MAP_FAILED) { + perror("mmap()"); + return EXIT_FAILURE; + } + getcontext(&uc); + uc.uc_link = NULL; + uc.uc_stack.ss_sp = ustack; + uc.uc_stack.ss_size = SIGSTKSZ; + makecontext(&uc, switch_fn, 0); + raise(SIGUSR1); + printf("[OK]\tTest passed\n"); + return 0; +} -- 2.5.0
| |