{
  "finding_id": "DF-2799",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED: permanent kernel-wide AB-BA deadlock between the global jail_lock and the per-CPU gd_sysctllock locks. Root side: sys_jail holds jail_lock (kern_jail.c:275) across prison_sysctl_create (:223) whose SYSCTL_ADD_* macros take the all-CPU sysctl xlock (_sysctl_xlock, kern_sysctl.c:1641-51). Unprivileged side: userland_sysctl holds its CPU's gd_sysctllock SHARED across the whole handler dispatch (kern_sysctl.c:1571-73) and sysctl_jail_list blocks acquiring jail_lock (kern_jail.c:696) inside it. On the stock kernel, 4 unprivileged jail.list readers plus a 3000-iteration jail(2) churn wedged the guest in seconds: markers listonce/jailonce returned rc 124 under timeout, even `echo` stopped returning (new process startup blocks on the exclusively-held per-CPU locks via rtld boot sysctls), and the serial console flooded 'maxproc limit exceeded by jailchurn' because the deadlocked parent never reaps. Zero id-sharing flood lines at 3000 iterations, isolating this wedge from DF-2802. On the patched kernel (prison_sysctl_create moved before publication and out of jail_lock; sys_jail drops the lock before kern_jail) the identical storm completed: 1,146,880 jail.list reads with 0 errors, markers rc=0, guest healthy. Permanent unrecoverable hang requiring reboot; unprivileged-triggerable whenever jail(2) runs on the host.",
  "exploit_chain": "unprivileged user: while(1) sysctlbyname(\"jail.list\") — each read parks holding a per-CPU gd_sysctllock; concurrent root jail(2) reaches SYSCTL_XLOCK under jail_lock; cycle closes; whole-system wedge (all jails, all sysctl activity, new process exec). DoS ceiling; no memory-safety primitive.",
  "evidence": [
    "findings/poc/DF-2799/run.log — attempt-2 evidence: PRE markers rc=0, post-storm PROBE/TRIVIAL/MARKERS all 124 with no output, maxproc console flood, flood-lines=0 note",
    "findings/poc/DF-2799/run.patched.log — fixed kernel: storm survives, POST-LISTONCE:0 (335 bytes listed mid-storm), 1.15M reads 0 errors",
    "findings/poc/DF-2799/serial_wrong_oid_run.log — attempt-1 context (wrong oid; wedge that run was DF-2802-family)"
  ],
  "kernel_refs": [
    "sys/kern/kern_jail.c:275", "sys/kern/kern_jail.c:223", "sys/kern/kern_jail.c:235",
    "sys/kern/kern_jail.c:696", "sys/kern/kern_sysctl.c:442", "sys/kern/kern_sysctl.c:1480",
    "sys/kern/kern_sysctl.c:1571", "sys/kern/kern_sysctl.c:1641", "sys/sys/sysctl.h:192-194"
  ],
  "poc_changes": "Reader oid corrected from kern.jail.list to jail.list (the SYSCTL_NODE parent is the root, not kern — attempt 1 used the wrong oid and its readers no-op'd); run_user reader launch fixed (cd must precede each nohup; 'cd X && nohup A &' backgrounds the compound and later nohups run in the wrong cwd); run.sh rewritten as a host-side vm.sh driver with every guest command timeout-wrapped because the guest wedges by design.",
  "attempts": 2,
  "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": 900,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o jailchurn jailchurn.c && cc -O2 -o jailistreader jailistreader.c && cc -O2 -o listonce listonce.c && cc -O2 -o jailonce jailonce.c",
  "run_cmd": "sh run.sh   (host-side driver: vm.sh run_user readers on jail.list + vm.sh run_root './jailchurn 3000', then timeout-wrapped markers)",
  "code_hash": "a095ededefb7fc56036245ec659006abc9d74f94fc17fc26f6f28fe4807e3a0c",
  "notes": "Lock-cycle proof is structural (lockmgr sleeps never time out; no cycle detection). The 3000-iteration bound proves purity: zero 'can't re-use a leaf' lines means no DF-2802 sharing was involved, so the wedge is solely the lock cycle. Fixed kernel = #1 Tue Sep 1 13:39:40 UTC 2026.",
  "recommended_fix": "Never call sysctl add/remove while holding jail_lock: create the prison sysctl tree before publishing the prison (and outside jail_lock) in kern_jail(), and release sys_jail's outer jail_lock before calling kern_jail(); prison_free already drops the lock before prison_sysctl_done.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Tue Sep  1 13:39:40 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Same storm on the patched kernel ran to completion: 4 readers performed 1,146,880 jail.list reads with 0 errors while the 3000-jail churn ran; listonce returned live data (rc=0) DURING the storm; jailonce rc=0; guest fully responsive after. Baseline wedge (markers 124, echo dead, maxproc flood) is gone.",
  "fix_evidence": "findings/poc/DF-2799/run.patched.log; fix.diff (hunks: kern_jail.c kern_jail/sys_jail restructure)"
}
