DF-0016 / leak_sample.txt
# DF-0016 leak sample — unredacted kernel pointers in kern.proc.* (kinfo_proc)
# Guest: DragonFly 6.5-DEVELOPMENT v6.5.0.1712.g89e6a-DEVELOPMENT (amd64)
# Reader: uid=1001 (maxx), NOT in wheel, NOT the owner of the target pids.
#
# sysctl_kern_proc (KERN_PROC_PID, kern_proc.c:1686) only checks PRISON_CHECK
# (jail) -- NOT p_trespass. fill_kinfo_proc / fill_kinfo_lwp write raw kernel
# virtual addresses into user-visible kinfo fields, copied out unredacted via
# sysctl_out_proc (kern_proc.c:1603/1612/1633). An unprivileged user can thus
# read the struct-proc slab address, filedesc slab address, and wait-channel
# of ANY pid (including every root daemon).
#
# 24 kernel pointers leaked across 8 processes in the decisive run.
## decisive run: kern.proc.pid.<root-pid> read as maxx
pid 1 uid=0 comm=init
kp_paddr = 0xfffff80066807880 (struct proc slab) kern_kinfo.c:128
kp_fd = 0xfffff80066840ec0 (filedesc slab) kern_kinfo.c:129
kl_wchan = 0xfffff80066807880 (wait channel) kern_kinfo.c:272
pid 68 uid=0 comm=hammer2
kp_paddr = 0xfffff800ab143280 (struct proc slab)
kp_fd = 0xfffff800ab163c40 (filedesc slab)
kl_wchan = 0xfffff80065c799f8 (wait channel)
pid 285 uid=0 comm=dhclient
kp_paddr = 0xfffff8006680c880 ; kp_fd = 0xfffff8006684c140 ; kl_wchan = 0xfffff8006680c880
pid 328 uid=0 comm=devd
kp_paddr = 0xfffff800ab144180 ; kp_fd = 0xfffff800ab1669c0 ; kl_wchan = 0xfffff80067a5dff8
pid 411 uid=0 comm=syslogd
kp_paddr = 0xfffff800ab145080 ; kp_fd = 0xfffff800ab167b40 ; kl_wchan = 0xfffff80067a5e778
pid 699 uid=0 comm=sshd
kp_paddr = 0xfffff800ab144b80 ; kp_fd = 0xfffff800ab1677c0 ; kl_wchan = 0xfffff80067a5e4f8
pid 730 uid=0 comm=cron
kp_paddr = 0xfffff800ab144680 ; kp_fd = 0xfffff800ab16a540
kl_wchan = 0xffffffff8130f670 (kernel .text/.data!) kern_kinfo.c:272
## nm /boot/kernel/kernel cross-reference (proves the leaked values are real
## kernel addresses, not garbage/zeros)
cron kl_wchan 0xffffffff8130f670 -> nearest nm symbol: nanowait.<clone>+0x0 EXACT
(a .text-range address -> directly reveals the kernel .text base = KASLR defeat)
kp_paddr/kp_fd/kl_wchan in 0xfffff8xxxxxxxxxx = DragonFly kernel KVA/malloc region
(slab-allocated struct proc / struct filedesc / wait-channel tokens). These are
dynamic allocations, so nm has no symbol; they are confirmed real by:
- canonical upper-half kernel addresses (>= 0xffff800000000000)
- STABLE across repeated reads (3x: pid 1 kp_paddr identical) -- a real,
fixed live kernel object address, not random stack residue
- DIFFERENT distinct values per pid, clustered in slab-sized groups
(e.g. init/dhclient kp_paddr in 0xfffff8006680xxxx; hammer2/devd/syslogd/
sshd/cron in 0xfffff800ab14xxxx) -- consistent with slab bucket layout
## stability check (decisive run)
pid 1 kp_paddr: 0xfffff80066807880 / 0xfffff80066807880 / 0xfffff80066807880 (STABLE)
## variance
run.log vs run.2.log: root-daemon slab addresses byte-identical (long-running
processes do not relocate); the self (leak_kinfo) process kp_paddr differs run
to run (new process, new slab object) -- expected, and itself confirms these are
live slab addresses.
## interpretation
Any unprivileged local user recovers, for every process on the system: the
slab address of its struct proc (kp_paddr) and struct filedesc (kp_fd), plus a
wait-channel address that is sometimes a kernel .text symbol (cron -> nanowait).
This is a reliable KASLR-bypass + slab-layout primitive that escalates the
practical severity of any local heap/struct-proc corruption bug (e.g. DF-0013)
from DoS to reliable code execution.