Skip to content

RAM Load and Direct XIP firmware downgrade capability #2225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

djr-spectrummfg
Copy link

This PR adds new configuration options MCUBOOT_RAM_LOAD_USE_UPDATE_COUNTER (for use with MCUBOOT_RAM_LOAD) and MCUBOOT_DIRECT_XIP_USE_UPDATE_COUNTER (for use with MCUBOOT_DIRECT_XIP).

By default, in RAM load/direct XIP modes, the slot that will boot is the one having the higher version number. This means it is not possible to downgrade to earlier image versions. By configuring one of the new *_USE_UPDATE_COUNTER options, a counter value in the image trailer will be consulted first to determine which image to boot, falling back to comparing the image version if the trailer is missing or there is a tie.

During firmware update, the application code should read the counter value for the running image, increment it, and store that value in the image trailer of the updated slot. The counter is stored in the 'swap size' field which is not used by the RAM load/direct XIP modes.

…/direct XIP rather than relying on version number comparison

This commit adds new configuration option MCUBOOT_RAM_LOAD_USE_UPDATE_COUNTER (for use with MCUBOOT_RAM_LOAD) and MCUBOOT_DIRECT_XIP_USE_UPDATE_COUNTER (for use with MCUBOOT_DIRECT_XIP).

By default, in RAM load/direct XIP modes, the slot that will boot is the one having the higher version number. This means it is not possible to downgrade to earlier image versions. By configuring one of the new *_USE_UPDATE_COUNTER options, a counter value in the image trailer will be consulted first to determine which image to boot, falling back to comparing the image version if the trailer is missing or there is a tie.

During firmware update, the application code should read the counter value for the running image, increment it, and store that value in the image trailer of the updated slot. The counter is stored in the 'swap size' field which is not used by the RAM load/direct XIP modes.
Copy link
Collaborator

@nordicjm nordicjm left a comment

Choose a reason for hiding this comment

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

I don't see the point in this, the whole point in the version is to boot the newest version. If you want something different, you should utilise the boot hooks to select the image to boot and return the other image as empty. Also this is completely bypassable by any rogue code so your security is nil

@djr-spectrummfg
Copy link
Author

djr-spectrummfg commented Mar 10, 2025

That may be what is appropriate for your use case, but for me it is an absolute requirement that it is possible to downgrade the firmware.

The swap upgrade modes allow downgrades to happen, so this is just an extension of that to RAM load/direct XIP modes.

Security is not "nil", because the image still has to be signed. If downgrade is not desirable in a particular application, then just leave the feature off. If my system is running "rogue code" then it is already compromised at that point.

I would also add that returning one image as empty is not equivalent to this because my implementation allows falling back to the other image if the selected one is not bootable (e.g. signature check fails). This is necessary because when the application installs a new image to the non-running slot, it cannot know whether it will pass the signature check etc. If we only allowed mcuboot to boot from that new image, installing an invalid update file would brick the device.

@de-nordic de-nordic requested a review from d3zd3z April 16, 2025 16:41
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