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

bti-2.c (2610B)


      1/*
      2 * Branch target identification, basic notskip cases.
      3 */
      4
      5#include <stdio.h>
      6#include <signal.h>
      7#include <string.h>
      8#include <unistd.h>
      9#include <sys/mman.h>
     10
     11#ifndef PROT_BTI
     12#define PROT_BTI  0x10
     13#endif
     14
     15static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
     16{
     17    ucontext_t *uc = vuc;
     18    uc->uc_mcontext.pc += 8;
     19    uc->uc_mcontext.pstate = 1;
     20}
     21
     22#define NOP       "nop"
     23#define BTI_N     "hint #32"
     24#define BTI_C     "hint #34"
     25#define BTI_J     "hint #36"
     26#define BTI_JC    "hint #38"
     27
     28#define BTYPE_1(DEST)    \
     29    "mov x1, #1\n\t"     \
     30    "adr x16, 1f\n\t"    \
     31    "br x16\n"           \
     32"1: " DEST "\n\t"        \
     33    "mov x1, #0"
     34
     35#define BTYPE_2(DEST)    \
     36    "mov x1, #1\n\t"     \
     37    "adr x16, 1f\n\t"    \
     38    "blr x16\n"          \
     39"1: " DEST "\n\t"        \
     40    "mov x1, #0"
     41
     42#define BTYPE_3(DEST)    \
     43    "mov x1, #1\n\t"     \
     44    "adr x15, 1f\n\t"    \
     45    "br x15\n"           \
     46"1: " DEST "\n\t"        \
     47    "mov x1, #0"
     48
     49#define TEST(WHICH, DEST, EXPECT) \
     50    WHICH(DEST) "\n"              \
     51    ".if " #EXPECT "\n\t"         \
     52    "eor x1, x1," #EXPECT "\n"    \
     53    ".endif\n\t"                  \
     54    "add x0, x0, x1\n\t"
     55
     56asm("\n"
     57"test_begin:\n\t"
     58    BTI_C "\n\t"
     59    "mov x2, x30\n\t"
     60    "mov x0, #0\n\t"
     61
     62    TEST(BTYPE_1, NOP, 1)
     63    TEST(BTYPE_1, BTI_N, 1)
     64    TEST(BTYPE_1, BTI_C, 0)
     65    TEST(BTYPE_1, BTI_J, 0)
     66    TEST(BTYPE_1, BTI_JC, 0)
     67
     68    TEST(BTYPE_2, NOP, 1)
     69    TEST(BTYPE_2, BTI_N, 1)
     70    TEST(BTYPE_2, BTI_C, 0)
     71    TEST(BTYPE_2, BTI_J, 1)
     72    TEST(BTYPE_2, BTI_JC, 0)
     73
     74    TEST(BTYPE_3, NOP, 1)
     75    TEST(BTYPE_3, BTI_N, 1)
     76    TEST(BTYPE_3, BTI_C, 1)
     77    TEST(BTYPE_3, BTI_J, 0)
     78    TEST(BTYPE_3, BTI_JC, 0)
     79
     80    "ret x2\n"
     81"test_end:"
     82);
     83
     84int main()
     85{
     86    struct sigaction sa;
     87    void *tb, *te;
     88
     89    void *p = mmap(0, getpagesize(),
     90                   PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
     91                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     92    if (p == MAP_FAILED) {
     93        perror("mmap");
     94        return 1;
     95    }
     96
     97    memset(&sa, 0, sizeof(sa));
     98    sa.sa_sigaction = skip2_sigill;
     99    sa.sa_flags = SA_SIGINFO;
    100    if (sigaction(SIGILL, &sa, NULL) < 0) {
    101        perror("sigaction");
    102        return 1;
    103    }
    104
    105    /*
    106     * ??? With "extern char test_begin[]", some compiler versions
    107     * will use :got references, and some linker versions will
    108     * resolve this reference to a static symbol incorrectly.
    109     * Bypass this error by using a pc-relative reference directly.
    110     */
    111    asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te));
    112
    113    memcpy(p, tb, te - tb);
    114
    115    return ((int (*)(void))p)();
    116}