# DF-4807 — VERDICT

**Status: not_reproduced** (the stale-byte transmission facet is
hardware-gated on this guest: it requires an IEEE1284 *master* peer to
complete the peripheral-side negotiation before ppiwrite's data loop is
reachable). reproduced=0, impact=none *as demonstrable on this guest*;
the code defect is certain, and its runtime consequence is proven by the
line-identical, runtime-verified twin DF-4535 (lpt).

## Root cause (path:line)

`sys/dev/misc/ppi/ppi.c:478` — `uiomove(ppi->ppi_buffer, len, uio);`
return value discarded; `byte_peripheral_write(ppbus, ppi->ppi_buffer,
len, &sent)` (ppi.c:479-480) transmits `len` bytes regardless of how
many uiomove actually copied. On EFAULT: stale `ppi_buffer` content
(prior write's bytes) is transmitted to the 1284 master; if uiomove
copies 0 bytes, `uio_resid` never shrinks and the loop re-sends the
stale chunk indefinitely (bounded only by the wire handshake timeouts /
PCATCH). Same defect class as DF-4535 (`sys/dev/misc/lpt/lpt.c:763`,
reproduced live: 133,120 stale bytes out the port).

## What was verified live (ppi.ko built with PERIPH_1284, pristine
sources, guest 6.5-DEVELOPMENT X86_64_GENERIC, ppc0 0x378 irq7)

1. **Path entry + block**: `write(fd, faulting_buf, 8192)` blocks in the
   kernel at ppi.c:459 — `ps`: `S3 wchan=ppiwrite`; SIGKILL terminates
   (PCATCH sleep, unlike lpt's polled-mode unkillable loop). The data
   loop at ppi.c:477 requires `PPB_PERIPHERAL_IDLE`, which requires a
   remote 1284 master host — absent on QEMU (SPP emulation only).
2. **Binary proof of the dropped check** (`ppiwrite.dis`, objdump -dr of
   the loaded module):
   ```
   58e: callq  ...   R_X86_64_PLT32 uiomove-0x4
   593: mov    %r15,%rsi          <- no test of %eax (uiomove rc)
   ...
   5a0: callq  ...   R_X86_64_PLT32 byte_peripheral_write-0x4
   5a5: mov    %eax,%r15d
   5a8: test   %eax,%eax          <- THIS rc is checked
   ```
3. Sibling verification cross-reference: DF-4535 evidence pack (same
   guest, same port) demonstrates the identical dropped-uiomove shape
   transmitting stale kernel bytes out the parallel port in lpt.

## Exploit chain

None. Privileged-only (0600 root:wheel), PERIPH_1284-gated,
peer-hardware-gated; impact ceiling is stale-buffer disclosure over the
parallel cable plus a killable retransmit spin. Fix is defensive.

## Fix (not hardware-validated on this guest — trivial check-and-bail)

```diff
 	while ((len = (int)szmin(uio->uio_resid, BUFSIZE)) != 0) {
-		uiomove(ppi->ppi_buffer, (size_t)len, uio);
+		if ((error = uiomove(ppi->ppi_buffer, (size_t)len, uio)))
+			goto error;
 		if ((error = byte_peripheral_write(ppbus,
 						ppi->ppi_buffer, len, &sent)))
 			goto error;
```

(Validating this end-to-end requires a 1284 master peer; the fix is the
same check-and-bail validated for DF-4535.)

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

(No fix.diff for this item: documented recommendation only - see Fix above.)
