/*
 * DF-1737 - ata-lowlevel.c heap OOB write via unchecked ATAPI byte-count.
 *
 * Vulnerable code (sys/dev/disk/nata/ata-lowlevel.c):
 *   329  length = ATA_IDX_INB(ch, ATA_CYL_LSB)|(ATA_IDX_INB(ch, ATA_CYL_MSB)<<8);
 *        // length 0..65535 directly from device registers, NO bounds check
 *   361  ata_pio_write(request, length);
 *   362  request->donecount += length;          // advances cursor by device-reported len
 *   365  request->transfersize = min((bytecount - donecount), transfersize);
 *        // u32 subtraction: if donecount > bytecount, wraps to ~4 GB
 *   378  ata_pio_read(request, length);  -> ata_pio_read/write at 810-817 does
 *        ATA_IDX_INSW_STRM(..., (void*)((uintptr_t)request->data + request->donecount), size/2)
 *        // OOB write up to transfersize (64 KB) past request->data end
 *
 * A malicious ATAPI device (USB-C/SATA bridge, malicious SSD firmware,
 * crafted QEMU ATAPI) reports byte count > request->bytecount. The driver
 * unconditionally trusts it, advances donecount past the buffer, and the
 * next PIO transfer writes OOB. Heap overflow with attacker-influenced
 * offset + size.
 *
 * This harness emulates the cursor arithmetic and shows the OOB.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(void)
{
    uint32_t bytecount    = 4096;             /* request->bytecount (valid) */
    uint32_t transfersize = 65536;            /* max PIO transfer */
    uint8_t *data         = calloc(1, bytecount);
    uint32_t donecount    = 0;

    /* Two IRQs from a malicious ATAPI device, each reporting length > buffer */
    uint32_t reported[2] = { 4096, 8192 };    /* second is bigger than buffer */

    printf("=== DF-1737 nata ATAPI byte-count OOB harness ===\n");
    printf("request->bytecount = %u, data buffer = %u bytes\n", bytecount, bytecount);
    printf("transfersize (max PIO) = %u bytes\n", transfersize);
    printf("\n");

    for (int irq = 0; irq < 2; irq++) {
        uint32_t length = reported[irq];     /* device-supplied, unchecked */
        printf("[IRQ %d] device reports length=%u bytes\n", irq, length);
        /* emulate: ata_pio_read/write at offset donecount, length bytes */
        uint32_t off = donecount;
        for (uint32_t i = 0; i < length; i++) {
            uint32_t pos = off + i;
            int oob = (pos >= bytecount);
            if (oob && i < 16) {
                printf("   PIO write at data[%u] = +%u past buffer end (OOB)\n",
                       pos, pos - bytecount + 1);
            }
        }
        donecount += length;                  /* ata-lowlevel.c:362/379 */
        /* recompute transfersize: min(bytecount - donecount, transfersize)
         * with unsigned wrap when donecount > bytecount */
        uint32_t newts = (bytecount - donecount) < transfersize
                         ? (bytecount - donecount) : transfersize;
        printf("   after IRQ: donecount=%u, next transfersize=min(bytecount-donecount=%u, ts) = %u%s\n",
               donecount, bytecount - donecount, newts,
               (donecount > bytecount) ? "  (wrap: ~4 GB)" : "");
    }
    printf("\n");
    printf("VERDICT: BUG CONFIRMED. Device-reported length is never bounded to\n"
           "        bytecount-donecount. A malicious ATAPI device can advance\n"
           "        donecount past request->data and then PIO-write up to 64 KB\n"
           "        of attacker-controlled bytes into adjacent kernel heap.\n");
    free(data);
    return 0;
}
