# DF-3068 — Undo-walk desync via PAD/fake-tail inconsistency → deterministic `KKASSERT` panic in `hammer_recover_stage1` (INVARIANTS) / silent mis-recovery (production)

Kernel: DragonFly 6.5-DEVELOPMENT #0 (X86_64_GENERIC, INVARIANTS), `sys/vfs/hammer`
File under audit: `sys/vfs/hammer/hammer_recover.c` (pass 2). New finding —
distinct root cause from DF-0812/2594 (redo_data_bytes) and DF-3040
(vol0_undo_array).

## Root cause (hammer_recover.c)

* For version < 4 filesystems the nominal undo range is taken **verbatim**
  from the crafted `vol0_blockmap[3]` (`:225-226`) — `next_offset` need not
  be a record boundary.
* `_hammer_check_signature` skips all head/tail agreement checks for PAD-8
  records (`:901-924`) and re-derives the tail from `head + hdr_size - 8`
  (`:948-961`), so the **tail bytes at `end_off-8` are never required to
  agree with the head the tail's `tail_size` points at** when that head is a
  short PAD/DUMMY-style record. `hammer_recover_scan_rev` (`:1023-1026`,
  `:814-815`) then steps the walk back by the *head's* `hdr_size` while the
  tail's `tail_size` was the only thing anchoring validation — a crafted
  "fake tail" whose `tail_size` (24) points at a 24-byte DUMMY head makes
  one loop iteration consume 24 bytes where only 8 remain in `bytes`.
* Stage1's undo loop exits with `bytes = -16` and
  `KKASSERT(error || bytes == 0)` at `:460` fires → deterministic panic on
  INVARIANTS kernels. On production kernels the assert is absent: the mount
  **silently continues**, executes an UNDO/DUMMY record from *outside* the
  nominal undo range, then rewrites and flushes the volume-header blockmap
  (`:481-488`) — silent mis-recovery of the FIFO indices. (The copies
  themselves stay buffer-bounded — no memory unsafety; impact is DoS on
  INVARIANTS + wrong recovery semantics on production.)
* Sibling asserts reachable the same way: `:394` (`scan_offset !=
  first_offset`), stage2 `:698`/`:716`, and the rterm `KKASSERT` at `:1286`
  when the stage2 forward walk desyncs against the reverse TERM scan.

## Reproduce

```
# guest (root), after build.sh + run.sh of DF-3067 (vn0 wedged):
cp findings/poc/DF-3068/run.sh + padflood.c; sh build.sh (if needed)
sh run.sh          # padflood desync mode: vol_version=3, DUMMY@F-16 with
                  # fake tail at F (tail_size=24), first=F, next=F+8
# expected on the stock INVARIANTS guest:
#   Fatal trap ... assertion: error || bytes == 0 in hammer_recover_stage1
#   (guest wedged at db>)
```

Impact ceiling: deterministic mount-time panic (local DoS, crafted image;
root or `vfs.usermount=1`). Low — INVARIANTS-only for the panic; production
kernels get silent wrong recovery, no memory corruption (all undo copies are
bounds-checked at `:1053-1076`).
