You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2026/10/27 09:33:27 UTC
(mynewt-core) 01/08: hw/usb/tinyusb/msc_flash: Check LBA range in READ10 and WRITE10
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit d5746e99b239619bf734edc3ed063e200a207fff
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 22:33:42 2026 +0100
hw/usb/tinyusb/msc_flash: Check LBA range in READ10 and WRITE10
LBA received from USB host was not checked against the number of
blocks exported by LUN, and was used to compute flash address with
32-bit arithmetic. With MSC_FLASH_FLASH_ID and non-zero
MSC_FLASH_FLASH_OFFSET this allowed the host to read, erase and write
any part of the flash, including bootloader and images, and not only
the exported part.
Reject accesses that are not fully contained within the exported
blocks. Offset within block is now also taken into account for reads.
Assisted-by: Claude:claude-opus-5-5
---
hw/usb/tinyusb/msc_flash/src/msc_flash.c | 37 ++++++++++++++++++++++++++++++--
1 file changed, 35 insertions(+), 2 deletions(-)
diff --git a/hw/usb/tinyusb/msc_flash/src/msc_flash.c b/hw/usb/tinyusb/msc_flash/src/msc_flash.c
index 357b98b8c..77c1b1aee 100644
--- a/hw/usb/tinyusb/msc_flash/src/msc_flash.c
+++ b/hw/usb/tinyusb/msc_flash/src/msc_flash.c
@@ -122,6 +122,33 @@ get_lun_data(uint8_t lun)
return IN_ARRAY(luns, lun) ? luns + lun : NULL;
}
+/*
+ * Converts LBA and offset to flash address. Returns false if access of size
+ * bytes is not fully contained within flash exported by LUN.
+ */
+static bool
+lba_to_flash_addr(struct lun_data *lun_data, uint32_t lba, uint32_t offset,
+ uint32_t size, uint32_t *addr)
+{
+ uint64_t start;
+ uint64_t end;
+
+ if (lba < MYNEWT_VAL_MSC_FLASH_MBR || lba >= lun_data->block_count) {
+ return false;
+ }
+
+ start = (uint64_t)(lba - MYNEWT_VAL_MSC_FLASH_MBR) * lun_data->block_size + offset;
+ end = (uint64_t)(lun_data->block_count - MYNEWT_VAL_MSC_FLASH_MBR) *
+ lun_data->block_size;
+ if (start + size > end) {
+ return false;
+ }
+
+ *addr = start;
+
+ return true;
+}
+
/*
* Invoked when received SCSI_CMD_INQUIRY
* Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
@@ -209,6 +236,7 @@ tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer,
uint32_t bufsize)
{
struct lun_data *lun_data = get_lun_data(lun);
+ uint32_t flash_addr;
MSC_FLASH_LOG_DEBUG("read10(%d, %d, buf, %d)", lba, offset, bufsize);
@@ -226,7 +254,10 @@ tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer,
buf[510] = 0x55;
buf[511] = 0xAA;
} else {
- flash_read(lun_data, (lba - MYNEWT_VAL_MSC_FLASH_MBR) * 512, buffer, bufsize);
+ if (!lba_to_flash_addr(lun_data, lba, offset, bufsize, &flash_addr)) {
+ return -1;
+ }
+ flash_read(lun_data, flash_addr, buffer, bufsize);
}
return bufsize;
@@ -252,7 +283,9 @@ tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer,
}
if (lba >= MYNEWT_VAL_MSC_FLASH_MBR) {
- flash_addr = (lba - MYNEWT_VAL_MSC_FLASH_MBR) * 512;
+ if (!lba_to_flash_addr(lun_data, lba, offset, bufsize, &flash_addr)) {
+ return -1;
+ }
flash_erase_if_needed(lun_data, flash_addr, bufsize);
flash_write(lun_data, flash_addr, buffer, bufsize);
}