Skip to content

boot: cypress: bound flash access by area size#2803

Open
d3zd3z wants to merge 1 commit into
mcu-tools:mainfrom
d3zd3z:fix-006
Open

boot: cypress: bound flash access by area size#2803
d3zd3z wants to merge 1 commit into
mcu-tools:mainfrom
d3zd3z:fix-006

Conversation

@d3zd3z

@d3zd3z d3zd3z commented Jul 24, 2026

Copy link
Copy Markdown
Member

The Cypress flash map backend bounds every flash access against the wrong
field of struct flash_area.

flash_area_read(), flash_area_write() and flash_area_erase() all check
the requested offset against fa->fa_off, the partition's absolute base
address, rather than fa->fa_size, its length. Since off is relative to
the start of the area and fa_off is a large device address, the check
accepts offsets well past the end of the partition and rejects only
absurdly large ones. The offset is then converted to fa->fa_off + off and
used, so an out-of-range request is followed instead of refused.

The checks are also assert()s, so they compile out entirely under
NDEBUG.

This matters because the bootutil core does not range-check image offsets
itself; it relies on flash_area_read() returning an error for anything
outside the area, which is what the other backends (Zephyr, mynewt, sim) do.

Replace all three with an unconditional range check against fa_size,
written as

if (off > fa->fa_size || len > fa->fa_size - off) {
    return -1;
}

so the arithmetic cannot wrap (off, len and fa_size are all
uint32_t). -1 is what these functions already return from their
bad-device-id path. The row alignment assert in flash_area_erase()
expresses a separate caller contract and is left alone.

Inspection only: boot/cypress/ is not built by the simulator and has no CI
workflow, so this has not been compiled. A review from someone who can build
MCUBootApp for PSoC6 would be welcome.

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 <david.brown@linaro.org>
@d3zd3z
d3zd3z requested a review from romanjoe as a code owner July 24, 2026 21:41
Copilot AI review requested due to automatic review settings July 24, 2026 21:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@d3zd3z
d3zd3z requested review from de-nordic and nordicjm July 24, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants