# DF-4373 VERDICT — divide-by-zero in dce_transform.c:710

**Status: not_reproduced — target hardware absent (no AMD GPU in QEMU guest).
The exploit chain is proven statically, link by link, from UABI to the faulting
instruction.**

## Reproduction attempt (honest)

- Guest: DragonFly 6.5-DEVELOPMENT `#0 Thu Jul 2 06:02:54 UTC 2026`, QEMU
  std VGA only (`vgapci0@pci0:0:2:0 class=0x030000 chip=0x11111234`).
- `/dev/dri` does not exist; `pciconf -l` shows no vendor 0x1002 device; the
  amdgpu DC path (`dce_transform.c` is compiled into the amdgpu module,
  sys/dev/drm/amd/amdgpu/Makefile:12-13) cannot attach.
- Probe built cleanly (`cc -O2`) and run: exit 2, "cannot open
  /dev/dri/card0". See `build.log` / `run.log`.
- Therefore the division could not be executed. Per the audit's status
  mapping, device-absent on the guest = `not_reproduced` with impact `none`
  *observed on this guest*; the analysis below is the deliverable.

## Why the bug is real (static proof chain, every step cited)

1. **Unprivileged reachability.** Modeset ioctls require DRM master; on any
   modern seat/desktop the session user holds DRM master (root not required
   otherwise). The faulting path runs during atomic *check*
   (`DRM_MODE_ATOMIC_TEST_ONLY` suffices): amdgpu_dm_atomic_check →
   dc_validate_global → resource_build_scaling (dc_resource.c:1119-1147) →
   transform_get_optimal_number_of_taps →
   dce_transform_get_max_num_of_supported_lines → division at :710.

2. **Plane rects are never clipped by amdgpu_dm.**
   `fill_rects_from_plane_state` (amdgpu_dm.c:2210-2238) copies raw
   `crtc_x/y/w/h`, rejects only zero dimensions, and sets
   `clip_rect = dst_rect` (:2238). amdgpu_dm never calls
   `drm_atomic_helper_check_plane_state` (verified: dm_plane_atomic_check at
   amdgpu_dm.c:3585-3603 only calls fill_rects + dc_validate_plane).

3. **Validation is format-only.** `dc_validate_plane` (dc_resource.c:2891):
   "TODO For now validates pixel format only" → returns DC_OK.

4. **The ≥16 guard tests the wrong rectangle.** `calculate_viewport`
   (dc_resource.c:543) computes `viewport.width = clip.width * surf_src.width
   / plane dst_rect.width` — SOURCE pixels. A plane with src 640 wide, dst 1
   wide, positioned flush off the right edge keeps viewport.width = 640, so
   `viewport.width < 16` (dc_resource.c:1122) does NOT trip.

5. **recout clamps to exactly zero.** `calculate_recout` (dc_resource.c:631-643):
   with stream dst = [0,640) and raw plane clip.x = 640:
   `recout.x = 0 + (640-0)*640/640 = 640`; clamp at :639-643:
   `recout.width = (0+640) - 640 = 0`. (struct rect fields are signed ints,
   dc_hw_types.h:107-112; the zero is exact, not an underflow.)

6. **prescaler_on forces recout to be used.** dce_transform.c:1359 sets
   `prescaler_on = true` unconditionally in `dce_transform_construct` (used by
   DCE100/110/112/120 resource pools — dce100_resource.c:523-533,
   dce110_resource.c:539-549, dce112_resource.c:538-548,
   dce120_resource.c:743-753). dce_transform.c:900-902:
   `viewport.width(640) > recout.width(0)` → `pixel_width = 0`.

7. **ASSERT does not stop execution.** os_types.h:48:
   `#define ASSERT(expr) WARN_ON(!(expr))` — :675 warns and falls through to
   `return (max_pixels_supports / pixel_width)` at :710 → integer #DE in
   kernel mode → trap → kernel panic.

Alternative zero source (no off-CRTC positioning): underscan. The connector
property "underscan hborder" (range 0..128, amdgpu_display.c:605-607) insets
`stream->dst` (amdgpu_dm.c:2502-2506) while `stream->src` stays the full mode;
a fully-visible 1px-wide plane then yields `recout.width = clip.width *
dst.width / src.width = 1*512/640 = 0` at dc_resource.c:637-638.

## Impact
Local DoS (kernel panic) by an unprivileged session user on any DragonFly
machine with a DCE100/110/112/120-era AMD GPU driven by the in-tree amdgpu DC
code. Same class as DF-3828/DF-3857/DF-3869 (DCE watermark divide families).

## Fix validation
Not possible on this guest (no AMD GPU; kernel build with the fix cannot be
exercised on DCE hardware). `fix.diff` is authored against the read-only tree
and returns 0 lines-supported for degenerate input, which makes
`dce_transform_get_optimal_number_of_taps` return false (:910-911 with
max_num_of_lines==0), failing validation cleanly instead of dividing.
fix_status: not_testable (hardware absent).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
