# DF-2783 VERDICT

**Status: reproduced (leak, certain). Fix validated (fixed).**

## Baseline (stock kernel #0, Thu Jul 2 06:02:54 UTC 2026)

Unprivileged uid 1001, own `semget(IPC_PRIVATE, 3, 0600)` + `IPC_STAT`:

```
IPC_STAT : sem_base=0xfffff8008d363168 nsems=3 mode=1600   (run 1)
IPC_STAT : sem_base=0xfffff8008d363168 nsems=3 mode=1600   (run 2)
IPC_STAT : sem_base=0xfffff8008d363168 nsems=3 mode=1600   (run 3)
LEAK: kernel pointer disclosed to uid=1001  (rc=0)
```

`0xfffff800_8d363168` is a live kernel-map heap address — the M_SEM
allocation returned by `kmalloc()` at sysv_sem.c:698 and stored in
`semaptr->ds.sem_base` — copied verbatim by `copyout(&semaptr->ds, …)`
at sys/kern/sysv_sem.c:431 (IPC_STAT) and :450 (SEM_STAT).  Pointer is
deterministic within a boot/alloc-sequence window (three identical
values) and drifts with heap churn (see leak_sample.txt: 0xfffff8008d981fe8
… across later runs) — always a non-NULL kernel address.  Leak class:
kernel heap-address disclosure → KASLR-relevant; on this INVARIANTS
guest KASLR is off, but the disclosure is configuration-independent.

## PoC changes vs seed

None (finding + PoC authored in this run).  SEM_STAT probe initially
passed the IPC id; the kernel's pre-switch seq check (sysv_sem.c:376-380)
plus in-case index check (:441) make SEM_STAT unconditionally EINVAL
(dead command — noted in README); leak stands on IPC_STAT alone.

## Fix validation (patched kernel #1, built in-guest from fix.diff)

```
IPC_STAT : sem_base=0x0 nsems=3 mode=1600
clean: kernel pointer zeroed to uid=1001  (rc=2)
```

Bad behavior gone: pointer is NULL; command still succeeds otherwise.

## Impact ceiling

Low — single-pointer kernel-heap disclosure to any IPC_R holder (any
user, own semaphore).  No memory corruption; defeats kernel address
randomization and aids heap-layout inference for other bugs.
