Commit 926cde5f authored by Prasad J Pandit's avatar Prasad J Pandit Committed by Paolo Bonzini
Browse files

scsi: esp: make cmdbuf big enough for maximum CDB size



While doing DMA read into ESP command buffer 's->cmdbuf', it could
write past the 's->cmdbuf' area, if it was transferring more than 16
bytes.  Increase the command buffer size to 32, which is maximum when
's->do_cmd' is set, and add a check on 'len' to avoid OOB access.

Reported-by: default avatarLi Qiang <liqiang6-s@360.cn>
Signed-off-by: default avatarPrasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 7f0b6e11
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -248,6 +248,8 @@ static void esp_do_dma(ESPState *s)
    len = s->dma_left;
    if (s->do_cmd) {
        trace_esp_do_dma(s->cmdlen, len);
        assert (s->cmdlen <= sizeof(s->cmdbuf) &&
                len <= sizeof(s->cmdbuf) - s->cmdlen);
        s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
        return;
    }
@@ -345,7 +347,7 @@ static void handle_ti(ESPState *s)
    s->dma_counter = dmalen;

    if (s->do_cmd)
        minlen = (dmalen < 32) ? dmalen : 32;
        minlen = (dmalen < ESP_CMDBUF_SZ) ? dmalen : ESP_CMDBUF_SZ;
    else if (s->ti_size < 0)
        minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
    else
@@ -449,7 +451,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
        break;
    case ESP_FIFO:
        if (s->do_cmd) {
            if (s->cmdlen < TI_BUFSZ) {
            if (s->cmdlen < ESP_CMDBUF_SZ) {
                s->cmdbuf[s->cmdlen++] = val & 0xff;
            } else {
                trace_esp_error_fifo_overrun();
+2 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ void esp_init(hwaddr espaddr, int it_shift,

#define ESP_REGS 16
#define TI_BUFSZ 16
#define ESP_CMDBUF_SZ 32

typedef struct ESPState ESPState;

@@ -31,7 +32,7 @@ struct ESPState {
    SCSIBus bus;
    SCSIDevice *current_dev;
    SCSIRequest *current_req;
    uint8_t cmdbuf[TI_BUFSZ];
    uint8_t cmdbuf[ESP_CMDBUF_SZ];
    uint32_t cmdlen;
    uint32_t do_cmd;