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

_hammer_ip_reseek() KKASSERTs on an EDEADLK-capable seek: INVARIANTS panic (or silent early iteration-EOF on release builds) when the btree re-seek deadlocks

Field Value
ID DF-3013
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H
CWE CWE-754
File sys/vfs/hammer/hammer_object.c
Lines 1492-1493 (vs :1443-1451; btree.c:869 documents EDEADLK)
Area vfs/hammer
Confidence speculative
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket base:vfs
Reported pending
Known CVE none
CVE match novel

Summary

_hammer_ip_seek_btree() explicitly tolerates EDEADLK from hammer_btree_iterate and propagates it, but _hammer_ip_reseek() wraps the call in KKASSERT(error == 0). Under flusher/frontend contention during a merged iteration whose rec_generation changed, an EDEADLK there panics an INVARIANTS kernel; on release builds error is __debugvar and the cursor has already been flagged DISKEOF|ATEDISK, so the iteration silently terminates early β€” e.g. hammer_ip_delete_range/delete_clean stop early, readdir misses entries. hammer_ip_first() handles the same error correctly, proving the reseek path is the outlier. Race-dependent, reachable from any unpriv merged iteration under heavy flusher contention. No PoC attempted (race, Low). Fix: handle EDEADLK instead of asserting β€” leave the DISKEOF|ATEDISK flags and propagate to hammer_ip_next()'s callers (all implement the terminate-cursor-and-retry protocol).

Timeline

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

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3013 Β· 8 files
FileTypeDescriptionSize
README.md β€” 300 B ↓ raw
VERDICT.md β€” 1.0 KB ↓ raw
df3013stress.c β€” 1.4 KB view raw
env.txt β€” 248 B view raw
fix.diff β€” 188 B view raw
manifest.json β€” 542 B view raw
run.log β€” 155 B view raw
verdict.json β€” 1.4 KB view raw

DF-3013 - _hammer_ip_reseek() KKASSERTs on EDEADLK-capable seek

Severity Low | verdict: not_reproduced | impact: none

Reproduce

Sources in this directory; build with cc -O2 -o <bin> <src> -pthread on the guest.

See VERDICT.md for the full narrative and run.log for the decisive output.

VERDICT.md
↓ download raw

DF-3013 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

90-second hammer stress on a fresh HAMMER1 volume: 4 writer threads (create/write/fsync/unlink, 130,347 ops) racing 4 readdir threads with 5 concurrent hammer reblock+prune passes. No panic; clean unmount. The EDEADLK-during-reseek window is real in the code (hammer_object.c:1493 KKASSERT(error==0) after _hammer_ip_seek_btree) but was not crossed under this load on a 6-vCPU INVARIANTS guest.

Kernel references

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_testable
↓ fix.diffper-fix-DF-3013

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md + run.log + sources

PoC changes

adjusted from finding sketch to guest syscall/layout reality

Verified recommended fix

diff: handle EDEADLK in _hammer_ip_reseek (leave HAMMER_CURSOR_DISKEOF|ATEDISK cleared, propagate error to hammer_ip_next callers retry protocol) mirroring hammer_ip_first (:1568-1570).

Verdict

90-second hammer stress on a fresh HAMMER1 volume: 4 writer threads (create/write/fsync/unlink, 130,347 ops) racing 4 readdir threads with 5 concurrent hammer reblock+prune passes. No panic; clean unmount. The EDEADLK-during-reseek window is real in the code (hammer_object.c:1493 KKASSERT(error==0) after _hammer_ip_seek_btree) but was not crossed under this load on a 6-vCPU INVARIANTS guest.