{
  "finding_id": "DF-2984",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "syscall_deregister() (kern_syscalls.c:75-76) writes sysent[*offset] = *old_sysent with no bounds check on the index (NO_SYSCALL == -1 passes the old 'if (*offset)' test) and no proof that a successful syscall_register() established the pair. The MOD_LOAD-failure rollback in module_register_init() (kern_module.c:112 module_unload -> MOD_UNLOAD -> syscall_module_handler kern_syscalls.c:99-106) reaches this sink with a never-initialized (offset, old_sysent). Verified on the guest: two legitimate fixed-slot-210 KLDs; loading the second fails syscall_register with EEXIST yet kldload(2) returns 0, and the rollback executes sysent[210] = {0,0,NULL,NULL}, destroying the first module's LIVE syscall; every subsequent unprivileged syscall(210) (verified as uid 1001) performs a kernel NULL function call - deterministic 'Fatal trap 12 ... instruction pointer = 0x8:0x0' panic persistent until reboot. The EINVAL variant (fixed offset 99999) was likewise driven to the sink (MOD_LOAD error 22, kldload rc=0), executing sysent[99999]=zeros ~2.3MB past the table (silent on that boot: target was already-zero .bss); ENFILE gives sysent[-1] identically. Unprivileged ceiling is persistent panic: the written value is the module's static zero initializer, and controlling it (or the OOB index) requires authoring a KLD, i.e. root via SYSCAP_NOKLD. fix.diff (bounds re-validation + registered gate + proper rollback on chainevh failure) applied in-guest, kernel rebuilt: same steps leave slot 210 live (call210 still returns 4242, no panic), modC writes nothing, guest healthy.",
  "exploit_chain": "root one-time setup: kldload legitimate module A (fixed slot 210) -> kldload legitimate module B (same fixed slot): syscall_register EEXIST -> MOD_LOAD fails -> kern_module.c:112 module_unload dispatches MOD_UNLOAD -> syscall_module_handler:105 syscall_deregister(&210, &{0,0,NULL,NULL}) -> sysent[210].sy_call = NULL (kern_syscalls.c:76) while kldload(B) returns 0. Then ANY unprivileged user: syscall(210) -> trap.c:1224 callp=&sysent[210], :1235 narg=0, :1285 (*NULL)(&sysmsg, argp) -> Fatal trap 12, RIP=0, reboot required. No uid0 route for unprivileged users: written value is fixed zeros from stock module initializers; controlling value/index requires module authorship = root.",
  "evidence": [
    "panic.txt: 'Fatal user address access from kernel mode from call210 at 0000000000000000' / 'instruction pointer = 0x8:0x0' after unprivileged syscall(210) as uid 1001",
    "run.log: KLDLOAD_A_RC=0 ... KLDLOAD_B_RC=0 with dmesg 'module_register_init: MOD_LOAD (dfpocb, ...) error 17' (EEXIST rollback fired, kldload still reports success)",
    "run.modc.log: 'MOD_LOAD (dfpocc, ...) error 22' (EINVAL variant reached the same sink; kldload rc=0)",
    "run.fix.log: on fix.diff kernel #1, same kldload B produces 'error 17' but unprivileged call210 'survived: syscall(210) returned 4242' (twice, plus after modC load), guest up",
    "VERDICT.md: full narrative + exploitability-ceiling analysis"
  ],
  "kernel_refs": [
    "sys/kern/kern_syscalls.c:72-78",
    "sys/kern/kern_syscalls.c:99-106",
    "sys/kern/kern_module.c:110-116",
    "sys/kern/kern_linker.c:342-351",
    "sys/platform/pc64/x86_64/trap.c:1219-1224",
    "sys/platform/pc64/x86_64/trap.c:1235",
    "sys/platform/pc64/x86_64/trap.c:1285",
    "sys/sys/sysent.h:84-94"
  ],
  "poc_changes": "Seed lead assumed only 'root-loaded modules with fixed offsets' could mis-index. Deepened: the reachable path is the MOD_LOAD-failure rollback (kern_module.c:112), so NO module bug is needed - two legitimate fixed-offset KLDs conflicting (EEXIST) corrupts a live slot; ENFILE(*offset=-1)/EINVAL(arbitrary index) variants added. Stock SYSCALL_MODULE macro is bit-rotted ({0,NULL} vs 4-field sysent, -Werror), so the PoC hand-rolls the exact macro expansion to reach syscall_module_handler. call210 uses plain syscall(210); run.sh switched sudo->run_user (no sudo in guest).",
  "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": 1260,
  "guest_dirty": 0,
  "build_cmd": "sh /tmp/df2984/build.sh  (make -C modA; make -C modB; make -C modC against /usr/obj/usr/src/sys/X86_64_GENERIC; cc call210.c)",
  "run_cmd": "root: sh /tmp/df2984/run.sh ; then unprivileged: /tmp/df2984/call210",
  "code_hash": "556912c4fec0dedbf71c7e10b30ff04682885907b2a0bcb97328f194271fc5f2",
  "recommended_fix": "Re-validate the index in syscall_deregister (reject <=0 or >=SYS_MAXSYSCALL) and gate deregistration on a 'registered' flag set only after a successful syscall_register (also roll back the registration when the module's chainevh init fails).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Fri Sep  4 17:32:24 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "bounds re-validation in syscall_deregister plus a registered flag in syscall_module_data gating MOD_UNLOAD deregistration (and rolling back the registration when the chainevh init fails) removes the unvalidated write entirely; the exact baseline panic input (unprivileged call210 after kldload A+B) is inert on the patched kernel (call210 still returns the live marker 4242, also after loading the out-of-range modC), guest stays up; kldload success-misreporting is DF-2936 and intentionally unchanged",
  "fix_evidence": [
    "fix_run.log (patched-kernel sequence: error 17 + error 22 rollbacks leave slot live)",
    "VERDICT.md fix-validation section (kernel #1 uname, KBUILD_RC=0, IK_RC=0)"
  ],
  "notes": "fix_status=fixed. fix_kernel_uname='DragonFly dfbsd 6.5-DEVELOPMENT #1: Fri Sep 4 17:32:24 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64'. fix_baseline_reproduced=1 (panic at RIP=0 from uid 1001). fix_patched_reproduced=0 (call210 returns 4242 after kldload B and C; guest up). fix_verdict='bounds re-validation in syscall_deregister plus a registered flag in syscall_module_data gating MOD_UNLOAD deregistration (and rolling back the registration when chainevh init fails) removes the unvalidated write entirely; baseline panic input is inert on the patched kernel with no visible regression (kldload-success mis-reporting is DF-2936 and intentionally unchanged)'. fix_evidence=['run.fix.log','/tmp/kbuild.log in-guest (KBUILD_RC=0)','kernel #1 uname in VERDICT.md']. Guest reset with-src after validation. Related: DF-2936 (same rollback machinery, module-registry aspect), DF-2966/DF-2918 (registry discipline family)."
}