# DF-0026 — Proof of Concept

## The bug

`bioq_reorder_minor_interval` (`sys/kern/subr_disk.c:1325-1327`) is a
`SYSCTL_INT(..., CTLFLAG_RW, ...)` with no bounds validation. It is used
directly as a modulus divisor at `:1376`:

```c
if (bioq->reorder % bioq_reorder_minor_interval == 0) {
```

Setting `kern.bioq_reorder_minor_interval=0` (root) causes an integer
divide-by-zero (`FPE_INTDIV`, trap 18) panic in `bioqdisksort()` the next time
a READ bio is sorted into a bioq that already has a pending WRITE (`transition
!= NULL`).

Root-only (sysctl writes gated by `SYSCAP_NOSYSCTL_WR`). Low severity.

## Files

| File | Description |
|------|-------------|
| `bioq_div0.sh` | Original trigger script (sets sysctl; workload illustrative) |
| `trigger.c` | Aggressive parallel I/O flood trigger (vtblk target) |
| `trigger_md.c` | md0 SMP-race trigger |
| `trigger_md2.c` | md0 O_DIRECT + disjoint-range trigger |
| `df26_harness.c` | **Kernel module harness** — directly constructs the div0 bioq state |
| `Makefile` | kld module build for the harness |
| `fix.diff` | Standalone git-apply-able fix (consumer-side divisor clamp) |
| `build.sh` / `run.sh` | Repro scripts |

## How to reproduce

### Prerequisites
- DragonFlyBSD 6.5-DEVELOPMENT (master DEV) guest, default X86_64_GENERIC kernel
- Root access (sysctl write + kldload)

### Build the harness
```sh
./build.sh
```

### Run (root, disposable VM)
```sh
./run.sh
```

### Expected (bug present — unpatched `#0` kernel)
```
Fatal trap 18: integer divide fault while in kernel mode
Stopped at      bioqdisksort+0x9f:      idivl   0xa4b82b(%rip),%eax
db>
```

### Expected (fixed — patched `#1` kernel)
```
DF-0026: harness loaded. bioq_reorder_minor_interval=0
DF-0026: queuing WRITE (transition before=0)
DF-0026: queued WRITE, transition=0xfffff8008d640840. Now queuing READ -> DIV0
DF-0026: BUG NOT TRIGGERED (unexpected!)
```
Guest stays up, no panic.

## Why a kernel module harness?

The div0 code path requires `bioq->transition != NULL` (a WRITE bio already
queued) when a READ bio enters `bioqdisksort()`. On real hardware/virtio, the
disk strategy drains the bioq immediately after each `bioqdisksort()` call,
making the window where `transition != NULL` extremely tight from userspace.
The finding is root-only (sysctl write), so a root-loaded harness module is a
legitimate proof: it constructs the exact bioq state and calls the real
`bioqdisksort()` (the actual vulnerable function), not a simulation. The
sysctl is still set from userspace — the module only sets up the I/O state.
