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

exc_validate.c (2688B)


      1#include <stdlib.h>
      2#include <string.h>
      3#include <stdio.h>
      4#include <signal.h>
      5#include <unistd.h>
      6#include <sys/mman.h>
      7
      8#include "utils.h"
      9
     10extern char __start___ex_table[];
     11extern char __stop___ex_table[];
     12
     13#if defined(__powerpc64__)
     14#define UCONTEXT_NIA(UC)	(UC)->uc_mcontext.gp_regs[PT_NIP]
     15#elif defined(__powerpc__)
     16#define UCONTEXT_NIA(UC)	(UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
     17#else
     18#error implement UCONTEXT_NIA
     19#endif
     20
     21static void segv_handler(int signr, siginfo_t *info, void *ptr)
     22{
     23	ucontext_t *uc = (ucontext_t *)ptr;
     24	unsigned long addr = (unsigned long)info->si_addr;
     25	unsigned long *ip = &UCONTEXT_NIA(uc);
     26	unsigned long *ex_p = (unsigned long *)__start___ex_table;
     27
     28	while (ex_p < (unsigned long *)__stop___ex_table) {
     29		unsigned long insn, fixup;
     30
     31		insn = *ex_p++;
     32		fixup = *ex_p++;
     33
     34		if (insn == *ip) {
     35			*ip = fixup;
     36			return;
     37		}
     38	}
     39
     40	printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);
     41	abort();
     42}
     43
     44static void setup_segv_handler(void)
     45{
     46	struct sigaction action;
     47
     48	memset(&action, 0, sizeof(action));
     49	action.sa_sigaction = segv_handler;
     50	action.sa_flags = SA_SIGINFO;
     51	sigaction(SIGSEGV, &action, NULL);
     52}
     53
     54unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
     55unsigned long test_copy_tofrom_user_reference(void *to, const void *from, unsigned long size);
     56
     57static int total_passed;
     58static int total_failed;
     59
     60static void do_one_test(char *dstp, char *srcp, unsigned long len)
     61{
     62	unsigned long got, expected;
     63
     64	got = COPY_LOOP(dstp, srcp, len);
     65	expected = test_copy_tofrom_user_reference(dstp, srcp, len);
     66
     67	if (got != expected) {
     68		total_failed++;
     69		printf("FAIL from=%p to=%p len=%ld returned %ld, expected %ld\n",
     70		       srcp, dstp, len, got, expected);
     71		//abort();
     72	} else
     73		total_passed++;
     74}
     75
     76//#define MAX_LEN 512
     77#define MAX_LEN 16
     78
     79int test_copy_exception(void)
     80{
     81	int page_size;
     82	static char *p, *q;
     83	unsigned long src, dst, len;
     84
     85	page_size = getpagesize();
     86	p = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,
     87		MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     88
     89	if (p == MAP_FAILED) {
     90		perror("mmap");
     91		exit(1);
     92	}
     93
     94	memset(p, 0, page_size);
     95
     96	setup_segv_handler();
     97
     98	if (mprotect(p + page_size, page_size, PROT_NONE)) {
     99		perror("mprotect");
    100		exit(1);
    101	}
    102
    103	q = p + page_size - MAX_LEN;
    104
    105	for (src = 0; src < MAX_LEN; src++) {
    106		for (dst = 0; dst < MAX_LEN; dst++) {
    107			for (len = 0; len < MAX_LEN+1; len++) {
    108				// printf("from=%p to=%p len=%ld\n", q+dst, q+src, len);
    109				do_one_test(q+dst, q+src, len);
    110			}
    111		}
    112	}
    113
    114	printf("Totals:\n");
    115	printf("  Pass: %d\n", total_passed);
    116	printf("  Fail: %d\n", total_failed);
    117
    118	return 0;
    119}
    120
    121int main(void)
    122{
    123	return test_harness(test_copy_exception, str(COPY_LOOP));
    124}