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

load_unaligned_zeropad.c (3080B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Userspace test harness for load_unaligned_zeropad. Creates two
      4 * pages and uses mprotect to prevent access to the second page and
      5 * a SEGV handler that walks the exception tables and runs the fixup
      6 * routine.
      7 *
      8 * The results are compared against a normal load that is that is
      9 * performed while access to the second page is enabled via mprotect.
     10 *
     11 * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM
     12 */
     13
     14#include <stdlib.h>
     15#include <string.h>
     16#include <stdio.h>
     17#include <stdbool.h>
     18#include <signal.h>
     19#include <unistd.h>
     20#include <sys/mman.h>
     21
     22#define FIXUP_SECTION ".ex_fixup"
     23
     24static inline unsigned long __fls(unsigned long x);
     25
     26#include "word-at-a-time.h"
     27
     28#include "utils.h"
     29
     30static inline unsigned long __fls(unsigned long x)
     31{
     32	int lz;
     33
     34	asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
     35	return sizeof(unsigned long) - 1 - lz;
     36}
     37
     38static int page_size;
     39static char *mem_region;
     40
     41static int protect_region(void)
     42{
     43	if (mprotect(mem_region + page_size, page_size, PROT_NONE)) {
     44		perror("mprotect");
     45		return 1;
     46	}
     47
     48	return 0;
     49}
     50
     51static int unprotect_region(void)
     52{
     53	if (mprotect(mem_region + page_size, page_size, PROT_READ|PROT_WRITE)) {
     54		perror("mprotect");
     55		return 1;
     56	}
     57
     58	return 0;
     59}
     60
     61extern char __start___ex_table[];
     62extern char __stop___ex_table[];
     63
     64struct extbl_entry {
     65	int insn;
     66	int fixup;
     67};
     68
     69static void segv_handler(int signr, siginfo_t *info, void *ptr)
     70{
     71	ucontext_t *uc = (ucontext_t *)ptr;
     72	unsigned long addr = (unsigned long)info->si_addr;
     73	unsigned long *ip = &UCONTEXT_NIA(uc);
     74	struct extbl_entry *entry = (struct extbl_entry *)__start___ex_table;
     75
     76	while (entry < (struct extbl_entry *)__stop___ex_table) {
     77		unsigned long insn, fixup;
     78
     79		insn  = (unsigned long)&entry->insn + entry->insn;
     80		fixup = (unsigned long)&entry->fixup + entry->fixup;
     81
     82		if (insn == *ip) {
     83			*ip = fixup;
     84			return;
     85		}
     86	}
     87
     88	printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);
     89	abort();
     90}
     91
     92static void setup_segv_handler(void)
     93{
     94	struct sigaction action;
     95
     96	memset(&action, 0, sizeof(action));
     97	action.sa_sigaction = segv_handler;
     98	action.sa_flags = SA_SIGINFO;
     99	sigaction(SIGSEGV, &action, NULL);
    100}
    101
    102static int do_one_test(char *p, int page_offset)
    103{
    104	unsigned long should;
    105	unsigned long got;
    106
    107	FAIL_IF(unprotect_region());
    108	should = *(unsigned long *)p;
    109	FAIL_IF(protect_region());
    110
    111	got = load_unaligned_zeropad(p);
    112
    113	if (should != got) {
    114		printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should);
    115		return 1;
    116	}
    117
    118	return 0;
    119}
    120
    121static int test_body(void)
    122{
    123	unsigned long i;
    124
    125	page_size = getpagesize();
    126	mem_region = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,
    127		MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    128
    129	FAIL_IF(mem_region == MAP_FAILED);
    130
    131	for (i = 0; i < page_size; i++)
    132		mem_region[i] = i;
    133
    134	memset(mem_region+page_size, 0, page_size);
    135
    136	setup_segv_handler();
    137
    138	for (i = 0; i < page_size; i++)
    139		FAIL_IF(do_one_test(mem_region+i, i));
    140
    141	return 0;
    142}
    143
    144int main(void)
    145{
    146	return test_harness(test_body, "load_unaligned_zeropad");
    147}