eos_multicore_start() parses the image header of an AMP slot and then starts the core on it, without ever checking integrity or the signature.
core/multicore.c:64-72 (and the eos_multicore_start_amp() wrapper at :215-237) call eos_image_parse_header() and use hdr.entry_addr. A header parses whenever the magic and sizes are well formed — that is a shape check, not an authentication. Anything that can write the slot chooses entry_addr, and the core executes it.
Every other consumer of a slot in this tree checks both: core/slot_manager.c:62,68, stage1/jump_app.c:47,54, core/recovery.c:324,328, core/fw_update.c:259. This is the only one that does not.
Trigger
An image with load_addr == 0. core/image_verify.c:101 skips its only entry_addr range check in that case, so entry_addr is unvalidated as well as unauthenticated.
Planting such an image in slot A, with one byte of the signed prefix altered:
planted image: parse_header=0 entry_addr=0xdeadbe00
eos_image_verify_signature() on it : -4 (EOS_ERR_SIGNATURE)
the normal boot path refuses it:
eos_slot_is_valid(SLOT_A) : false
the AMP path does not:
eos_multicore_start_amp(core 1, SLOT_A) -> 0
board start_core() called 1 time(s); core 1 started at 0xdeadbe00
Scope, stated honestly
eos_multicore_start() and eos_multicore_start_amp() are public API (include/eos_multicore.h). In-tree, only tests/unit/test_multicore.c calls them — the shipped stage-1 path is eboot_jump_to_app(), which does its own verification. So this is a bypass for an integrator bringing up an AMP core, not a hole in the stock boot flow. It is filed at this severity because the API is documented as the supported way to boot a secondary core from a slot, and it is the one image consumer that authenticates nothing.
Found while auditing core/ against the other slot consumers; not reported by a tool.
eos_multicore_start()parses the image header of an AMP slot and then starts the core on it, without ever checking integrity or the signature.core/multicore.c:64-72(and theeos_multicore_start_amp()wrapper at:215-237) calleos_image_parse_header()and usehdr.entry_addr. A header parses whenever the magic and sizes are well formed — that is a shape check, not an authentication. Anything that can write the slot choosesentry_addr, and the core executes it.Every other consumer of a slot in this tree checks both:
core/slot_manager.c:62,68,stage1/jump_app.c:47,54,core/recovery.c:324,328,core/fw_update.c:259. This is the only one that does not.Trigger
An image with
load_addr == 0.core/image_verify.c:101skips its onlyentry_addrrange check in that case, soentry_addris unvalidated as well as unauthenticated.Planting such an image in slot A, with one byte of the signed prefix altered:
Scope, stated honestly
eos_multicore_start()andeos_multicore_start_amp()are public API (include/eos_multicore.h). In-tree, onlytests/unit/test_multicore.ccalls them — the shipped stage-1 path iseboot_jump_to_app(), which does its own verification. So this is a bypass for an integrator bringing up an AMP core, not a hole in the stock boot flow. It is filed at this severity because the API is documented as the supported way to boot a secondary core from a slot, and it is the one image consumer that authenticates nothing.Found while auditing
core/against the other slot consumers; not reported by a tool.