⬢ DragonFlyBSD Kernel Audit
DF-4225 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4225",
  "status": "untested",
  "reproduced": 0,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Kernel path untestable on this guest (no DRM device; DRM_IOCTL_MODE_SETCRTC cannot be issued), but both halves of the bug are proven on the guest toolchain: (1) verbatim drm_mode_validate_basic() ACCEPTS the crafted umode {clock=108000, h 1/2/3/65536, v 1/2/3/65536} with MODE_OK \u2014 the function only checks monotonicity, never magnitude; (2) verbatim drm_mode_vrefresh() then computes den = 65536*65536 which wraps to 0 in unsigned int and DIV_ROUND_CLOSEST(num,0) raises SIGFPE (exit=136) at drm_modes.c:796, at -O2 and -O0. On real hardware the mode enters via drm_crtc.c:655 (setcrtc umode) and the trap fires in the radeon/amdgpu DPM vrefresh consumers (r600_dpm.c:195, rs780_dpm.c:66, amdgpu_dpm.c:178) \u2014 local kernel-panic DoS for a DRM master. No memory corruption.",
  "exploit_chain": "open /dev/dri/card0 -> SET_MASTER -> DRM_IOCTL_MODE_SETCRTC{mode_valid=1, modeinfo htotal=65536 vtotal=65536, monotonic 1/2/3 chains, clock=108000} -> drm_crtc.c:655 drm_mode_convert_umode -> MODE_OK (no magnitude cap) -> modeset commit -> radeon DPM: r600_dpm.c:195 drm_mode_vrefresh(&hw_mode) -> drm_modes.c:796 num/0 -> #DE -> panic.",
  "evidence": "run.log: umode validate_basic status=0 then [marker] VREFRESH: drm_modes.c:796 then Floating point exception (core dumped) exit=136 (both -O2 and -O0); harness.c case 5; env.txt documents absent DRM device.",
  "kernel_refs": [
    "sys/dev/drm/drm_modes.c:787",
    "sys/dev/drm/drm_modes.c:796",
    "sys/dev/drm/drm_modes.c:1102",
    "sys/dev/drm/drm_modes.c:1691",
    "sys/dev/drm/drm_crtc.c:655",
    "sys/dev/drm/radeon/r600_dpm.c:195",
    "sys/dev/drm/drm_probe_helper.c:526"
  ],
  "poc_changes": "self-authored (case 5 of the DF-4224 harness, shared verbatim extracts); htotal/vtotal read from argv so GCC cannot fold the wrap",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 300,
  "guest_dirty": 0,
  "build_cmd": "cd /tmp && cc -O2 -Wall -o harness harness.c && cc -O0 -g -o harness_O0 harness.c",
  "run_cmd": "cd /tmp && ./harness 5 0 65536 65536; ./harness_O0 5 0 65536 65536",
  "code_hash": "c4dc7f52393275f62ec75a0f94800c11c15dae9d3ecb5a16a95e1d2ff41b3c72",
  "notes": "Same division also feeds drm_mode_hsync (clock*1000 int overflow, garbage values only). Guest lacks any GPU DRM device so ioctl issuance is impossible; SIGFPE on the identical ABI is the strongest achievable evidence.",
  "recommended_fix": "Widen num/den to u64 in drm_mode_vrefresh (drm_modes.c:784-787) and add a USHRT_MAX magnitude cap for h/v timings in drm_mode_validate_basic(), matching the boundary drm_mode_convert_to_umode already WARNs about.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched-kernel test impossible on this guest (no DRM hardware). fix.diff removes the wrap by construction ((u64)65536*65536 = 2^32 != 0) and the validate_basic cap rejects the umode before it can be programmed; harness-level equivalence: with den computed in u64 the harness case-5 division returns 0 instead of trapping.",
  "fix_evidence": "fix.diff; run.log validate_basic acceptance demonstrates the exact acceptance path the cap closes"
}