⬢ DragonFlyBSD Kernel Audit
DF-3457 / run.log
← back to finding ↓ download raw
DF-3457 — run.log (decisive run, 2026-09-13 05:57-06:07 UTC)

Guest: DragonFly dfbsd 6.5-DEVELOPMENT #0 X86_64_GENERIC (INVARIANTS), 6 vCPU KVM
Snapshot: with-src (clean), booted fresh for this run.

CONTROL (churn accidentally not executable, gif0 stable, 300s):
  6 unprivileged flooders (maxx), 512B UDP -> 10.99.0.1 via gif0:
    ok=1260591 packets, EAFNOSUPPORT=0, netdown=0, other=0
    gif0 Opkts=1260596 (gif_output stats corroborate)
  => a configured gif0 NEVER returns EAFNOSUPPORT to a sender;
     baseline stability established.

RACE RUN:
  maxx$ nohup /tmp/df3457/floodi 6 10.99.0.1 ... &   (6 processes)
  root# /tmp/df3457/churn.sh 300
      (gif0 create; tunnel 127.0.0.1 -> 127.0.0.99; 10.98.0.1/10.98.0.2 up;
       route add -net 10.99.0.0/24 -iface gif0; sleep 0.001; destroy; repeat)

  ~75 s into the race the guest went down with:

--- panic.txt (serial console, full copy in panic.txt) ---
Fatal trap 12: page fault while in kernel mode
cpuid = 3; lapic id = 3
fault virtual address	= 0x1
fault code		= supervisor read data, page not present
instruction pointer	= 0x8:0xffffffff8073a228
...
kernel: type 12 trap, code=0
CPU3 stopping CPUs: 0x00000037
Stopped at      gif_output+0x128:       movzbl 0x1(%rax),%eax
db>
---

Mechanism (fault VA == 0x1 => %rax == NULL => sc->gif_psrc == NULL):
  gif_output_serialized() validated gif_psrc != NULL at if_gif.c:345-350,
  then re-read sc->gif_psrc->sa_family at if_gif.c:373.  Between the two,
  gif_clone_destroy() -> gif_delete_tunnel() (running in the ifconfig
  destroy syscall thread, holding NO gif0 serializer) executed
  kfree(sc->gif_psrc); sc->gif_psrc = NULL;  (if_gif.c:821-828).
  The NULL write landed inside the window -> movzbl 0x1(NULL) -> trap 12.

  This is the unserialized-teardown half of the destroy-path lifetime bug:
  with slightly different interleaving the same window reads the kfree'd
  (INVARIANTS 0xdeadc0de-poisoned, kern_slaballoc.c WEIRD_ADDR) sockaddr
  or the freed softc itself instead of the NULL.

Actors: traffic side = unprivileged user (maxx, uid 1001) sending UDP
into a root-configured gif0 route; teardown side = root `ifconfig gif0
destroy` churn.  The faulting deref runs in the traffic path's context.

Runtime to panic: ~75 s (flood ~20-25k pps aggregate, ~1-2ms tunnel
up-time per churn cycle).