# VERDICT — DF-3148

## Status: REPRODUCED (panic) / fix VALIDATED

## Baseline (stock INVARIANTS kernel `#0`, 2026-07-02)

Single `HAMMERIOC_MIRROR_WRITE` ioctl, one REC mrec:
`data_len=0`, `btype=0`, create_tid=0x1000, rec_type=DB(0x12), PFS0.

Result: kernel panic, exact predicted sink and chain (serial console):

```
panic: assertion "elm->base.btype != 0" failed in hammer_btree_insert
       at /usr/src/sys/vfs/hammer/hammer_btree.c:816
hammer_btree_insert() at hammer_btree_insert+0x2d9
hammer_create_at_cursor() at hammer_create_at_cursor+0x1cf
hammer_ioc_mirror_write() at hammer_ioc_mirror_write+0x3f8
hammer_ioctl() at hammer_ioctl+0xebe
hammer_vop_ioctl() at hammer_vop_ioctl+0x48
```

Root cause chain (line-accurate):
- `hammer_ioc_mirror_write_rec()` validates ONLY `data_len`
  (sys/vfs/hammer/hammer_mirror.c:575-579). The rest of the wire leaf —
  including `base.btype` — is passed through unvalidated.
- `hammer_create_at_cursor()` (sys/vfs/hammer/hammer_object.c:2274) stores the
  leaf verbatim: with `data_len == 0` the whole alloc/copyin/CRC block is
  skipped (:2298-2339), so no other validation happens either; then
  `hammer_btree_insert()`.
- `hammer_btree_insert()` KKASSERTs `elm->base.btype != 0`
  (sys/vfs/hammer/hammer_btree.c:816). btype is a full wire-controlled byte.
- Nonzero-but-wrong btype (not 'R') passes :816 and is stored; any later
  mirror delete-through hits `KKASSERT(elm->base.btype == HAMMER_BTREE_TYPE_RECORD)`
  at hammer_mirror.c:737 / hammer_object.c:2448 (deferred panic), so BOTH
  btype=0 and btype=junk panic INVARIANTS kernels.

Reachability: ioctl gated by `caps_priv_check(SYSCAP_NOVFS_IOCTL)`
(hammer_ioctl.c:72,169-176) → local root, or the untrusted mirror-master wire
stream (the real threat: `hammer mirror-stream` pipes remote records into this
ioctl; a malicious master kills the slave kernel with one record).
Not DF-0867: that finding is `rec_type`→`hammer_alloc_data` hpanic
(data_len>0 path); this is `btype`→B-Tree insert/delete assertions.

Non-INVARIANTS production kernels: the bogus btype is stored on disk
(invariant violation) instead of panicking.

## Fix validation (patched kernel `#1`, 2026-09-07, fix.diff applied)

`fix.diff` rejects `btype != HAMMER_BTREE_TYPE_RECORD` in
`hammer_ioc_mirror_write_rec` (hammer_mirror.c:580-586 after patch).

Re-run of the identical PoC on a fresh fs:

```
=== btype0 on patched kernel ===
MIRROR_WRITE rc=0 head.error=22 head.flags=00008000 count=0
=> kernel REJECTED the stream (error 22)
```

No panic, guest stayed up, stream rejected with EINVAL (22). Build:
`make -j6 nativekernel` RC=0, `make installkernel` RC=0 (same X86_64_GENERIC
INVARIANTS config).

## Bottom line

Certain. Single-ioctl kernel panic from wire data on INVARIANTS kernels;
on-disk B-Tree invariant violation on production kernels; malicious-master
remote DoS of HAMMER1 mirror targets. Fix proven.

## 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.
