cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sigaltstack.c (2789B)


      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}