DF-2898 / sysent_var.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | /* * Variant battery for the sys_xsyscall double-fault crash. * usage: sysent_var <variant> * b1 = indirect getpid syscall(0, 20) narg=0 * b2 = indirect write syscall(0, 4, fd, buf, n) narg=3 (<= regcnt) * c = indirect mmap syscall(0, 197, ...) 7 args (narg=7 > regcnt=5) [known crasher] * d = RAW asm indirect mmap: exact regs, stack args pad=0,pos=0 at rsp+8/rsp+16 * e = RAW asm DIRECT mmap (rax=197): 6 regs + stack args at rsp+8 (pad), rsp+16 (pos) * f = indirect via __syscall(198, ...) mmap (libc wrapper path) * g = RAW asm indirect with stack args beyond mapped user stack (rsp+8 unmapped) */ #include <sys/syscall.h> #include <sys/mman.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> /* raw indirect syscall 0: rdi=code, rsi..r9=a1..a5, [rsp+8]=a6, [rsp+16]=a7 */ static long raw_ind(long code, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { long ret; __asm__ volatile( "subq $32, %%rsp\n\t" "movq %[a6], 8(%%rsp)\n\t" "movq %[a7], 16(%%rsp)\n\t" "movq $0, (%%rsp)\n\t" /* slot kernel skips (+8 offset) */ "movl $0, %%eax\n\t" "movq %[code], %%rdi\n\t" "movq %[a1], %%rsi\n\t" "movq %[a2], %%rdx\n\t" "movq %[a3], %%rcx\n\t" "movq %[a4], %%r8\n\t" "movq %[a5], %%r9\n\t" "syscall\n\t" "addq $32, %%rsp\n\t" : "=a"(ret) : [code]"r"(code), [a1]"r"(a1), [a2]"r"(a2), [a3]"r"(a3), [a4]"r"(a4), [a5]"r"(a5), [a6]"r"(a6), [a7]"r"(a7) : "rcx", "r11", "memory"); return ret; } /* raw direct syscall: rax=n, rdi..r9=a1..a6, [rsp+8]=a7, [rsp+16]=a8 */ static long raw_dir(long n, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { long ret; __asm__ volatile( "subq $32, %%rsp\n\t" "movq %[a7], 8(%%rsp)\n\t" "movq %[a8], 16(%%rsp)\n\t" "movq $0, (%%rsp)\n\t" "movq %[n], %%rax\n\t" "movq %[a1], %%rdi\n\t" "movq %[a2], %%rsi\n\t" "movq %[a3], %%rdx\n\t" "movq %[a4], %%rcx\n\t" "movq %[a5], %%r8\n\t" "movq %[a6], %%r9\n\t" "syscall\n\t" "addq $32, %%rsp\n\t" : "=a"(ret) : [n]"r"(n), [a1]"r"(a1), [a2]"r"(a2), [a3]"r"(a3), [a4]"r"(a4), [a5]"r"(a5), [a6]"r"(a6), [a7]"r"(a7), [a8]"r"(a8) : "rcx", "r11", "memory"); return ret; } int main(int argc, char **argv) { char v = argc > 1 ? argv[1][0] : 'z'; long r; const char msg[] = "X\n"; switch (v) { case 'p': r = syscall(SYS_syscall, 20); printf("[p] indirect getpid = %ld\n", r); break; case 'w': r = syscall(SYS_syscall, 4, 1, msg, 2); printf("[w] indirect write = %ld\n", r); break; case 'c': printf("[c] indirect mmap before\n"); fflush(stdout); r = syscall(SYS_syscall, 197, 0, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); printf("[c] indirect mmap = 0x%lx\n", (unsigned long)r); break; case 'd': printf("[d] raw indirect mmap before\n"); fflush(stdout); r = raw_ind(197, 0, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0, 0); printf("[d] raw indirect mmap = 0x%lx\n", (unsigned long)r); break; case 'e': printf("[e] raw direct mmap before\n"); fflush(stdout); r = raw_dir(197, 0, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0, 0, 0); printf("[e] raw direct mmap = 0x%lx\n", (unsigned long)r); break; case 'f': printf("[f] indirect __syscall mmap before\n"); fflush(stdout); r = syscall(SYS___syscall, 197, 0, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); printf("[f] __syscall mmap = 0x%lx\n", (unsigned long)r); break; case 'g': printf("[g] raw indirect, stack args unmapped\n"); fflush(stdout); r = raw_ind(197, 0, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0, 0); printf("[g] ret = 0x%lx\n", (unsigned long)r); break; default: printf("unknown variant\n"); return 2; } return 0; } |