โฌข DragonFlyBSD Kernel Audit
DF-0079 / fix_run.log
โ† back to finding โ†“ download raw
================================================================================
DF-0079 โ€” FIX VALIDATION RUN LOG (single-fix kernel #1)
================================================================================
Test:        re-run the SAME PoC (./df0079) on the patched kernel; the
             infinite-loop DoS must NOT reproduce โ€” write() must return in
             finite time. Contrast with the unpatched #0 baseline (write hangs
             forever, full-system DoS, only reset recovers).

Patched kernel (kern.version):
  DragonFly 6.5-DEVELOPMENT #1: Thu Jul  2 15:52:03 UTC 2026
      root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC
  kernel.stripped sha256 = 7f49550e41a1fba71b19d49f44f4d5f6144e720657a68c4a215b233a04d9b677
  (built from /usr/src with fix.diff applied: sys/kern/kern_memio.c:225
   u_int c;  ->  size_t c;)

PoC build (as maxx, uid 1001):
  $ cd poc/DF-0079 && sh ./build.sh
  BUILD_OK: -rwxr-xr-x  1 maxx  maxx  9104 Jul  2 15:58 df0079
  BUILD_EXIT=0

================================================================================
Run #1 โ€” single proc, /dev/null  (the original trigger)
================================================================================
[15:58:13] calling ./df0079 (single proc, /dev/null) on PATCHED #1 kernel
DF-0079: triggering /dev/null infinite-loop DoS, 1 procs
DF-0079: pid=856 calling write(fd, 0x1, 2^32)
write returned 4294967296 (unexpected!)
        0.00 real         0.00 user         0.00 sys
TRIGGER_EXIT=0
guest status immediately after: UP, responsive, load ~0.1

================================================================================
Run #2 โ€” single proc, /dev/null  (determinism)
================================================================================
DF-0079: triggering /dev/null infinite-loop DoS, 1 procs
DF-0079: pid=915 calling write(fd, 0x1, 2^32)
write returned 4294967296 (unexpected!)
        0.00 real         0.00 user         0.00 sys
EXIT=0

================================================================================
Run #3 โ€” single proc, /dev/null  (determinism)
================================================================================
DF-0079: triggering /dev/null infinite-loop DoS, 1 procs
DF-0079: pid=921 calling write(fd, 0x1, 2^32)
write returned 4294967296 (unexpected!)
        0.00 real         0.00 user         0.00 sys
EXIT=0

================================================================================
Run #4 โ€” /dev/zero variant (case 12, same u_int truncation root cause)
================================================================================
DF-0079: triggering /dev/zero infinite-loop DoS, 1 procs
DF-0079: pid=927 calling write(fd, 0x1, 2^32)
write returned 4294967296 (unexpected!)
        0.00 real         0.00 user         0.00 sys
EXIT=0

================================================================================
Run #5 โ€” fork-2 variant (would wedge 2 CPUs on the unpatched kernel)
================================================================================
DF-0079: triggering /dev/null infinite-loop DoS, 2 procs
DF-0079: pid=933 calling write(fd, 0x1, 2^32)
DF-0079: spawned 2 wedged children on /dev/null
write returned 4294967296 (unexpected!)
write returned 4294967296 (unexpected!)
        0.00 real         0.00 user         0.00 sys
EXIT=0
(both children returned cleanly; no CPU pegged; guest load ~0.12)

================================================================================
Final guest state after all 5 runs
================================================================================
status: up
Thu Jul  2 15:58:51 UTC 2026
 3:58PM  up 1 min, 0 users, load averages: 0.12, 0.05, 0.02
(no df0079 processes lingering; no CPU pegged; box fully responsive)

================================================================================
VERDICT: FIXED
================================================================================
On the unpatched #0 kernel: a single `write(/dev/null, 0x1, 2^32)` by uid 1001
  pegged one CPU at 100% in-kernel (mmrw) FOREVER; ssh to BOTH maxx and root
  was starved within ~1 s (Connection reset / timeout 124); `vm.sh status`
  reported `down`; only `vm.sh reset` recovered. Reproduced deterministically.
On the single-fix #1 kernel: the SAME write returns 4294967296 (= 2^32) in
  0.00 s real (sub-millisecond), EXIT=0, across 5 runs (single /dev/null x3,
  /dev/zero x1, fork-2 x1). Guest stays UP and responsive; load stays ~0.1.

Mechanism of the fix: widening `c` from `u_int` (32-bit) to `size_t` (64-bit)
  at sys/kern/kern_memio.c:225 means `c = iov->iov_len` (= 2^32) no longer
  truncates to 0. The bookkeeping at :380/382 subtracts the full 2^32, draining
  uio_resid to 0 in a single iteration, so the `while (uio_resid > 0)` predicate
  at :232 exits and mmrw returns. This closes /dev/null (:298), /dev/zero
  (:364) AND /dev/kmem (:264, root-only) in one change. The other in-function
  uses of `c` (uiomove/read_random/add_buffer_randomness_src at
  :253/:289/:309/:314/:319/:328/:354/:372) all operate on values already
  bounded by min(..., PAGE_SIZE), so widening c changes no bounded-path
  behaviour โ€” confirmed by the clean rc=0 build (fix_build.log).

nativekernel build: rc=0, no errors (see fix_build.log, 35510 lines).
  kern_memio.o rebuilt at 15:50 (post-patch); mmrw/mmwrite symbols present.
================================================================================