DF-5358 / pmx_user.c
/* * pmx_user.c - DF-5358 userland trigger (DragonFly pc64, root) * * pread() on /dev/kmem at a kernel VA whose upper paging level is absent. * The read goes through: * mmrw() sys/kern/kern_memio.c:257 (minor 1) * kvm_access_check() sys/platform/pc64/x86_64/vm_machdep.c:1276 * pmap_kextract() sys/platform/pc64/x86_64/pmap.c:1865 * *vtopt(va) pmap.c:800 (recursive-map PDE-slot address) * -> kernel-mode data page fault with pcb_onfault == NULL -> panic. * * On a kernel with the DF-5358 fix, this instead fails cleanly with EFAULT * (pmap_kextract returns 0 -> kvm_access_check rejects the range). * * usage: pmx_user <kva-hex> [len] */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <inttypes.h> int main(int argc, char **argv) { unsigned long long va; size_t len = 8; char buf[32]; ssize_t n; int fd; if (argc < 2) { fprintf(stderr, "usage: %s <kva-hex> [len]\n", argv[0]); return (2); } va = strtoull(argv[1], NULL, 0); if (argc > 2) len = strtoull(argv[2], NULL, 0); fd = open("/dev/kmem", O_RDONLY); if (fd < 0) { perror("pmx_user: open /dev/kmem"); return (1); } printf("pmx_user: pread(/dev/kmem, %zu bytes) at kva %016jx ...\n", len, (uintmax_t)va); fflush(stdout); errno = 0; n = pread(fd, buf, len < sizeof(buf) ? len : sizeof(buf), (off_t)va); printf("pmx_user: pread returned %zd errno=%d (%s)\n", n, errno, strerror(errno)); printf("pmx_user: kernel survived (no panic)\n"); return (0); } |