Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#define _GNU_SOURCE
  4#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	2048
 19
 20#ifndef AT_MINSIGSTKSZ
 21#  define AT_MINSIGSTKSZ	51
 22#endif
 23
 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}