Skip to content

Commit 41e1c2d

Browse files
authored
Merge pull request #12727 from ARMmbed/mergify/bp/mbed-os-5.15/pr-12693
USBMSD security updates (bp #12693)
2 parents 978db96 + 95bb2a8 commit 41e1c2d

File tree

1 file changed

+35
-18
lines changed

1 file changed

+35
-18
lines changed

drivers/source/usb/USBMSD.cpp

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,14 @@ void USBMSD::_read_next()
565565

566566
void USBMSD::memoryWrite(uint8_t *buf, uint16_t size)
567567
{
568+
// Max sized packets are required to be sent until the transfer is complete
569+
MBED_ASSERT(_block_size % MAX_PACKET == 0);
570+
if ((size != MAX_PACKET) && (size != 0)) {
571+
_stage = ERROR;
572+
endpoint_stall(_bulk_out);
573+
return;
574+
}
575+
568576
if ((_addr + size) > _memory_size) {
569577
size = _memory_size - _addr;
570578
_stage = ERROR;
@@ -869,23 +877,25 @@ void USBMSD::memoryRead(void)
869877

870878
n = (_length > MAX_PACKET) ? MAX_PACKET : _length;
871879

872-
if ((_addr + n) > _memory_size) {
873-
n = _memory_size - _addr;
880+
if (_addr > (_memory_size - n)) {
881+
n = _addr < _memory_size ? _memory_size - _addr : 0;
874882
_stage = ERROR;
875883
}
876884

877-
// we read an entire block
878-
if (!(_addr % _block_size)) {
879-
disk_read(_page, _addr / _block_size, 1);
880-
}
885+
if (n > 0) {
886+
// we read an entire block
887+
if (!(_addr % _block_size)) {
888+
disk_read(_page, _addr / _block_size, 1);
889+
}
881890

882-
// write data which are in RAM
883-
_write_next(&_page[_addr % _block_size], MAX_PACKET);
891+
// write data which are in RAM
892+
_write_next(&_page[_addr % _block_size], MAX_PACKET);
884893

885-
_addr += n;
886-
_length -= n;
894+
_addr += n;
895+
_length -= n;
887896

888-
_csw.DataResidue -= n;
897+
_csw.DataResidue -= n;
898+
}
889899

890900
if (!_length || (_stage != PROCESS_CBW)) {
891901
_csw.Status = (_stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
@@ -896,30 +906,37 @@ void USBMSD::memoryRead(void)
896906

897907
bool USBMSD::infoTransfer(void)
898908
{
899-
uint32_t n;
909+
uint32_t addr_block;
900910

901911
// Logical Block Address of First Block
902-
n = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
912+
addr_block = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
913+
914+
_addr = addr_block * _block_size;
903915

904-
_addr = n * _block_size;
916+
if ((addr_block >= _block_count) || (_addr >= _memory_size)) {
917+
_csw.Status = CSW_FAILED;
918+
sendCSW();
919+
return false;
920+
}
905921

922+
uint32_t length_blocks = 0;
906923
// Number of Blocks to transfer
907924
switch (_cbw.CB[0]) {
908925
case READ10:
909926
case WRITE10:
910927
case VERIFY10:
911-
n = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
928+
length_blocks = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
912929
break;
913930

914931
case READ12:
915932
case WRITE12:
916-
n = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
933+
length_blocks = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
917934
break;
918935
}
919936

920-
_length = n * _block_size;
937+
_length = length_blocks * _block_size;
921938

922-
if (!_cbw.DataLength) { // host requests no data
939+
if (!_cbw.DataLength || !length_blocks || (length_blocks > _block_count - addr_block) || (_length > _memory_size - _addr)) { // host requests no data or wrong length
923940
_csw.Status = CSW_FAILED;
924941
sendCSW();
925942
return false;

0 commit comments

Comments
 (0)