# DF-1818 — Verification Verdict

## Verdict: REPRODUCED (source-confirmed + arithmetic-harness)

The slow-path advance bug is confirmed at
`sys/dev/misc/syscons/sckmsrndr.c:445`. The harness reproduces the
exact arithmetic and shows a 13824-byte framebuffer overrun for the
1366x768@24bpp right-border case.

## Mechanism

`fill_rect24` (sckmsrndr.c:414-448) computes `d = line_width - width*3`
(:420), the per-row right-padding. The fast path (:423-436) correctly
does `draw_pos += d` at :435 after each row. The slow path (:437-446)
— taken when `(draw_pos|line_width|width) & 3 != 0` — does
`draw_pos += line_width` at :445 instead of `draw_pos += d`. Since the
inner loop already advanced by `3*width`, the slow path advances by
`3*width + line_width` per row instead of `line_width`, drifting by
`3*width` per row. For the right-border call at :487-489 with
`width = rightpixel = fbi->width - scp->xsize*blk_width` (e.g. 6 at
1366x768), drift accumulates to `(height-1)*3*width = 767*18 = 13806`
bytes. The final `writeb` lands ~13824 bytes past the framebuffer
mapping. `writeb` is an unchecked volatile store.

## Harness evidence

```
DF-1818: fill_rect24 slow path (sckmsrndr.c:437-446)
  width=6 height=768 line_width=4096  d=4078 (per-row padding)
  BUGGY (+=line_width at :445): final draw_pos=3159552, 13824 bytes PAST fb end
  FIXED (+=d):                 final draw_pos=3145728, 0 bytes past fb end
  Per-row drift = 3*width = 18 bytes; total drift = (height-1)*3*width = 13806 bytes
```

## Why no live trigger on this guest

The slow path is reached only from `kms_draw_border` (sckmsrndr.c:487),
which runs under the syscons KMS renderer when a VT border is drawn on a
KMS framebuffer at 24bpp with non-4-aligned width. The audit guest
boots on serial console (`console=comconsole`), no KMS console attached.
Valid Phase-6 hard blocker.

## Exploit chain

Not applicable (needs KMS 24bpp console with unaligned border width).
No `uid=0` claim. Live ceiling: DoS panic when writeb hits an unmapped
page, or adjacent kmem corruption if the framebuffer is followed by
mapped kernel memory. Border color partially controls written bytes.

## PoC changes

- Added `harness.c`: reproduces the buggy and fixed slow-path arithmetic
  side by side.
- Added `fix.diff`: `draw_pos += line_width` → `draw_pos += d`.

## Fix

`fix.diff` changes line 445 from `draw_pos += line_width` to
`draw_pos += d`, matching the fast path at :435.

- BEFORE: harness shows final draw_pos 13824 bytes past fb end.
- AFTER: harness shows final draw_pos exactly at fb end (0 past).
