โฌข DragonFlyBSD Kernel Audit
โ† dashboard
DF-0026

Root-writable bioq_reorder_minor_interval used as modulus divisor without validation -> divide-by-zero panic

Field Value
ID DF-0026
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H
CWE CWE-369 Divide By Zero; CWE-20 Improper Input Validation
File sys/kern/subr_disk.c
Lines 1325-1327, 1376
Area kern
Confidence certain
Discovered 2026-06-29
Reported pending

Summary

kern.bioq_reorder_minor_interval is exported as a CTLFLAG_RW SYSCTL_INT with no bounds validation and is used directly as the right-hand operand of a modulus (bioq->reorder % bioq_reorder_minor_interval) in the disk bio-sort hot path bioqdisksort(). Setting it to 0 (root) causes an immediate integer divide-by-zero (FPE_INTDIV) and kernel panic on the next disk read dispatched to a bioq that already has pending writes (bioq->transition != NULL).

Root cause

sys/kern/subr_disk.c:1325-1327:

int bioq_reorder_minor_interval = 5;
SYSCTL_INT(_kern, OID_AUTO, bioq_reorder_minor_interval,
           CTLFLAG_RW, &bioq_reorder_minor_interval, 0, "");

sys/kern/subr_disk.c:1376:

if (bioq->reorder % bioq_reorder_minor_interval == 0) {     /* no divisor guard */

There is no lower-bound check on the divisor. The other three bioq_reorder_* knobs are not divisors (burst_interval is only compared with >=; the *_bytes knobs are subtracted under a left < n guard), so this is the only fatal one.

Threat model & preconditions

  • Attacker position: privileged โ€” writing kern.* sysctls requires SYSCAP_NOSYSCTL_WR (root, cr_uid==0). So this is a privileged-user- triggered kernel panic (self-DoS / hardening defect), not an escalation.
  • Privileges gained or impact: kernel panic (full-system DoS). No integrity/confidentiality impact.
  • Required config or capabilities: root; a disk with mixed read/write I/O so a read reaches the bioq->transition != NULL branch.
  • Reachability: sysctl kern.bioq_reorder_minor_interval=0, then any disk read on a bioq with pending writes.

Proof of concept

PoC source: findings/poc/DF-0026/bioq_div0.sh

Run (root, disposable VM)

sh findings/poc/DF-0026/bioq_div0.sh

Expected output

panic: integer divide fault   (FPE_INTDIV in bioqdisksort)

Impact

Root-only self-DoS. The kernel should not panic from a sysctl write of an in-range integer โ€” an unintentional panic knob reachable through normal disk I/O. Rated Low (privileged trigger). Same class as DF-0019.

Guard the divisor in the consumer (and/or validate in a SYSCTL_PROC handler):

--- a/sys/kern/subr_disk.c
+++ b/sys/kern/subr_disk.c
@@ -1373,8 +1373,14 @@
         * Insert before the first write.  Bleedover writes
         * based on reorder intervals to prevent starvation.
         */
+       int minor_interval = bioq_reorder_minor_interval;
+       int burst_interval = bioq_reorder_burst_interval;
+       if (minor_interval < 1)
+           minor_interval = 1;
+       if (burst_interval < minor_interval)
+           burst_interval = minor_interval;
        TAILQ_INSERT_BEFORE(bioq->transition, bio, bio_act);
        ++bioq->reorder;
-       if (bioq->reorder % bioq_reorder_minor_interval == 0) {
+       if (bioq->reorder % minor_interval == 0) {
            bioqwritereorder(bioq);
-           if (bioq->reorder >= bioq_reorder_burst_interval) {
+           if (bioq->reorder >= burst_interval) {
                bioq->reorder = 0;

Defense-in-depth: convert the knob to a SYSCTL_PROC handler that rejects values < 1 (and enforces the existing "burst must be a multiple of minor" invariant noted in the comment at :1322).

References

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/subr_disk.c.
  • pending Reported to DragonFlyBSD security contact.