DragonFlyBSD Kernel Audit
← triage · dashboard
DF-2833

kern.syncdelay=SYNCER_MAXDELAY (32) accepted by sysctl → same-slot requeue livelock/deadlock of the syncer under sc_token (also kern.retrydelay<=0)

Field Value
ID DF-2833
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H
CWE CWE-834 / CWE-835 (config-gated)
File sys/kern/vfs_sync.c
Lines 133-136 (requeue :864; slots :207/:286/:301/:421-436)
Area kern
Confidence certain
Discovered 2026-08-31
Pass 2 (GLM 5.3 second pass)
Bucket base:kern
Reported pending
Known CVE none
CVE match novel

Summary

sysctl_kern_syncdelay clamps to [1, SYNCER_MAXDELAY] so 32 is accepted. With syncdelay==32: (a) vsyncscan's requeue computes −(i+32)&31 == i — the just-scanned vnode is reinserted at the HEAD of the very bucket being scanned, so the drain loop rescans it forever whenever vget(NOWAIT) keeps failing; the scanning thread holds sc_token and spins, and a lock holder blocked on sc_token (the exact discipline documented at hammer_inode.c:258-269) can never get it → unkillable mount-wide livelock/deadlock. (b) vsetisdirty/vsetobjdirty's vn_syncer_add(vp, syncdelay) targets slot (delayno+32)&31 == delayno — re-dirtying churn re-enters the syncer's own drain bucket, livelocking the syncer thread. Similarly retrydelay (unclamped SYSCTL_INT) set to 0 makes vn_syncer_add(vp,0) map to slot 0 — when delayno==0 the drain loop spins forever holding sc_token for any vnode that stays dirty across VOP_FSYNC. Root-gated configuration DoS; no memory-safety impact. Fix: clamp syncdelay to [1, MAXDELAY−2] (and validate the other delay sysctls), or make the delay≤0 path use (delayno+1)&mask.

Timeline

  • 2026-08-31 Discovered during pass-2 audit of vfs_sync.c (GLM 5.3).

Discussion (0)

No comments yet.