# DF-5171 VERDICT — vcd FLUSH/FREEBLKS panic: **REPRODUCED, fix validated**

## 1. Reproduced? YES — `panic: vcd: bad b_cmd 5` inside `mount(2)`

Guest: DragonFly 6.5-DEVELOPMENT x86_64 (X86_64_GENERIC #0 Thu Jul 2 2026),
cc 8.3, `vm.vkernel_enable=1`. A purpose-built VKERNEL64 (built from the
guest's `/usr/src`, which mirrors the audited tree) was booted as:

```
./vkernel64 -m 256M -r root.img -c hammer.img -e init_path=/poc
```

* `root.img` — 128 MB UFS carrying the static PID1 PoC (`vcd_flush_poc.c`);
* `hammer.img` — 2 GB `newfs_hammer -f` volume, attached as the CD.

`/poc` runs `mount("hammer", "/mnt", 0 /*rw*/, &info)` with
`info.volumes = {"/dev/vcd0"}`. Decisive console sequence (run.log:34-46):

```
DF-5171(B) vcd FLUSH panic PoC (hammer) start
MOUNTING hammer on /dev/vcd0 (rw)...
VCDDBG: bio cmd=1 off=0 bcount=16384 dev=vcd0      <- hammer reads vol header
HAMMER(vktest2) recovery check seqno=000fffff
VCDDBG: bio cmd=2 off=0 bcount=16384 dev=vcd0      <- rw mount writes header
VCDDBG: bio cmd=5 off=0 bcount=0    dev=vcd0      <- hammer_io_flush_sync()
panic: vcd: bad b_cmd 5                             <- vcd.c:165
Uptime: 3s
```

(The VCDDBG lines came from a temporary one-line kprintf in the guest's
vcd.c used during triage; it is not part of the finding or the fix and
records the fatal bio's identity: `BUF_CMD_FLUSH`, offset 0, length 0 —
exactly `hammer_io.c:1995-1999`.)

The `mount(2)` never returns; the vkernel dies at 3s uptime. Backtrace
and `panic.txt` in the pack.

## 2. The chain, line by line

1. `hammer` rw mount on `/dev/vcd0` → mount-time recovery walks the undo
   FIFO and then calls `hammer_io_wait_all(hmp, ..., 1)`
   (hammer_recover.c:1438/1461/1465; every flusher cycle does the same,
   hammer_flusher.c:784/910).
2. `hammer_io_flush_sync()` (hammer_io.c:1985-2007): `getpbuf`,
   `bp->b_cmd = BUF_CMD_FLUSH`, `bio_offset = 0`, `b_bcount = 0`,
   `vn_strategy(volume->devvp, &bp->b_bio1)`.
3. devfs spec strategy passes non-READ/WRITE bios straight through
   (`devfs_spec_strategy`, devfs_vnops.c — the `b_cmd != READ && != WRITE`
   shortcut → `dev_dstrategy_chain`, kern_device.c:392).
4. `/dev/vcd0` is a disk-core covering device (`disk1_ops`,
   subr_disk.c:716-745) → `diskstrategy` → `dscheck()`
   (subr_diskslice.c:91): offset 0 / length 0 is sector-aligned and in
   bounds → **passes through untouched** (dscheck never filters by b_cmd).
5. `dev_dstrategy(dp->d_rawdev)` → `vcdstrategy()` → `switch (bp->b_cmd)`
   has no FLUSH case → `panic("vcd: bad b_cmd 5")` (vcd.c:154-167).

## 3. Fix validated (baseline panic ⇒ patched clean)

`fix.diff` adds the vdisk-mirror FLUSH case (`fsync(sc->fd)`,
cf. vdisk.c:332-337) and completes unknown commands instead of panicking.
Guest rebuilt with only that diff applied to vcd.c:

```
fix_run.log:35  HAMMER(vktest2) mounted clean, no recovery needed
fix_run.log:39  mount(hammer) returned OK
fix_run.log:40  RESULT: no-panic (STILL ALIVE after 15s)
fix_run.log:58  Uptime: 18s
```

15 seconds of HAMMER flusher cycles (multiple FLUSH bios each completed
via fsync) — no panic, mount fully functional.

## 4. Secondary discovery (killed route, real bug, out of this file's scope)

The FFS-TRIM producer was explored first and is **dead code in this
tree**: `ffs_blkfree()` gates the trim bio on
`ip->i_devvp->v_mount->mnt_flag & MNT_TRIM` (ffs_alloc.c:1670-1677) —
but `i_devvp` is the *device* vnode, whose `v_mount` is **devfs**, never
the UFS mount that carries MNT_TRIM. Empirically proven inside the
vkernel: `statfs("/mnt")` showed `f_flags=01001040` (MNT_TRIM set), file
deletions and reallocation writes produced only cmd=1/cmd=2 bios
(instrumented run), and the bitmap frees went through `ffs_blkfree_cg`.
⇒ FFS TRIM never issues trim bios anywhere in this kernel — worth a
separate finding against ffs_alloc.c (one-word fix:
`ITOV(ip)->v_mount`).

## 5. Reachability preconditions (honest scoping)

* Requires a vkernel booted with `-c <image>` — which today crashes in
  `init_disk` (DF-1031: `diskFlags == NULL` deref, init.c:487-489). The
  PoC applies a two-line guest-local enabler (NULL → static zero flags,
  plus O_RDWR for the CD backing to allow a rw mount — vcd's dev_ops
  include physwrite, so a writable image is an ordinary configuration).
  With DF-1031 fixed upstream, the panic is reachable on any vkernel
  given a CD image.
* Trigger needs guest-root (mounting a filesystem). Guest-unprivileged
  users cannot mount; once root mounts HAMMER the panic is immediate.
* Impact ceiling: **DoS of the vkernel process** (userspace). No host
  kernel impact, no host privilege boundary crossed — hence Low, not
  Medium.

## 6. Verdict

`reproduced` / impact `panic` (of the vkernel target process) /
confidence `certain`. Fix: add FLUSH handling mirroring vdisk and stop
panicking on unknown commands — validated on the guest.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
