// 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;}
// 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;
}