{
  "finding_id": "DF-2682",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Unprivileged syscall-only kernel heap use-after-free in kern_descrip.c: funsetown() clears *sigiop under sigio_token and then kfrees the struct sigio with no reference count and no token held (kern_descrip.c:1245-1273), while pgsigio() readers at uipc_socket2.c:601-602 (sowakeup/SS_ASYNC), uipc_socket.c:2537-2538, tty.c:2366/2380 and kern_event.c:2055 load the raw pointer without the token and dereference it (sio_pgid, sio_ucred->cr_uid, sio_pgrp->pgref, sio_proc). Reproduced on the stock INVARIANTS guest with a 3-thread socketpair harness: Fatal trap 12 in pgsigio+0x13 reading 0x40(%rax) == (freed sigio)->sio_ucred->cr_uid, kernel stopped in DDB, ssh dead. The primitive is a read-side UAF whose downstream dereferences (pgref atomic-increment, ksignal, lockmgr through forged pointers) are write-capable if the 48-byte M_SIGIO chunk is reclaimed under attacker control; a reliable uid=0 chain was not completed in this run (documented in VERDICT.md).",
  "exploit_chain": "unprivileged socketpair + F_SETOWN/O_ASYNC -> thread A: write() storm drives sowakeup()->pgsigio(so->so_sigio) lockless loads; thread B: fcntl(F_SETOWN)+dup/close churn drives fsetown()/soclose()->funsetown() which clears and kfrees the sigio; in-flight reader enters pgsigio() with freed pointer -> sio_ucred read from freed memory -> cr_uid deref at NULL+0x40 -> Fatal trap 12 (demonstrated). With slab reuse under attacker control the same chain yields pgref() increment / ksignal() writes through attacker-chosen pointers (escalation feasible in principle on this no-SMAP/SMEP/KASLR guest; not completed).",
  "evidence": [
    "panic.txt: 'Fatal trap 12 ... fault virtual address = 0x40 ... Stopped at pgsigio+0x13: movl 0x40(%rax),%eax' from unprivileged sigio_uaf",
    "run.log: harness start line, ssh session death, vm.sh status=down immediately after",
    "sigio_uaf.c: the 3-thread harness (writer/F_SETOWN+dup-close churner)",
    "VERDICT.md: root cause lines, primitive characterization, fix iteration history",
    "sys/kern/kern_descrip.c:1245-1273 (free without reader exclusion), sys/kern/uipc_socket2.c:601-602 (unguarded load), sys/kern/sys_pipe.c:211-215 (the guarded idiom that the missing sites should mirror)"
  ],
  "kernel_refs": [
    "sys/kern/kern_descrip.c:1238",
    "sys/kern/kern_descrip.c:1245",
    "sys/kern/kern_descrip.c:1273",
    "sys/kern/uipc_socket2.c:601",
    "sys/kern/uipc_socket.c:2537",
    "sys/kern/kern_sig.c:2639",
    "sys/kern/sys_pipe.c:211"
  ],
  "poc_changes": "None material; added <err.h>/<sys/socket.h> includes and fixed the drain side (recv on the O_ASYNC end) vs the seed sketch.",
  "attempts": 1,
  "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": 320,
  "guest_dirty": 1,
  "build_cmd": "cc -O2 -pthread -o sigio_uaf sigio_uaf.c",
  "run_cmd": "./sigio_uaf 300",
  "code_hash": "7e2acb53210b7cbb9c2d08845476532cb43f7798fad3766d30fb4c54f73a2533",
  "notes": "fix.diff (v4: token-guarded readers + ordered free, no token nesting) compiles and boots, but the race storm still crashes the restructured fsetown/funsetownlst replacement machinery shared with DF-2683; fix_status=fix_failed with 4 documented iterations (see VERDICT.md). Guest was reset with-src after the runs.",
  "recommended_fix": "Give struct sigio a reference count (or a dedicated list lock): readers acquire a ref under sigio_token before using the pointer; funsetown drops the last ref only after list removal, so pgsigio readers can never hold a freed sigio; mirror the existing pipewakeup() token-guard at all missing pgsigio call sites."
}
