โฌข DragonFlyBSD Kernel Audit
DF-2925 / verdict.json
โ† back to finding โ†“ download raw
{
  "finding_id": "DF-2925",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "Uninitialized kernel stack disclosed to unprivileged users through quota accounting. cmd_set_limit() (vfs_quota.c:273-284) stores the never-initialized uint64_t 'limit' into mp->mnt_acct.ac_limit when the \"limit\" key is absent (prop_dictionary_get_uint64 leaves *valp untouched on failure, prop_dictionary_util.c), and cmd_get_usage_all() echoes ac_limit to userspace (vfs_quota.c:184). Observed: consecutive unprivileged calls leaked 0x10, 0, 3, 4, 5, ... i.e. the previous syscall's leftover stack slot (the value tracks prior activity = steerable disclosure; same pattern for 'space' at :249/:263 and the locals at :293/:314). On the DF-2922-patched kernel (which zero-initializes these) the same PoC reports 0 across all runs โ€” fix validated on the same build.",
  "exploit_chain": "",
  "evidence": [
    "run.log โ€” 5-run sample: leaked ac_limit=0x10/0x0/0x3/0x4/0x5 (not attacker-set, varies with prior syscall)",
    "run.200.log โ€” 200-run sweep showing the slot tracks the previous call's loop counter"
  ],
  "kernel_refs": [
    "sys/kern/vfs_quota.c:277",
    "sys/kern/vfs_quota.c:280",
    "sys/kern/vfs_quota.c:184",
    "sys/kern/vfs_quota.c:249",
    "sys/kern/vfs_quota.c:263",
    "sys/libprop/prop_dictionary_util.c"
  ],
  "poc_changes": "prop_object_is_array() is not exported to userland โ€” removed from the reply parser.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 60,
  "guest_dirty": 0,
  "build_cmd": "cc -O -o vqleak vqleak.c -lprop",
  "run_cmd": "/tmp/vqleak /boot 5   (as uid 1001)",
  "code_hash": "46aa0f37447d67992f58aaa77796125404f363dd8fec8afaf35d745e498023c2",
  "notes": "Precondition: vfs.quota_enabled=1. 8 bytes of kernel stack per call; a pointer-seeding syscall run immediately before vquotactl would place kernel pointers in the slot (KASLR-defeating use on hardened builds).",
  "recommended_fix": "Zero-initialize limit/space/id before the prop_dictionary_get_* calls (included and validated in DF-2922's fix.diff).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Thu Sep  3 13:57:47 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "On kernel #1 with the zero-initialization in fix.diff, the same PoC reports ac_limit=0 on every run (was nonzero stack garbage on #0).",
  "fix_evidence": "VERDICT.md in DF-2922 pack (fix validation section); run on patched kernel: all runs 0x0"
}