# DF-2636 — VERDICT

**Status: reproduced (impact: panic, confidence: certain).**

## Narrative
The PoC forger (cribbing the proven DF-2616/DF-2624 technique) walks
volhdr -> sroot blockset -> PFS inodes, finds the inode named `testvol`
(inode block at image offset 0x1400800 on our base image), flips
`meta.type` (inode block offset +0x50 per hammer2_disk.h
`hammer2_inode_meta_t`) from 1 (DIRECTORY) to 0x42, sets CHECK_NONE on the
poison bref and the sroot bref, zeroes mirror_tid on the poison bref so
recovery does not recurse, and recomputes the volume-header CRC32Cs.

On the guest (stock INVARIANTS kernel, DragonFly 6.5-DEVELOPMENT #0):

1. `mount_hammer2 -o ro /dev/vn1@testvol /mnt/h2636` **succeeded**
   (console: `hammer2_mount: devstr="/dev/vn1@testvol" ... rdonly=1`,
   `HAMMER2: INITIATE SPANs`). No type validation exists on the mount path.
2. The first VFS_ROOT — triggered by the `lstat` inside `ls -la` — panics
   exactly at the cited site:

```
panic: hammer2: unhandled objtype 66
hammer2_igetv() at hammer2_igetv+0x42a
hammer2_vfs_root() at hammer2_vfs_root+0xdc
nlookup() at nlookup+0xb9c
kern_stat() at kern_stat+0x1d
sys_lstat() at sys_lstat+0x57
```

The ssh session died at the panic (guest froze in ddb) — panic.txt and
run.log contain the serial-console capture.

## Why this is the cited bug
`hammer2_igetv()` at sys/vfs/hammer2/hammer2_inode.c:791-793:
`default: panic("hammer2: unhandled objtype %d", ip->meta.type);`
`ip->meta` was populated from media in `hammer2_pfsalloc`
(hammer2_vfsops.c:456, `iroot->meta = ripdata->meta`) with no validation
of `type`. Valid-but-unhandled on-media values include 0, 3, 8, 10
(WHITEOUT), and 11..255.

## Exploit ceiling
Unauthenticated kernel panic (DoS) from a crafted filesystem image at
mount/first-access; requires the ability to mount a hammer2 image (root).
No memory-corruption primitive — the switch is a straight dispatch on an
unvalidated byte, the default branch is a controlled panic.

## Fix validation
fix.diff changes the default branch to log, mark the vp VBAD, vx_put it,
and return EINVAL; `if (vp == NULL) break;` guards the tail of the loop.
Built with `make nativekernel` in the guest, installed, rebooted: the same
forged image then mounts and `ls` returns an error instead of panicking
(see fix_run.log, fix_build.log). Baseline panic confirmed on the stock
kernel in the same session.
