DragonFlyBSD Kernel Audit
DF-0015 / leak_sample.txt
← back to finding ↓ download raw
# DF-0015 leak sample — executable path of arbitrary (root-owned) processes
# disclosed to an unprivileged user via kern.proc.pathname.<pid>
# 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.

## DECISIVE: kern.ps_argsopen=0 (admin hardening) — args/cwd gated, pathname NOT
#   (run as maxx, target = pid 1 = init, uid 0)
running as uid=1001; self pid=1714; target pid=1 (not ours)
kern.ps_argsopen = 0

=== exe-path leak via kern.proc.pathname.<target> ===
  kern.proc.pathname  .1   : rc=0 len= 11  '/sbin/init'        <-- LEAKED (no gate)

=== contrast: gated siblings on the same target ===
  kern.proc.args      .1   : rc=0 len=0   (blocked/empty)      <-- gate (1897) works
  kern.proc.cwd       .1   : rc=0 len=0   (blocked/empty)      <-- gate (2052) works

=== several other root-owned daemons (all leaked) ===
  kern.proc.pathname  .1   : '/sbin/init'          (uid 0)
  kern.proc.pathname  .68  : '/sbin/hammer2'       (uid 0)
  kern.proc.pathname  .285 : '/sbin/dhclient'      (uid 0)
  kern.proc.pathname  .328 : '/sbin/devd'          (uid 0)
  kern.proc.pathname  .411 : '/usr/sbin/syslogd'   (uid 0)
  kern.proc.pathname  .699 : '/usr/sbin/sshd'      (uid 0)
  kern.proc.pathname  .730 : '/usr/sbin/cron'      (uid 0)

## DEFAULT CONFIG: kern.ps_argsopen=1 (gate disabled for args/cwd)
#   pathname still leaks; args/cwd also leak because the gate is short-circuited.
  kern.proc.pathname  .1   : rc=0 len= 11  '/sbin/init'
  kern.proc.args      .1   : rc=0 len= 14  '/sbin/init'      (ps_argsopen=1 disables gate)
  kern.proc.cwd       .1   : rc=0 len=  2  '/'

## access pattern note
These are "node-with-pid-child" sysctls. The pid is passed as a trailing MIB
element via sysctlnametomib("kern.proc.pathname", mib, &len) then mib[len]=pid
then sysctl(mib, len+1, ...). The dotted sysctlbyname("kern.proc.pathname.1")
form does NOT resolve (returns ENOENT) -- this is a sysctl(8)/sysctlbyname
quirk, NOT a privilege control. The MIB form above succeeds as any user.

## gate trace (why this is a real authorization gap)
sysctl_kern_proc_pathname  (kern_proc.c:2080-2117)  -> NO p_trespass / ps_argsopen gate
sysctl_kern_proc_args      (kern_proc.c:1897)       -> if((!ps_argsopen) && p_trespass(..)) goto done;
sysctl_kern_proc_cwd       (kern_proc.c:2052)       -> if((!ps_argsopen) && p_trespass(..)) goto done;
ps_argsopen default = 1 (kern_exec.c:103); admin sets it 0 to hide other procs'
args/cwd. Setting it to 0 does NOT stop pathname from leaking -> the gap is real.