β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3042

Volume-header CRC (vol_crc) is never verified β€” hammer_crc_test_volume has zero callers; all mount-time header consumption is integrity-unchecked

Field Value
ID DF-3042
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:N
CWE CWE-345
File sys/vfs/hammer/hammer_ondisk.c
Lines 180-213
Area vfs/hammer
Confidence certain
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket base:vfs
Reported pending
Known CVE none
CVE match novel

Summary

hammer_install_volume validates only vol_signature, fsid match, duplicate vol_no and root vol_no; the root volume's vol_crc field is loaded into kernel memory but never checked β€” hammer_crc_test_volume() is defined and referenced nowhere else in the kernel (tree-wide grep). Everything downstream of mount β€” vol_no, vol_count, vol_version, vol_buf_beg/vol_buf_end, vol0_blockmap[] (including the undo map that feeds DF-3040), vol0_undo_array[], vol0_btree_root, vol0_stat_* β€” is consumed with zero integrity gate. For a malicious crafter this changes nothing (CRC is forgeable), but for the corruption/robustness threat model the missing gate means random media corruption is interpreted as trusted metadata instead of failing the mount; it is also the reason the DF-3040 PoC needed no CRC fixup. Layer1 freemap CRCs are verified on blockmap paths and B-Tree nodes at load β€” the volume header is the one unchecked anchor structure. Fix: verify the header CRC after the signature check (row diff). Not applicable to Phase V (hardening).

Timeline

  • 2026-09-02 Discovered during pass-2 audit of hammer_ondisk.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3042 Β· 6 files
FileTypeDescriptionSize
README.md β€” 217 B ↓ raw
corrupt3042.c β€” 3.1 KB view raw
fix.diff β€” 774 B view raw
manifest.json β€” 429 B view raw
run.log β€” 529 B view raw
verdict.json β€” 2.2 KB view raw

DF-3042 evidence pack

What

hammer volume-header CRC never verified at mount

Verdict

status=reproduced impact=none confidence=certain

See VERDICT.md for the full narrative and fix.diff for the verified fix.

Fix verification

fixed

A/B complete: stock mounts any corrupted header (vol_crc never checked); F40FIX refuses an image whose stored vol_crc is nonzero-and-wrong (console: HAMMER: volume has an invalid header CRC, mount EINVAL) while fresh newfs_hammer images (vol_crc==0) still mount - compat retained. Fix verified end to end.

↓ fix.diffper-fix-DF-3042

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md with path:line citations; run.log where a live demo exists; fix.diff

PoC changes

corruptor computes CRC32C locally (userland has no iscsi_crc32) to prove stored-vs-computed mismatch; also discovered vol_crc==0 on fresh images

Verified recommended fix

verify vol_crc after the signature check when vol_crc != 0 (newfs_hammer leaves it 0)

Verdict

Reproduced on the stock INVARIANTS guest: a newfs_hammer image whose volume header byte (vol_reserved[7], covered by vol_crc) was flipped WITHOUT fixing vol_crc mounted successfully (mount_hammer /dev/vn1 /mnt -> OK) - tree-wide hammer_crc_test_volume() has zero callers, so vol_no, vol_count, vol_version, vol0_blockmap[] etc. are consumed integrity-unchecked (hammer_ondisk.c:199-247 validates only signature/fsid/dup-vol_no/root vol_no). IMPORTANT fix-design discovery recorded by the corruptor: newfs_hammer leaves vol_crc == 0 on fresh images (two independent images verified), so a naive always-enforce fix would reject every new volume; the fix enforces the CRC only when vol_crc != 0. Post-fix A/B on F40FIX: image with a forged non-zero vol_crc is rejected with invalid header CRC/EFTYPE while a vol_crc==0 image still mounts (compat).