# DF-4158 VERDICT

**status: not_reproduced (by design — no user-reachable trigger exists today) | impact: none (hardening)**

## Was it reproduced?

Attempted on the live guest and **no impact could be produced**, because the
missing bounds check is not reachable with attacker-chosen values on this
kernel:

1. `vga_load_font`/`vga_save_font` (`vga.c:1189`, `1241`) have no FBIO
   ioctl anywhere in the tree (grep across sys/: no FBIOPUTFONT handler;
   `fb.c:741-765` returns ENODEV for font/palette-adjacent unknowns via the
   default arm).
2. All call sites are kernel-internal with clamped arguments:
   - `syscons.c:1653/1691/1727/3403-3417/4201-4207`, `scvidctl.c:674-678`:
     ch=0, count=256, fontsize∈{8,14,16} → max byte offset 8192 = the
     0x4000-byte... (256 glyphs × 32 B = 0x2000) well inside the font page.
   - `scvgarndr.c:380`: ch=`sc->mouse_char`, count=4, fontsize=32 → max
     offset (mouse_char+3)*32+128 ≤ 251*32+128 = 8160 < 0x4000.
     `mouse_char` is user-settable via MOUSE_MOUSECHAR but pre-clamped to
     ≤ (unsigned char)-1-4 = 251 (`scmouse.c:881`).
   - `scmouse.c:888`: same clamped ch, count=4.
3. `vgafuzz` (run.log) additionally proves the *actually reachable* vga.c
   sinks reject or safely consume every hostile scalar: modes, palette
   index/count, dispstart, linewidth. FBIO_SETLINEWIDTH INT_MAX is accepted
   but lands only in one CRTC byte + the `va_line_width` int — I traced
   every consumer of `va_line_width` (set_display_start arithmetic → CRTC
   bytes; planar/packed_fill length → window_size-bounded loops;
   genfbread → window_size/modulo) and none turns it into an unclamped
   memory op. FBIO_SETDISPSTART likewise only programs CRTC/ATC bytes.

Guest survived the whole battery (dmesg tail clean, subsequent ssh runs
fine). `/dev/vga0` absent (FB_INSTALL_CDEV not compiled; would be 02660
root:wheel when compiled — `vga_isa.c:156`). /dev/ttyv* 0600 root:wheel;
unprivileged `maxx` gets EPERM on open (run.log); the historical model is
that a vty is chowned to the user who logs in on it.

## Why file it at all

This is the classic shape that later becomes a real overflow the day one
new caller forwards an unchecked value (user-influenced scalars like
`mouse_char` already flow into this API). One-line clamp per function makes
the invariant local. Info severity, no demonstrated impact — consistent
with `not_reproduced`/impact none.

## Fix validation

Not meaningful (nothing to observe pre/post on this kernel). `fix.diff`
applies cleanly (`git apply --check`); it validates
`ch ≥ 0 && count ≥ 0 && ch+count ≤ 512` (0x4000-byte page / 32-byte glyph)
in both functions.

## 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.
