DragonFlyBSD Kernel Audit
DF-2680 / run.log
← back to finding ↓ download raw
DF-2680 runtime evidence (DragonFly 6.5-DEVELOPMENT #0 X86_64_GENERIC, stock kernel)

$ sh run_seq.sh
== control (live async_proc) ==
victim2: pid=1961 armed, sleeping 20
victim2: GOT_SIGIO (live path works) pid=1961
== stale (victim exits, async_proc dangles) ==
victim: pid=1993 enabled FIOASYNC on /dev/devctl, exiting
-- result:
GOT_SIGIO pid=1994 (never opened devctl)

Repetition (5 rounds, victim exits each time, fresh catchers each time):
round 2: GOT_SIGIO pid=2032 (never opened devctl)
round 3: GOT_SIGIO pid=2048 (never opened devctl)
round 4: GOT_SIGIO pid=2075 (never opened devctl)
round 5: GOT_SIGIO pid=2091 (never opened devctl)

Interpretation:
- victim (root) opened /dev/devctl (0600, SYSCAP_RESTRICTEDROOT gated) and
  issued FIOASYNC=1: devioctl() stored raw curproc in devsoftc.async_proc
  (sys/kern/subr_bus.c:412-417) with no reference taken.
- victim exited; devclose() (subr_bus.c:352-361) reset inuse but left
  async_proc pointing at the reaped-and-freed struct proc
  (kfree(p, M_PROC) at sys/kern/kern_exit.c:1336).
- The next fork (catcher, pid = victim+1) recycled the freed proc chunk.
- Each devctl event ran devctl_queue_data() -> ksignal(stale proc, SIGIO)
  (subr_bus.c:521-523) -> lwpsignal() executed PHOLD(p),
  lwkt_gettoken(&p->p_token) and the lwp walk on the recycled memory and
  delivered SIGIO to a process that never opened /dev/devctl.
- With a non-proc kernel allocation recycling the chunk instead, the same
  PHOLD/token writes land in foreign kernel objects (memory corruption).