update USBMSD::infoTransfer implementation

Fix protects underlaying block device from out-of-bound read/writes
 - prevents the host from setting block device addres larger then block device size
 - prevents the host from setting wrong read/write lenght
pull/12693/head
Maciej Bocianski 2020-03-12 10:43:49 +01:00
parent da9f85b6af
commit ac105f5a18
1 changed files with 14 additions and 7 deletions

View File

@ -903,30 +903,37 @@ void USBMSD::memoryRead(void)
bool USBMSD::infoTransfer(void)
{
uint32_t n;
uint32_t addr_block;
// Logical Block Address of First Block
n = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
addr_block = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0);
_addr = n * _block_size;
_addr = addr_block * _block_size;
if ((addr_block >= _block_count) || (_addr >= _memory_size)) {
_csw.Status = CSW_FAILED;
sendCSW();
return false;
}
uint32_t length_blocks = 0;
// Number of Blocks to transfer
switch (_cbw.CB[0]) {
case READ10:
case WRITE10:
case VERIFY10:
n = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
length_blocks = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0);
break;
case READ12:
case WRITE12:
n = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
length_blocks = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0);
break;
}
_length = n * _block_size;
_length = length_blocks * _block_size;
if (!_cbw.DataLength) { // host requests no data
if (!_cbw.DataLength || !length_blocks || (length_blocks > _block_count - addr_block) || (_length > _memory_size - _addr)) { // host requests no data or wrong length
_csw.Status = CSW_FAILED;
sendCSW();
return false;