DF-3045 / env.txt
Guest (single-tenant QEMU/KVM rig, owned for the whole verification run)
DragonFly dfbsd 6.5-DEVELOPMENT #0..#4 x86_64 (kernel rebuilt in-place
during the run; decisive baseline boot: "DragonFly 6.5-DEVELOPMENT #2";
decisive fixed boot: "DragonFly 6.5-DEVELOPMENT #2" of 16:53:09 UTC 2026,
both built from /usr/src on the guest)
CPU: QEMU Virtual CPU version 2.5+ (6 vCPUs), 4094 MB RAM
Compiler: cc 8.3 [DragonFly] Release/2019-02-22
kern.osreldate=600519
Rig
- /usr/src/sys/vfs/nfs/dfrig12_bootp.c (this packs copy = the exact file
compiled into the guest kernel; sha256
f017052c0ccd052813c7dabfb13ea4ec0b7e28046308beef1dbef707102b9902)
- /usr/src/sys/conf/files: one added line
"vfs/nfs/dfrig12_bootp.c optional nfs"
- built with: cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC
&& make installkernel (stock X86_64_GENERIC config: NO options BOOTP;
the harness compiles the production bootp_subr.c verbatim via #include,
sha256-gated by build.sh against the audited tree)
- verbatim gate hashes:
baseline sys/vfs/nfs/bootp_subr.c:
ada7d13fe5cd824dfb971384f00c04b5fd819eea82c0ab512f5dbd577bfc8ce3
fixed (baseline + all three fix hunks):
52154f24f8d0f6fd8964d8cab366e81a377c5c10c622a7b3531c293d33be0148
- trigger: sysctl -w kern.dfrig12=<test#>; markers via
sysctl -n kern.dfrig12_status; verbatim bootpc console output in dmesg
- attacker model: crafted BOOTP/DHCP replies injected at the verbatim
soreceive seam; origin 6.6.6.6 : 9999 (a port no DHCP server uses);
"blind" mode computes the reply XID purely from source constants
(seed 0xFFFF0000, +0x100/interface, +1/first compose on an unresolved
ifctx), never from an observed packet.
Notable guest facts
- stock kernel boots from disk (no netboot): bootpc code is NOT in the
shipped X86_64_GENERIC (options BOOTP absent; LINT64-only) -- exactly
the reachability gate the findings describe.
- the production `while (time_uptime < atimo)` loop in bootpc_call
relies on the real blocking soreceive to re-read the non-volatile
time_uptime (sys/time.h:163); the harness stub yields via lwkt_yield()
on its EWOULDBLOCK path to model that (see harness comment).