# DF-3081 — VERDICT

**Status: reproduced** (deterministic; guest stayed up).
**Impact: leak** — unprivileged disclosure of every process's executable
path (root daemons included) via `/proc/<pid>/file` and `/proc/<pid>/exe`.

## How it reproduces
1. Resolving `/proc/710/file` walks `procfs_lookup` Pproc for pid 710;
   with `security.ps_showallprocs=1` (default) the directory resolves for
   any user (sys/vfs/procfs/procfs_vnops.c:830-835).
2. The `Pfile` target has `pt_valid == NULL`
   (sys/vfs/procfs/procfs_vnops.c:147-148) so the per-target loop at
   :837-842 always matches `file`/`exe` — no validity filter.
3. `readlink(2)` performs no mode check on VLNK; `procfs_readlink`'s Pfile
   case (sys/vfs/procfs/procfs_vnops.c:1128-1162) runs `pfs_pfind`, checks
   only `p_ucred != NULL`, then `cache_fullpath()` on `p_textnch` and
   `uiomove`s the full path out. No CHECKIO / p_trespass / prison /
   showallprocs gate anywhere on this path (contrast `procfs_docmdline`,
   procfs_status.c:203-205, which gates argv reads exactly this way).
4. Observed as uid 1001: `/sbin/init`, `/sbin/dhclient`, `/sbin/devd`,
   `/usr/sbin/syslogd`, `/sbin/hammer2`, `/usr/sbin/sshd` (run.log).

The in-tree comment at sys/vfs/procfs/procfs_mem.c:212-219 acknowledges
"the /proc/pid/file object exposes an information leak that shouldn't
happen" — the `pt_valid == NULL` registration keeps it live.

## Why Low (not higher)
Information-only: path strings, no memory contents. `ps` already exposes
comm names and (with `kern.ps_argsopen=1`, as on this guest) full argv;
the delta is the authoritative binary path for every process regardless
of that sysctl. Valuable for recon (admin tooling paths, home-dir
binaries), consistent with Low/C:L.

## Fix validation
Not rebuilt (Low info-leak finding). `fix.diff` mirrors the docmdline
policy: `CHECKIO(curproc, procp) || p_trespass(...)` fails → emit
"unknown" (readlink) / size of "unknown" (getattr). Root and same-uid
debuggers keep full resolution.
fix_status: not_testable (authored only).
