DragonFlyBSD Kernel Audit
DF-1536 / harness.c
← back to finding ↓ download raw
/* DF-1536/DF-1544: atom PS operand unbounded idx harness.
 * atom_get_src_int ATOM_ARG_PS reads idx=U8(0..255) from bytecode, then
 *   val = get_unaligned_le32(&ctx->ps[idx]);
 * where ctx->ps is the caller's params buffer (e.g., atom_asic_init's
 * uint32_t ps[16] = 64 bytes). idx=255 -> params+1020 byte offset,
 * deep into kernel stack.
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>

static int fixed = 0;

/* Simulated caller params buffer (atom_asic_init: uint32_t ps[16] = 64 bytes) */
static uint32_t ps[16];

static uint32_t atom_ps_read(uint8_t idx, int ps_size) {
    if (fixed) {
        if (idx + 4 > ps_size) {
            printf("PATCHED: rejected idx=%u (ps_size=%d)\n", idx, ps_size);
            return 0;
        }
    } else {
        /* original buggy: no bounds */
    }
    /* val = get_unaligned_le32(&ctx->ps[idx]); idx is byte offset */
    if (idx >= sizeof(ps)) {
        printf("BUG: idx=%u reads byte offset %u into kernel stack (buffer=%zu)\n",
               idx, idx, sizeof(ps));
        return 0xDEAD;
    }
    uint8_t *p = (uint8_t*)ps;
    return p[idx] | (p[idx+1]<<8) | (p[idx+2]<<16) | (p[idx+3]<<24);
}

int main(int argc, char **argv) {
    if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1;

    int ps_size = 64;  /* what atom_asic_init declares */
    /* attacker scenario: VBIOS op PS[255] */
    uint32_t v = atom_ps_read(255, ps_size);
    if (fixed) {
        printf("RESULT: PATCHED - idx=255 rejected\n");
    } else {
        printf("RESULT: BUGGY - idx=255 reads ps+255 (OOB by %d bytes)\n", 255-64);
    }
    return 0;
}