| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- // SPDX-License-Identifier: GPL-2.0-only
- #define _GNU_SOURCE
- #include <signal.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <string.h>
- #include <err.h>
- #include <errno.h>
- #include <limits.h>
- #include <sys/mman.h>
- #include <sys/auxv.h>
- #include <sys/prctl.h>
- #include <sys/resource.h>
- #include <setjmp.h>
- #include "helpers.h"
- /* sigaltstack()-enforced minimum stack */
- #define ENFORCED_MINSIGSTKSZ 2048
- #ifndef AT_MINSIGSTKSZ
- # define AT_MINSIGSTKSZ 51
- #endif
- static int nerrs;
- static bool sigalrm_expected;
- static unsigned long at_minstack_size;
- static int setup_altstack(void *start, unsigned long size)
- {
- stack_t ss;
- memset(&ss, 0, sizeof(ss));
- ss.ss_size = size;
- ss.ss_sp = start;
- return sigaltstack(&ss, NULL);
- }
- static jmp_buf jmpbuf;
- static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
- {
- if (sigalrm_expected) {
- printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");
- nerrs++;
- } else {
- printf("[OK]\tSIGSEGV signal delivered.\n");
- }
- siglongjmp(jmpbuf, 1);
- }
- static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
- {
- if (!sigalrm_expected) {
- printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");
- nerrs++;
- } else {
- printf("[OK]\tSIGALRM signal delivered.\n");
- }
- }
- static void test_sigaltstack(void *altstack, unsigned long size)
- {
- if (setup_altstack(altstack, size))
- err(1, "sigaltstack()");
- sigalrm_expected = (size > at_minstack_size) ? true : false;
- sethandler(SIGSEGV, sigsegv, 0);
- sethandler(SIGALRM, sigalrm, SA_ONSTACK);
- if (!sigsetjmp(jmpbuf, 1)) {
- printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",
- sigalrm_expected ? "" : "in");
- printf("\tRaise SIGALRM. %s is expected to be delivered.\n",
- sigalrm_expected ? "It" : "SIGSEGV");
- raise(SIGALRM);
- }
- clearhandler(SIGALRM);
- clearhandler(SIGSEGV);
- }
- int main(void)
- {
- void *altstack;
- at_minstack_size = getauxval(AT_MINSIGSTKSZ);
- altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
- if (altstack == MAP_FAILED)
- err(1, "mmap()");
- if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
- test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
- test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
- return nerrs == 0 ? 0 : 1;
- }
|