DragonFlyBSD Kernel Audit
DF-1358 / trigger.c
← back to finding ↓ download raw
/* DF-1358 amr_quartz_get_work: completed[46] overflow when nstatus > 46 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define STACK_CANARY 0xAA
#define COMPLETED_SIZE 46

static int test_vuln(uint8_t nstatus){
    /* emulate stack frame with canary above completed[46] */
    uint8_t *frame = calloc(COMPLETED_SIZE + 8, 1);
    memset(frame + COMPLETED_SIZE, STACK_CANARY, 8);
    uint8_t *completed = frame;
    int overflow = 0;
    for (int i=0; i<nstatus; i++){
        if (i >= COMPLETED_SIZE) overflow++;
        else completed[i] = (uint8_t)i;
    }
    /* if overflow, bytes were written past completed[46] */
    int clobbered = 0;
    for (int i=0;i<8;i++) if (frame[COMPLETED_SIZE+i] != STACK_CANARY) clobbered++;
    free(frame);
    return clobbered + (overflow*1000);
}

static int test_fixed(uint8_t nstatus_in){
    uint8_t nstatus = nstatus_in;
    if (nstatus > COMPLETED_SIZE) nstatus = COMPLETED_SIZE;
    uint8_t *frame = calloc(COMPLETED_SIZE + 8, 1);
    memset(frame + COMPLETED_SIZE, STACK_CANARY, 8);
    for (int i=0;i<nstatus;i++) frame[i] = (uint8_t)i;
    int clobbered = 0;
    for (int i=0;i<8;i++) if (frame[COMPLETED_SIZE+i] != STACK_CANARY) clobbered++;
    free(frame);
    return clobbered;
}

int main(void){
    printf("== BEFORE-FIX (vulnerable) ==\n");
    int rc = test_vuln(200);    /* malicious HBA: nstatus = 200 */
    printf("BUG: completed[200] overflows stack[46] by 154 bytes (rc=%d clobbered canary=%d)\n", rc, rc%1000);
    printf("== AFTER-FIX ==\n");
    int rc2 = test_fixed(200);
    printf("FIX: nstatus clamped to 46, no overflow (rc=%d)\n", rc2);
    return 0;
}