Unbounded rterm/rte allocation during stage2 extended-range TERM collection β attacker-controlled kernel-heap exhaustion at mount ('This must fit in memory!' is not enforced)
Summary
hammer_recover_stage2's reverse scan of the extended range calls hammer_recover_redo_rec for every REDO_TERM_* record: one kmalloc(M_WAITOK) rterm per unique (objid, localization, flag, offset) (:1177) plus one kmalloc'd rterm_entry per record occurrence appended to the matching rterm's list (:1202-1205); all freed only at end of stage2 (:731-738). The extended range spans up to the whole undo FIFO (up to 128 bigblocks = 1GB), every record byte is attacker-crafted with matching CRCs and monotonically decreasing seqnos (:659-666), so ~16M crafted TERM records (64B each on disk) allocate ~1.1GB of non-pageable kernel heap during mount - memory-exhaustion DoS / M_WAITOK stall. The design comment admits the constraint ('This must fit in memory!', :611) but nothing enforces a bound. Requires the largest crafted image of the hammer family for the least impact - Low, not guest-verified per contract. Fix: cap total rterm+rte allocations, fail stage2 EIO when exceeded (REDO replay optional by design). [VERIFIED pass2: not attempted - needs 1GB of forged CRC-valid REDO_TERM records beyond rig budget for a Low DoS; unbounded allocation code-certain]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3069 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 291 B | β raw | |
| VERDICT.md | β | 1.2 KB | β raw | |
| env.txt | β | 248 B | view raw | |
| fix.diff | β | 141 B | view raw | |
| manifest.json | β | 622 B | view raw | |
| run.log | β | 170 B | view raw | |
| verdict.json | β | 1.4 KB | view raw |
DF-3069 - Unbounded rterm/rte allocation during stage2 extended-range TERM collection
Severity Low | verdict: not_reproduced | impact: none
Reproduce
No runnable PoC on this rig (see VERDICT.md for why).
See VERDICT.md for the full narrative and run.log for the decisive output.
DF-3069 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
Not attempted on the guest: demonstrating the memory-exhaustion requires forging on the order of a million CRC-valid, seqno-monotonic REDO_TERM records across the undo FIFO of a crafted image (~1GB of undo for a visible mount-time stall against 4GB RAM) - beyond the crafted-image rig budget for a Low/DoS return. Code-verified: one kmalloc per unique TERM key (hammer_recover.c:1177) plus one per occurrence (:1202-1205), all freed only at stage2 end (:731-738); nothing enforces the documented must-fit-in-memory constraint (:611).
Kernel references
- sys/vfs/hammer/hammer_recover.c:611
- sys/vfs/hammer/hammer_recover.c:1177
- sys/vfs/hammer/hammer_recover.c:1202
Fix
See fix.diff.
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.
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md + run.log + sources
PoC changes
none
Verified recommended fix
diff: cap total rterm+rte allocations (e.g. 64MB) in hammer_recover_stage2 and fail EIO when exceeded (REDO replay is optional by design).
Verdict
Not attempted on the guest: demonstrating the memory-exhaustion requires forging on the order of a million CRC-valid, seqno-monotonic REDO_TERM records across the undo FIFO of a crafted image (~1GB of undo for a visible mount-time stall against 4GB RAM) - beyond the crafted-image rig budget for a Low/DoS return. Code-verified: one kmalloc per unique TERM key (hammer_recover.c:1177) plus one per occurrence (:1202-1205), all freed only at stage2 end (:731-738); nothing enforces the documented must-fit-in-memory constraint (:611).
No comments yet.