โฌข DragonFlyBSD Kernel Audit
โ† dashboard
DF-0030

jrecord_write_path goto again can spin indefinitely under concurrent rename (local DoS)

Field Value
ID DF-0030
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
CWE CWE-835 Loop with Unreachable Exit Condition
File sys/kern/vfs_journal.c
Lines 1251-1255
Area kern
Confidence speculative
Discovered 2026-06-29
Reported pending

Summary

jrecord_write_path() walks the namecache parent chain twice: pass 1 computes pathlen, pass 2 fills the buffer. If any namecache entry's nc_nlen grows between passes (a concurrent rename of a directory component to a longer name), the bounds check scan->nc_nlen >= index frees the buffer and goto again restarts pass 1 โ€” with no cap on restarts. A sustained concurrent renamer can keep the journalizing thread (and whatever VFS serialization it holds) looping indefinitely while the FIFO fills and journal backpressure stalls the mount.

Root cause

sys/kern/vfs_journal.c:1251-1255:

if (scan->nc_nlen >= index) {
    if (base != buf)
        kfree(base, M_TEMP);
    goto again;                 /* unbounded retry */
}

This is a TOCTOU between pass 1 (pathlen accumulation, :1233-1237) and pass 2 (filling, :1248-1262).

Threat model & preconditions

  • Attacker position: unprivileged user with permission to rename within a path being journaled (journal installed by root).
  • Privileges gained or impact: local DoS of the journal layer (stall/ backpressure on the mount). Narrow; jrecord_write_path is reached from the VOP journal hooks via jrecord_write_vnode_ref/_link (:1349/1370).
  • Confidence: speculative โ€” requires winning a sustained concurrent-rename window against a journalizing thread; recorded for the unbounded-retry robustness defect.

Cap the retries and fall back to an empty/short path leaf:

--- a/sys/kern/vfs_journal.c
+++ b/sys/kern/vfs_journal.c
@@ -1220
+    int retries = 0;
@@ -1251 +1253,8 @@
    if (scan->nc_nlen >= index) {
        if (base != buf)
        kfree(base, M_TEMP);
+       if (++retries > 16) {
+       kprintf("jrecord_write_path: namespace racing, giving up\n");
+       jrecord_leaf(jrec, rectype, "", 1);
+       return;
+       }
        goto again;

References

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/vfs_journal.c.
  • pending Reported to DragonFlyBSD security contact.