# DF-3067 VERDICT — REPRODUCED (dos)

**Status: reproduced / impact: dos / confidence: certain.** Baseline
verified on the stock INVARIANTS kernel (DragonFly 6.5-DEVELOPMENT #0, Thu
Jul 2 06:02:54 UTC 2026); fix validated on the rebuilt kernel #1.

## What was run

`padflood backscan` patches a real `newfs_hammer` image (12G sparse, undo
FIFO 64 bigblocks, version 7→6): every byte of a 256KB undo ring
(`alloc_offset = UNDO|0x40000`, undo bigblock 0 at phys 0x1088000) becomes a
valid 8-byte PAD record `{0xC84E,0x8040,8}`, and
`vol0_blockmap[3].first_offset = next_offset = UNDO|0x1000`. Mounting it
(RO or RW) runs `hammer_recover_stage1`'s version-4 seqno backscan
(hammer_recover.c:257-270), which walks the FIFO backwards to find a non-PAD
record to seed `hdr_seq`.

## Why it hangs (path:line)

* The backscan `for(;;)` has exactly two exits: an I/O/signature error, or a
  **non-PAD** record (`:266-269`) — PAD records are exempt from the seqno
  discontinuity check that bounds every other walk in this file.
* `hammer_recover_scan_rev` wraps the walk at the zone base
  (`:789-790`: `scan_offset == HAMMER_ENCODE_UNDO(0) → alloc_offset`),
  making the FIFO a ring; PAD-8 records are self-consistent head==tail
  (8 bytes, `_hammer_check_signature:901-924,930,948-961` — no CRC needed),
  so every position validates and neither exit ever fires.
* There is **no byte counter and no lap limit** in the loop (the sibling
  forward scan's "grossly ahead" bound is `#if 0`'d out at `:312-335`).

## Baseline observations (stock kernel #0)

* The mount **never returns**; the mounting thread spins at 100% CPU in
  kernel mode; `kill -9` pends forever (no cancellation points) — the
  process cannot be reaped, vn0 stays configured.
* With `vfs.hammer.debug_general=0x80` the serial console trace
  (`bootlog_walk_trace.log`, 47,039 lines captured while still running)
  shows: first traced offset `3000000000001000` == the crafted
  `first_offset`; the walk descends to the zone base, **wraps UP
  `3000000000000000 → 300000000003fff8` at iterations 513 and 33281**
  (hammer_recover.c:789-790); 32,769 distinct offsets = the entire ring
  revisited — lap ≥ 2 at capture time, still descending.
* Guest otherwise alive (fresh ssh sessions answered) — CPU burn + wedged
  mount + unrecoverable vn device; repeated mounts stack spinning threads.
* Works on INVARIANTS **and** production kernels (no assertion involved);
  a **read-only** mount suffices (stage1 runs before the RW/RO distinction
  matters).

Stage2 variant (same root cause, not separately run): the extended-range
scan `:652-670` terminates only when `scan_offset == ext_offset` where
`ext_offset = REDO_SYNC.redo_offset` — an unvalidated u64 (`:423-424`);
a garbage value plus an all-PAD gap = the same infinite loop on RW mounts.

## Fix validation (fix.diff, kernel #1: Sat Sep  5 22:10:54 UTC 2026)

One-lap `walked` bound added to both backscan loops. Identical PoC image on
the patched kernel: the walk does exactly one lap (trace ends back at
`3000000000001008`) then `recovery failure during seqno backscan` →
`Failed to recover HAMMER filesystem on mount`, mount_hammer exits, guest
up. Regressions: stock image mount/RW-write/sync/umount/remount cycle clean;
hard-crash dirty recovery (`reboot -q` on mounted dirty fs) clean
(`recovery check seqno=0010014d` … files intact).

## Impact classification

Local DoS (livelock) from mount of a crafted image — root or
`vfs.usermount=1` (same precondition family as DF-0797/0798/0812/2594/3040);
unkillable spinning kernel thread per mount attempt. Not memory corruption;
no escalation path identified (the walk only reads FIFO buffers).
