DF-2702 / verdict.json
{ "finding_id": "DF-2702", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "certain", "verdict": "recvmsg(MSG_PEEK) on an AF_UNIX socket with a queued SCM_RIGHTS message copies the control mbuf (m_copym) without running dom_externalize/unp_externalize, disclosing raw kernel struct file pointers to unprivileged users. Reproduced as uid=1001 on SOCK_STREAM (controllen=32=CMSG_LEN(2*8), slots 0xfffff801167ffd80/0xfffff801167ffe80, stable across peeks) and SOCK_DGRAM (0xfffff801167e5500), 4/4 runs kernel-range; real recvmsg of the same message externalizes to fds 6,7, proving the peek branch is the anomaly. Root cause uipc_socket.c:1422-1425 interacting with unp_internalize (uipc_usrreq.c:1817-1825) and unp_externalize (uipc_usrreq.c:1543). fix.diff validated on an in-guest nativekernel build (#1): peek returns controllen=0 for rights (leak gone), SCM_CREDS peek intact, real fd passing intact.", "exploit_chain": "", "evidence": [ "run.log: PEEK controllen=32, cmsg_len=32, slots 0xfffff801167ffd80 and 0xfffff801167ffe80 marked 'RAW KERNEL POINTER', identical across PEEK #0/#1; REAL RECV controllen=24 with fds 6,7", "run.2.log: SOCK_DGRAM variant leaks 0xfffff801167e5500; fresh-process rerun leaks new pointers 0xfffff801167e5e80/... (4/4 kernel-range)", "fix_validation.log: patched kernel #1 PEEK controllen=0 (no pointers), REAL recv controllen=24 fds 6,7; creds_peek: SCM_CREDS still peekable (controllen=104, type=3)", "fix.diff: MSG_PEEK branch skips returning unreplaced SCM_RIGHTS control", "VERDICT.md: full narrative + negative-space analysis of uipc_usrreq.c" ], "kernel_refs": [ "sys/kern/uipc_socket.c:1421-1425", "sys/kern/uipc_usrreq.c:1543-1633", "sys/kern/uipc_usrreq.c:1817-1825", "sys/kern/uipc_usrreq.c:636-637", "sys/kern/uipc_syscalls.c:1172-1189", "sys/kern/uipc_syscalls.c:934-943" ], "poc_changes": "PoC authored fresh (no seed). Two-peek + real-recv design to prove internalized-vs-externalized cmsg_len delta (32 vs 24) and pointer stability; added SOCK_DGRAM and SCM_CREDS-post-fix variants.", "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": 210, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o peek_rights_leak peek_rights_leak.c", "run_cmd": "./peek_rights_leak (uid=1001; plus ./dgram_peek)", "code_hash": "7425fae3407f8a82269aa12cefef09d738bc222a354d2256a0aa0d7248c0b0ff", "notes": "Info leak, not memory corruption - no uid0 chain applicable; impact is defeat of heap-address randomization and reliable slab targeting for separate corruption bugs. uipc_usrreq.c itself audited clean beyond known findings (see VERDICT.md negative space: sa_len normalized by getsockaddr, xunpcb 256B unions, single-mbuf control chains, fp-ref protects unpcb across blocking token release, balanced unp_reference/unp_free, unp_gc overcount benign).", "recommended_fix": "soreceive MSG_PEEK branch: do not return unreplaced SCM_RIGHTS control to userland (skip rights cmsgs on peek; externalize only on consume)", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Aug 31 02:02:55 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel #1 (make nativekernel with fix.diff): PEEK returns controllen=0 for SCM_RIGHTS (baseline pointers 0xfffff801xxxxxxxx gone); SCM_CREDS peek still returns control (controllen=104, type=3); real recvmsg still externalizes fds correctly (controllen=24, fds 6,7). Bad behavior eliminated, no functional regression.", "fix_evidence": [ "fix_validation.log", "fix_build_excerpt.txt", "fix.diff" ] } |