diff options
| author | sakumisu <[email protected]> | 2026-10-22 12:41:45 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2026-10-23 18:29:36 +0800 |
| commit | 2397226c48fea88bdb742651f9280f47eef3197a (patch) | |
| tree | 333db0904d5d3591a93a79f564c4a859f9957ae0 /class/msc | |
| parent | 26b0feb09bb58ebb7a3161b5605f8e186b96db1f (diff) | |
fix(security): check array overflowdev
Signed-off-by: sakumisu <[email protected]>
Diffstat (limited to 'class/msc')
| -rw-r--r-- | class/msc/usbd_msc.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/class/msc/usbd_msc.c b/class/msc/usbd_msc.c index d21051f0..cd3fc4f7 100644 --- a/class/msc/usbd_msc.c +++ b/class/msc/usbd_msc.c @@ -538,6 +538,26 @@ static bool SCSI_readCapacity16(uint8_t busid, uint8_t **data, uint32_t *len) return true; } +/* Check the range before adding LBAs or multiplying the transfer size. */ +static bool SCSI_checkReadWriteRange(uint8_t busid) +{ + uint8_t lun = g_usbd_msc[busid].cbw.bLUN; + uint32_t capacity = g_usbd_msc[busid].scsi_blk_nbr[lun]; + uint32_t block_size = g_usbd_msc[busid].scsi_blk_size[lun]; + + if (g_usbd_msc[busid].start_sector >= capacity || + g_usbd_msc[busid].nsectors > capacity - g_usbd_msc[busid].start_sector) { + SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + return false; + } + if (block_size == 0 || g_usbd_msc[busid].nsectors == 0 || + g_usbd_msc[busid].nsectors > UINT32_MAX / block_size) { + SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA); + return false; + } + return true; +} + static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len) { (void)data; @@ -551,8 +571,7 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */ - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { - SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + if (!SCSI_checkReadWriteRange(busid)) { return false; } @@ -584,8 +603,7 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */ - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { - SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + if (!SCSI_checkReadWriteRange(busid)) { return false; } @@ -619,10 +637,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */ - data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { + if (!SCSI_checkReadWriteRange(busid)) { return false; } + data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; if (g_usbd_msc[busid].cbw.dDataLength != data_len) { return false; @@ -648,10 +666,10 @@ static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */ - data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { + if (!SCSI_checkReadWriteRange(busid)) { return false; } + data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; if (g_usbd_msc[busid].cbw.dDataLength != data_len) { return false; @@ -736,6 +754,9 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes) if ((g_usbd_msc[busid].cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc[busid].cbw.bCBLength < 1) || (g_usbd_msc[busid].cbw.bCBLength > 16)) { SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND); return false; + } else if (g_usbd_msc[busid].cbw.bLUN > g_usbd_msc[busid].max_lun) { + SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDLUN); + return false; } else { USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]); switch (g_usbd_msc[busid].cbw.CB[0]) { |
