brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · f689af7 Raw
129 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#define _GNU_SOURCE4#include <signal.h>5#include <stdio.h>6#include <stdbool.h>7#include <string.h>8#include <err.h>9#include <errno.h>10#include <limits.h>11#include <sys/mman.h>12#include <sys/auxv.h>13#include <sys/prctl.h>14#include <sys/resource.h>15#include <setjmp.h>16 17/* sigaltstack()-enforced minimum stack */18#define ENFORCED_MINSIGSTKSZ	204819 20#ifndef AT_MINSIGSTKSZ21#  define AT_MINSIGSTKSZ	5122#endif23 24static int nerrs;25 26static bool sigalrm_expected;27 28static unsigned long at_minstack_size;29 30static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),31		       int flags)32{33	struct sigaction sa;34 35	memset(&sa, 0, sizeof(sa));36	sa.sa_sigaction = handler;37	sa.sa_flags = SA_SIGINFO | flags;38	sigemptyset(&sa.sa_mask);39	if (sigaction(sig, &sa, 0))40		err(1, "sigaction");41}42 43static void clearhandler(int sig)44{45	struct sigaction sa;46 47	memset(&sa, 0, sizeof(sa));48	sa.sa_handler = SIG_DFL;49	sigemptyset(&sa.sa_mask);50	if (sigaction(sig, &sa, 0))51		err(1, "sigaction");52}53 54static int setup_altstack(void *start, unsigned long size)55{56	stack_t ss;57 58	memset(&ss, 0, sizeof(ss));59	ss.ss_size = size;60	ss.ss_sp = start;61 62	return sigaltstack(&ss, NULL);63}64 65static jmp_buf jmpbuf;66 67static void sigsegv(int sig, siginfo_t *info, void *ctx_void)68{69	if (sigalrm_expected) {70		printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");71		nerrs++;72	} else {73		printf("[OK]\tSIGSEGV signal delivered.\n");74	}75 76	siglongjmp(jmpbuf, 1);77}78 79static void sigalrm(int sig, siginfo_t *info, void *ctx_void)80{81	if (!sigalrm_expected) {82		printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");83		nerrs++;84	} else {85		printf("[OK]\tSIGALRM signal delivered.\n");86	}87}88 89static void test_sigaltstack(void *altstack, unsigned long size)90{91	if (setup_altstack(altstack, size))92		err(1, "sigaltstack()");93 94	sigalrm_expected = (size > at_minstack_size) ? true : false;95 96	sethandler(SIGSEGV, sigsegv, 0);97	sethandler(SIGALRM, sigalrm, SA_ONSTACK);98 99	if (!sigsetjmp(jmpbuf, 1)) {100		printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",101		       sigalrm_expected ? "" : "in");102		printf("\tRaise SIGALRM. %s is expected to be delivered.\n",103		       sigalrm_expected ? "It" : "SIGSEGV");104		raise(SIGALRM);105	}106 107	clearhandler(SIGALRM);108	clearhandler(SIGSEGV);109}110 111int main(void)112{113	void *altstack;114 115	at_minstack_size = getauxval(AT_MINSIGSTKSZ);116 117	altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,118			MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);119	if (altstack == MAP_FAILED)120		err(1, "mmap()");121 122	if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)123		test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);124 125	test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);126 127	return nerrs == 0 ? 0 : 1;128}129