cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

signals-s390x.c (4222B)


      1#include <assert.h>
      2#include <signal.h>
      3#include <string.h>
      4#include <sys/mman.h>
      5#include <ucontext.h>
      6#include <unistd.h>
      7
      8/*
      9 * Various instructions that generate SIGILL and SIGSEGV. They could have been
     10 * defined in a separate .s file, but this would complicate the build, so the
     11 * inline asm is used instead.
     12 */
     13
     14void illegal_op(void);
     15void after_illegal_op(void);
     16asm(".globl\tillegal_op\n"
     17    "illegal_op:\t.byte\t0x00,0x00\n"
     18    "\t.globl\tafter_illegal_op\n"
     19    "after_illegal_op:\tbr\t%r14");
     20
     21void stg(void *dst, unsigned long src);
     22asm(".globl\tstg\n"
     23    "stg:\tstg\t%r3,0(%r2)\n"
     24    "\tbr\t%r14");
     25
     26void mvc_8(void *dst, void *src);
     27asm(".globl\tmvc_8\n"
     28    "mvc_8:\tmvc\t0(8,%r2),0(%r3)\n"
     29    "\tbr\t%r14");
     30
     31static void safe_puts(const char *s)
     32{
     33    write(0, s, strlen(s));
     34    write(0, "\n", 1);
     35}
     36
     37enum exception {
     38    exception_operation,
     39    exception_translation,
     40    exception_protection,
     41};
     42
     43static struct {
     44    int sig;
     45    void *addr;
     46    unsigned long psw_addr;
     47    enum exception exception;
     48} expected;
     49
     50static void handle_signal(int sig, siginfo_t *info, void *ucontext)
     51{
     52    void *page;
     53    int err;
     54
     55    if (sig != expected.sig) {
     56        safe_puts("[  FAILED  ] wrong signal");
     57        _exit(1);
     58    }
     59
     60    if (info->si_addr != expected.addr) {
     61        safe_puts("[  FAILED  ] wrong si_addr");
     62        _exit(1);
     63    }
     64
     65    if (((ucontext_t *)ucontext)->uc_mcontext.psw.addr != expected.psw_addr) {
     66        safe_puts("[  FAILED  ] wrong psw.addr");
     67        _exit(1);
     68    }
     69
     70    switch (expected.exception) {
     71    case exception_translation:
     72        page = mmap(expected.addr, 4096, PROT_READ | PROT_WRITE,
     73                    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
     74        if (page != expected.addr) {
     75            safe_puts("[  FAILED  ] mmap() failed");
     76            _exit(1);
     77        }
     78        break;
     79    case exception_protection:
     80        err = mprotect(expected.addr, 4096, PROT_READ | PROT_WRITE);
     81        if (err != 0) {
     82            safe_puts("[  FAILED  ] mprotect() failed");
     83            _exit(1);
     84        }
     85        break;
     86    default:
     87        break;
     88    }
     89}
     90
     91static void check_sigsegv(void *func, enum exception exception,
     92                          unsigned long val)
     93{
     94    int prot;
     95    unsigned long *page;
     96    unsigned long *addr;
     97    int err;
     98
     99    prot = exception == exception_translation ? PROT_NONE : PROT_READ;
    100    page = mmap(NULL, 4096, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    101    assert(page != MAP_FAILED);
    102    if (exception == exception_translation) {
    103        /* Hopefully nothing will be mapped at this address. */
    104        err = munmap(page, 4096);
    105        assert(err == 0);
    106    }
    107    addr = page + (val & 0x1ff);
    108
    109    expected.sig = SIGSEGV;
    110    expected.addr = page;
    111    expected.psw_addr = (unsigned long)func;
    112    expected.exception = exception;
    113    if (func == stg) {
    114        stg(addr, val);
    115    } else {
    116        assert(func == mvc_8);
    117        mvc_8(addr, &val);
    118    }
    119    assert(*addr == val);
    120
    121    err = munmap(page, 4096);
    122    assert(err == 0);
    123}
    124
    125int main(void)
    126{
    127    struct sigaction act;
    128    int err;
    129
    130    memset(&act, 0, sizeof(act));
    131    act.sa_sigaction = handle_signal;
    132    act.sa_flags = SA_SIGINFO;
    133    err = sigaction(SIGILL, &act, NULL);
    134    assert(err == 0);
    135    err = sigaction(SIGSEGV, &act, NULL);
    136    assert(err == 0);
    137
    138    safe_puts("[ RUN      ] Operation exception");
    139    expected.sig = SIGILL;
    140    expected.addr = illegal_op;
    141    expected.psw_addr = (unsigned long)after_illegal_op;
    142    expected.exception = exception_operation;
    143    illegal_op();
    144    safe_puts("[       OK ]");
    145
    146    safe_puts("[ RUN      ] Translation exception from stg");
    147    check_sigsegv(stg, exception_translation, 42);
    148    safe_puts("[       OK ]");
    149
    150    safe_puts("[ RUN      ] Translation exception from mvc");
    151    check_sigsegv(mvc_8, exception_translation, 4242);
    152    safe_puts("[       OK ]");
    153
    154    safe_puts("[ RUN      ] Protection exception from stg");
    155    check_sigsegv(stg, exception_protection, 424242);
    156    safe_puts("[       OK ]");
    157
    158    safe_puts("[ RUN      ] Protection exception from mvc");
    159    check_sigsegv(mvc_8, exception_protection, 42424242);
    160    safe_puts("[       OK ]");
    161
    162    safe_puts("[  PASSED  ]");
    163
    164    _exit(0);
    165}