escb_tasklet_complete() derives the empty data buffer index from the done list opcode the sequencer wrote: int edb = (dl->opcode & DL_PHY_MASK) - 1; /* [0xc1,0xc7] -> [0,6] */ DL_PHY_MASK is 7, so the subtraction yields -1 through 6, and the function already says that anything outside [0,6] is wrong: if (edb > 6 || edb < 0) { ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n", ...); ... } The block reports the problem and then falls through to let it happen. edb is used twice afterwards: asd_bytes_dmaed_tasklet() adds ascb->edb_index to it to index seq->edb_arr[], and the out: label at the end of the function hands the same value to asd_invalidate_edb(), which indexes both escb->eb[] and seq->edb_arr[]. asd_assign_edbs2escbs() gives the first ESCB edb_index 0, so for that one edb == -1 reads seq->edb_arr[-1], one pointer before the array, and dereferences whatever it finds. Finish the check the way it reads: return instead of falling through. Whether the sequencer can really report an opcode that makes this zero is not something the tree answers. It is firmware loaded with request_firmware(), the done list opcode is described only by the comment above, and there is no Documentation/ file and no MAINTAINERS entry for this driver. This is not a claim of a reachable out-of-bounds access, only that the driver goes on to index an array with a value it has just decided is invalid. The intent to bound what the sequencer supplies is already in the same file, in asd_bytes_dmaed_tasklet(): size = min(size, (u16) sizeof(phy->frame_rcvd)); which clamps a device-supplied length a few lines after indexing seq->edb_arr[] with a device-supplied index and no bound. One consequence worth naming: an ESCB dropped this way is not invalidated and so is not reposted to the sequencer, because the repost happens inside asd_invalidate_edb(). That takes one empty buffer out of circulation per malformed opcode. It is the lesser of the two, and recovering the ESCB instead would mean choosing some other buffer to invalidate, which this index cannot tell us. Fixes: 2908d778ab3e ("[SCSI] aic94xx: new driver") Cc: stable@vger.kernel.org Signed-off-by: Yehyeong Lee --- drivers/scsi/aic94xx/aic94xx_scb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 08c8dad9ad621..d050e5325b943 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -421,6 +421,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, le64_to_cpu(ascb->scb->header.next_scb), le16_to_cpu(ascb->scb->header.index), ascb->scb->header.opcode); + return; } /* Catch these before we mask off the sb_opcode bits */ -- 2.43.0