summaryrefslogtreecommitdiff
path: root/class/msc
diff options
context:
space:
mode:
Diffstat (limited to 'class/msc')
-rw-r--r--class/msc/usbd_msc.c37
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]) {