diff options
| author | seteiro <[email protected]> | 2026-11-12 00:48:23 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-11-13 09:38:24 +0800 |
| commit | 4014174e525b200e8c64b48deb2af83b955233a2 (patch) | |
| tree | 84d8a7ab27c5f2b9623ca11f6f85914c678a3612 /components | |
| parent | e69e6620322f3394f7da5c56ebfcfed408669efb (diff) | |
[drivers][mtd] fix CFI sector table off-by-one bound
Complete the CFI erase-region and sector-table bounds hardening after #11558:
- When sect_count >= RT_ARRAY_SIZE(fdev->sect), log the actual >= limit
using %lu and fail probe with -RT_EINVAL via goto _fail instead of only
breaking the inner erase-region loop and registering a truncated flash.
- Reject zero sector counts, invalid size_ratio/dev_size shifts, and
ioremap failures during probe, guard cfi_flash_find() against
sect_count == 0 underflow, and clear fdev->sect[0] after rt_iounmap()
in _fail to avoid double-unmap from cfi_flash_probe().
Fixes #11272
Diffstat (limited to 'components')
| -rw-r--r-- | components/drivers/mtd/mtd-cfi.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/components/drivers/mtd/mtd-cfi.c b/components/drivers/mtd/mtd-cfi.c index 3f00b110ca..6b598a5d0c 100644 --- a/components/drivers/mtd/mtd-cfi.c +++ b/components/drivers/mtd/mtd-cfi.c @@ -210,6 +210,11 @@ static rt_off_t cfi_flash_find(struct cfi_flash_device *fdev, rt_ubase_t addr) { rt_off_t sect = 0; + if (fdev->sect_count == 0) + { + return 0; + } + while (sect < fdev->sect_count - 1 && fdev->sect[sect] < addr) { sect++; @@ -1056,6 +1061,11 @@ static rt_err_t cfi_flash_dev_probe(struct rt_device *dev, struct cfi_flash_devi } fdev->sect[0] = (rt_ubase_t)rt_ioremap((void *)addr, size); + if (!fdev->sect[0]) + { + err = -RT_EIO; + goto _fail; + } if (!cfi_flash_detect(fdev, query)) { @@ -1130,9 +1140,20 @@ static rt_err_t cfi_flash_dev_probe(struct rt_device *dev, struct cfi_flash_devi size_ratio >>= 1; } - fdev->size = 1 << query->dev_size; + if (size_ratio <= 0 || query->dev_size >= sizeof(fdev->size) * 8) + { + err = -RT_EINVAL; + goto _fail; + } + + fdev->size = (rt_size_t)1 << query->dev_size; + if (fdev->size > RT_SIZE_MAX / (rt_size_t)size_ratio) + { + err = -RT_EINVAL; + goto _fail; + } /* Multiply the size by the number of chips */ - fdev->size *= size_ratio; + fdev->size *= (rt_size_t)size_ratio; max_size = size; if (max_size && fdev->size > max_size) @@ -1160,9 +1181,11 @@ static rt_err_t cfi_flash_dev_probe(struct rt_device *dev, struct cfi_flash_devi if (sect_count >= RT_ARRAY_SIZE(fdev->sect)) { - LOG_E("Too many %d (> %d) sector found", - sect_count, RT_ARRAY_SIZE(fdev->sect)); - break; + LOG_E("Too many %lu (>= %lu) sectors found", + (unsigned long)sect_count, + (unsigned long)RT_ARRAY_SIZE(fdev->sect)); + err = -RT_EINVAL; + goto _fail; } fdev->sect[sect_count] = sect; @@ -1196,6 +1219,13 @@ static rt_err_t cfi_flash_dev_probe(struct rt_device *dev, struct cfi_flash_devi fdev->sect_count = sect_count; } + if (fdev->sect_count == 0) + { + LOG_E("No sector found"); + err = -RT_EINVAL; + goto _fail; + } + if (fdev->interface == FLASH_CFI_X8X16 && fdev->chipwidth == FLASH_CFI_BY8) { /* Need to test on x8/x16 in parallel. */ @@ -1241,6 +1271,7 @@ _fail: if (fdev->sect[0]) { rt_iounmap((void *)fdev->sect[0]); + fdev->sect[0] = 0; } rt_free(query); |
