# DF-3254 verification

Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

## Bottom line

HAMMERIOC_DEDUP with a leaf whose data_offset was forged to a NON-ZERO zone-0 value (0x100000) panics the INVARIANTS kernel exactly through the claimed ordering: hammer_ioc_dedup.c:66 calls hammer_btree_extract_data BEFORE the hammer_is_zone_data validation at :92-93, and _hammer_bread hits KKASSERT(HAMMER_ZONE(buf_offset) != 0) at hammer_ondisk.c:1123 - live trace: panic assertion failed in _hammer_bread, backtrace hammer_bread_ext -> hammer_btree_extract -> hammer_ioc_dedup -> hammer_ioctl -> hammer_vop_ioctl. Verification refines the original claim: a raw data_offset of exactly 0 is caught by the early guard at hammer_btree.c:730-731 (extract returns 0 with NULL data and the INVALID_ZONE flag fires cleanly, as observed in the first attempt); the zone validation is only ordered after a dereference for non-zero zone-0 (and forged non-data-zone) offsets. Privileged ioctl on a crafted RW-mounted image; availability only.

## Kernel references
- sys/vfs/hammer/hammer_dedup.c:66
- sys/vfs/hammer/hammer_dedup.c:82
- sys/vfs/hammer/hammer_dedup.c:92-93
- sys/vfs/hammer/hammer_ondisk.c:1123
- sys/vfs/hammer/hammer_btree.c:730-731

## Exploit chain
(none: availability/correctness finding; no privilege chain)

## Fix

extract leaf and zone-check BEFORE extract_data for both cursors; combined fixed kernel: the same trigger returns cleanly with the INVALID_ZONE flag and no panic

See fix.diff in this directory (git-apply-able against the read-only sys/
tree; applied only inside the disposable verification guest).

## Reproduction

build: guest: cc -O -o patch_doff patch_doff.c; cc -O -I/usr/src/sys/vfs/hammer -o dedup_trigger dedup_trigger.c; image: newfs_hammer + a data file + synctid, offline-patch a DATA leaf data_offset to 0x100000 with CRC fix

run: guest: mount_hammer /dev/vn0 /mnt/h1 && ./dedup_trigger /mnt/h1 --copy h1.img <element-offset>

expected: panic: assertion HAMMER_ZONE(buf_offset) != 0 failed in _hammer_bread (see panic.txt); with data_offset exactly 0 the ioctl instead returns INVALID_ZONE harmlessly

## Notes on the PoC (what changed vs the finding sketch)

first attempt used data_offset 0 (caught by the btree.c:730 guard, INVALID_ZONE flag, no panic); second used non-zero zone-0 0x100000 which passes the guard into the KKASSERT; also the DATA records live in zones 10/11 on this newfs, not 8/9, so the patcher filter was widened

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