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);
     }