The boot_os[] table in bootm_os.c is a sparse array whose compile-time size is set by its largest designated initializer (IH_OS_ELF), giving it IH_OS_ELF + 1 entries. The accessor bootm_os_get_boot_func() returns boot_os[os] without any bound check, even though the caller in bootm_run_states() passes images->os.os straight through. That field is populated by image_get_os() from the raw 8-bit ih_os byte of a legacy uImage, and by fit_image_get_os() for a FIT, neither of which clamps the value against the table size.
An attacker-supplied image whose OS field falls outside the populated range therefore drives an out-of-bounds read of boot_os[]. The caller only rejects a NULL return, so a non-NULL adjacent global is accepted as a valid handler and invoked through the indirect call in boot_selected_os(), turning an unsigned image with a malformed header into a jump through an attacker-influenced function pointer. FIT signature verification covers the os property and mitigates this path for signed images, but legacy bootm and unsigned FIT do not. Reject out-of-range indices in bootm_os_get_boot_func() so the existing NULL handling in bootm_run_states() reports an unsupported OS and declines to boot the image. Signed-off-by: Aristo Chen <[email protected]> --- boot/bootm_os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/bootm_os.c b/boot/bootm_os.c index ae20b555f5c..69aa577a2fc 100644 --- a/boot/bootm_os.c +++ b/boot/bootm_os.c @@ -599,5 +599,7 @@ int boot_selected_os(int state, struct bootm_info *bmi, boot_os_fn *boot_fn) boot_os_fn *bootm_os_get_boot_func(int os) { + if (os < 0 || os >= ARRAY_SIZE(boot_os)) + return NULL; return boot_os[os]; } -- 2.43.0

