From de03104e5bcc3454ddd784d32ba1e6bb250aa87d Mon Sep 17 00:00:00 2001 From: David Brown Date: Fri, 24 Jul 2026 15:34:19 -0600 Subject: [PATCH] boot: cypress: bound flash access by area size flash_area_read(), flash_area_write() and flash_area_erase() checked the requested offset against fa_off, the partition's absolute base address, instead of fa_size, its length. As off is relative to the start of the area while fa_off is a large device address, the check accepts offsets far past the end of the partition and rejects only absurdly large ones, so an out-of-range access is turned into an absolute address and followed. The checks were also assert()s, which compile out entirely under NDEBUG. Replace them with an unconditional range check against fa_size, ordered so that the arithmetic cannot wrap, returning -1 like the other error paths of these functions. The row alignment asserts express a separate caller contract and are left as they are. Assisted-by: Claude:opus-5 Signed-off-by: David Brown --- boot/cypress/cy_flash_pal/cy_flash_map.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/boot/cypress/cy_flash_pal/cy_flash_map.c b/boot/cypress/cy_flash_pal/cy_flash_map.c index af52bab9c2..25fe7def35 100644 --- a/boot/cypress/cy_flash_pal/cy_flash_map.c +++ b/boot/cypress/cy_flash_pal/cy_flash_map.c @@ -228,9 +228,10 @@ int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst, int rc = 0; size_t addr; - /* check if requested offset not less then flash area (fa) start */ - assert(off < fa->fa_off); - assert(off + len < fa->fa_off); + /* check that the requested range lies inside the flash area (fa) */ + if (off > fa->fa_size || len > fa->fa_size - off) { + return -1; + } /* convert to absolute address inside a device*/ addr = fa->fa_off + off; @@ -268,8 +269,10 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, size_t write_end_addr; const uint32_t * row_ptr = NULL; - assert(off < fa->fa_off); - assert(off + len < fa->fa_off); + /* check that the requested range lies inside the flash area (fa) */ + if (off > fa->fa_size || len > fa->fa_size - off) { + return -1; + } /* convert to absolute address inside a device */ write_start_addr = fa->fa_off + off; @@ -318,8 +321,11 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) size_t erase_start_addr; size_t erase_end_addr; - assert(off < fa->fa_off); - assert(off + len < fa->fa_off); + /* check that the requested range lies inside the flash area (fa) */ + if (off > fa->fa_size || len > fa->fa_size - off) { + return -1; + } + assert(!(len % CY_FLASH_SIZEOF_ROW)); /* convert to absolute address inside a device*/