Skip to content

Commit 292a1b9

Browse files
authored
Merge pull request #12693 from maciejbocianski/fix_usb_msd
USBMSD security updates
2 parents 1bbcaec + 1ffb4d7 commit 292a1b9

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
@@ -572,6 +572,14 @@ void USBMSD::_read_next()
572572

573573
void USBMSD::memoryWrite(uint8_t *buf, uint16_t size)
574574
{
575+
// Max sized packets are required to be sent until the transfer is complete
576+
MBED_ASSERT(_block_size % MAX_PACKET == 0);
577+
if ((size != MAX_PACKET) && (size != 0)) {
578+
_stage = ERROR;
579+
endpoint_stall(_bulk_out);
580+
return;
581+
}
582+
575583
if ((_addr + size) > _memory_size) {
576584
size = _memory_size - _addr;
577585
_stage = ERROR;
@@ -876,23 +884,25 @@ void USBMSD::memoryRead(void)
876884

877885
n = (_length > MAX_PACKET) ? MAX_PACKET : _length;
878886

879-
if ((_addr + n) > _memory_size) {
880-
n = _memory_size - _addr;
887+
if (_addr > (_memory_size - n)) {
888+
n = _addr < _memory_size ? _memory_size - _addr : 0;
881889
_stage = ERROR;
882890
}
883891

884-
// we read an entire block
885-
if (!(_addr % _block_size)) {
886-
disk_read(_page, _addr / _block_size, 1);
887-
}
892+
if (n > 0) {
893+
// we read an entire block
894+
if (!(_addr % _block_size)) {
895+
disk_read(_page, _addr / _block_size, 1);
896+
}
888897

889-
// write data which are in RAM
890-
_write_next(&_page[_addr % _block_size], MAX_PACKET);
898+
// write data which are in RAM
899+
_write_next(&_page[_addr % _block_size], MAX_PACKET);
891900

892-
_addr += n;
893-
_length -= n;
901+
_addr += n;
902+
_length -= n;
894903

895-
_csw.DataResidue -= n;
904+
_csw.DataResidue -= n;
905+
}
896906

897907
if (!_length || (_stage != PROCESS_CBW)) {
898908
_csw.Status = (_stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
@@ -903,30 +913,37 @@ void USBMSD::memoryRead(void)
903913

904914
bool USBMSD::infoTransfer(void)
905915
{
906-
uint32_t n;
916+
uint32_t addr_block;
907917

908918
// Logical Block Address of First Block
909-
n = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
919+
addr_block = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
920+
921+
_addr = addr_block * _block_size;
910922

911-
_addr = n * _block_size;
923+
if ((addr_block >= _block_count) || (_addr >= _memory_size)) {
924+
_csw.Status = CSW_FAILED;
925+
sendCSW();
926+
return false;
927+
}
912928

929+
uint32_t length_blocks = 0;
913930
// Number of Blocks to transfer
914931
switch (_cbw.CB[0]) {
915932
case READ10:
916933
case WRITE10:
917934
case VERIFY10:
918-
n = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
935+
length_blocks = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
919936
break;
920937

921938
case READ12:
922939
case WRITE12:
923-
n = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
940+
length_blocks = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
924941
break;
925942
}
926943

927-
_length = n * _block_size;
944+
_length = length_blocks * _block_size;
928945

929-
if (!_cbw.DataLength) { // host requests no data
946+
if (!_cbw.DataLength || !length_blocks || (length_blocks > _block_count - addr_block) || (_length > _memory_size - _addr)) { // host requests no data or wrong length
930947
_csw.Status = CSW_FAILED;
931948
sendCSW();
932949
return false;

0 commit comments

Comments
 (0)