DF-5321 / run.log
DF-5321 baseline (UNPATCHED production sys/bus/firewire/firewire.c)
====================================================================
guest: DragonFly dfbsd 6.5-DEVELOPMENT #0 X86_64_GENERIC, 6 vCPUs, no
FireWire hardware; module df5321.ko compiles the unmodified production
firewire.c in and drives its real completion paths
(fw_rcv / fw_tl2xfer / firewire_xfer_timeout / fw_get_tlabel /
fw_xfer_free_buf / fw_tl_free) from three lwkt threads modelling the
receiving interrupt context, the 10 Hz watchdog callout, and the
/dev/fw FW_ASYREQ ioctl waiter (fwdev.c: tsleep(xfer) -> wakeup ->
fw_xfer_free_buf).
--- mode 1: FW_ASYREQ scenario (run_mode1.sh) -------------------------
$ kldload /root/df5321/df5321.ko
$ sysctl kern.df5321_mode=1 kern.df5321_iters=3000
$ sysctl kern.df5321_fire=1
(ssh dies; serial console, full copy in run_mode1_console.log / panic.txt)
DF5321: mode 1 starting (3000 attempts, PRODUCTION firewire.c completion paths)
root0: split transaction timeout dst=0x101 tl=0x1 state=3
Fatal trap 12: page fault while in kernel mode
cpuid = 2; lapic id = 2
fault virtual address = 0x8
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff82601a8c
stack pointer = 0x10:0xfffff801183dfa40
frame pointer = 0x10:0xfffff801183dfa90
code segment = base = 0x0, limit = 0xfffff, type = 0x1b
processor eflags = interrupt enabled, resume, IOPL = 0
current process = Idle
current thread = pri 12 (CRIT)
kernel: type 12 trap, code=0
CPU2 stopping CPUs: 0x0000003b
stopped
Stopped at firewire_xfer_timeout+0xbc: movq 0x8(%rax),%rax
db>
=> PANIC on the first attempt. The watchdog CPU (crit section does not
exclude other CPUs) dereferenced a tlabel whose xfer field read as
NULL because the FW_ASYREQ waiter's fw_xfer_free_buf() -> fw_tl_free()
had already unlinked and kfree'd that exact `struct tlabel` between
the watchdog's STAILQ_FIRST() (firewire.c:336) and tl->xfer
(firewire.c:337). Use-after-free read of the freed 16-byte tlabel;
with non-zeroed reuse it dereferences an attacker-influenced pointer.
--- mode 2: kernel-handler scenario (run.sh, act.hand = production
fw_asy_callback_free, as fw_phy_config firewire.c:1078 and fw_bmr's
fwmem_write_quad firewire.c:2169-2170 use) ---------------------------
$ kldload /root/df5321/df5321.ko
$ sysctl kern.df5321_mode=2 kern.df5321_iters=3000
$ sysctl kern.df5321_fire=1
(serial console; identical signature)
DF5321: mode 2 starting (3000 attempts, PRODUCTION firewire.c completion paths)
root0: split transaction timeout dst=0x101 tl=0x1 state=3
Fatal trap 12: page fault while in kernel mode
cpuid = 2; lapic id = 2
fault virtual address = 0x8
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff82601a8c
...
Stopped at firewire_xfer_timeout+0xbc: movq 0x8(%rax),%rax
db>
=> PANIC again on the first attempt. Here the first completion
(fw_xfer_done via either path) ran the production
fw_asy_callback_free, whose fw_xfer_free() -> fw_tl_free() removed
and kfree'd the tlabel under the scanning watchdog -> same tlabel
use-after-free; absent the reuse-as-zeroed luck this is the
double-free / wild-pointer deref primitive.
--- Both runs reproduced from a fresh `vm.sh reset with-src` boot;
guest `down` at the db> prompt afterwards.