Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 #define _GNU_SOURCE
0004 #include <signal.h>
0005 #include <stdio.h>
0006 #include <stdbool.h>
0007 #include <string.h>
0008 #include <err.h>
0009 #include <errno.h>
0010 #include <limits.h>
0011 #include <sys/mman.h>
0012 #include <sys/auxv.h>
0013 #include <sys/prctl.h>
0014 #include <sys/resource.h>
0015 #include <setjmp.h>
0016 
0017 /* sigaltstack()-enforced minimum stack */
0018 #define ENFORCED_MINSIGSTKSZ    2048
0019 
0020 #ifndef AT_MINSIGSTKSZ
0021 #  define AT_MINSIGSTKSZ    51
0022 #endif
0023 
0024 static int nerrs;
0025 
0026 static bool sigalrm_expected;
0027 
0028 static unsigned long at_minstack_size;
0029 
0030 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
0031                int flags)
0032 {
0033     struct sigaction sa;
0034 
0035     memset(&sa, 0, sizeof(sa));
0036     sa.sa_sigaction = handler;
0037     sa.sa_flags = SA_SIGINFO | flags;
0038     sigemptyset(&sa.sa_mask);
0039     if (sigaction(sig, &sa, 0))
0040         err(1, "sigaction");
0041 }
0042 
0043 static void clearhandler(int sig)
0044 {
0045     struct sigaction sa;
0046 
0047     memset(&sa, 0, sizeof(sa));
0048     sa.sa_handler = SIG_DFL;
0049     sigemptyset(&sa.sa_mask);
0050     if (sigaction(sig, &sa, 0))
0051         err(1, "sigaction");
0052 }
0053 
0054 static int setup_altstack(void *start, unsigned long size)
0055 {
0056     stack_t ss;
0057 
0058     memset(&ss, 0, sizeof(ss));
0059     ss.ss_size = size;
0060     ss.ss_sp = start;
0061 
0062     return sigaltstack(&ss, NULL);
0063 }
0064 
0065 static jmp_buf jmpbuf;
0066 
0067 static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
0068 {
0069     if (sigalrm_expected) {
0070         printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");
0071         nerrs++;
0072     } else {
0073         printf("[OK]\tSIGSEGV signal delivered.\n");
0074     }
0075 
0076     siglongjmp(jmpbuf, 1);
0077 }
0078 
0079 static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
0080 {
0081     if (!sigalrm_expected) {
0082         printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");
0083         nerrs++;
0084     } else {
0085         printf("[OK]\tSIGALRM signal delivered.\n");
0086     }
0087 }
0088 
0089 static void test_sigaltstack(void *altstack, unsigned long size)
0090 {
0091     if (setup_altstack(altstack, size))
0092         err(1, "sigaltstack()");
0093 
0094     sigalrm_expected = (size > at_minstack_size) ? true : false;
0095 
0096     sethandler(SIGSEGV, sigsegv, 0);
0097     sethandler(SIGALRM, sigalrm, SA_ONSTACK);
0098 
0099     if (!sigsetjmp(jmpbuf, 1)) {
0100         printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",
0101                sigalrm_expected ? "" : "in");
0102         printf("\tRaise SIGALRM. %s is expected to be delivered.\n",
0103                sigalrm_expected ? "It" : "SIGSEGV");
0104         raise(SIGALRM);
0105     }
0106 
0107     clearhandler(SIGALRM);
0108     clearhandler(SIGSEGV);
0109 }
0110 
0111 int main(void)
0112 {
0113     void *altstack;
0114 
0115     at_minstack_size = getauxval(AT_MINSIGSTKSZ);
0116 
0117     altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
0118             MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
0119     if (altstack == MAP_FAILED)
0120         err(1, "mmap()");
0121 
0122     if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
0123         test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
0124 
0125     test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
0126 
0127     return nerrs == 0 ? 0 : 1;
0128 }