Skip to content

Commit 3597384

Browse files
dgarskedanielinux
authored andcommitted
Add image bounds checking on ELF parser
1 parent d91555f commit 3597384

File tree

6 files changed

+38
-7
lines changed

6 files changed

+38
-7
lines changed

include/elf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ typedef struct elf64_program_header {
166166
#define GET_E32(name) (is_elf32 ? GET32(e32->name) : GET32(e64->name))
167167

168168
typedef int (*elf_mmu_map_cb)(uint64_t, uint64_t, uint32_t);
169-
int elf_load_image_mmu(uint8_t *image, uintptr_t *pentry, elf_mmu_map_cb mmu_cb);
169+
int elf_load_image_mmu(uint8_t *image, uint32_t image_sz, uintptr_t *pentry,
170+
elf_mmu_map_cb mmu_cb);
170171
int elf_load_image(uint8_t *image, uintptr_t *entry, int is_ext);
171172
int64_t elf_hdr_pht_combined_size(const unsigned char* ehdr);
172173
int elf_open(const unsigned char *ehdr, int *is_elf32);

src/boot_x86_fsp_payload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void do_boot(const uint32_t *app)
119119
/* TODO: to remove */
120120
mptable_setup();
121121
x86_paging_dump_info();
122-
r = elf_load_image_mmu((uint8_t *)app, &e, mmu_cb);
122+
r = elf_load_image_mmu((uint8_t *)app, WOLFBOOT_PARTITION_SIZE, &e, mmu_cb);
123123
wolfBoot_printf("Elf loaded (ret %d), entry 0x%x_%x\r\n", r,
124124
(uint32_t)(e >> 32),
125125
(uint32_t)(e));

src/elf.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,25 @@ static int check_scatter_format(const unsigned char* ehdr, int is_elf32);
5858
/* Loader for elf32 or elf64 format program headers
5959
* Returns the entry point function
6060
*/
61-
int elf_load_image_mmu(uint8_t *image, uintptr_t *pentry, elf_mmu_map_cb mmu_cb)
61+
int elf_load_image_mmu(uint8_t *image, uint32_t image_sz, uintptr_t *pentry,
62+
elf_mmu_map_cb mmu_cb)
6263
{
6364
elf32_header* h32 = (elf32_header*)image;
6465
elf64_header* h64 = (elf64_header*)image;
6566
uint16_t entry_count, entry_size;
6667
uint8_t *entry_off;
68+
uint32_t ph_offset;
6769
int is_elf32, is_le, i;
6870

6971
#ifdef DEBUG_ELF
7072
wolfBoot_printf("Loading elf at %p\r\n", (void*)image);
7173
#endif
7274

75+
/* Verify image is large enough for the smallest ELF header */
76+
if (image_sz < sizeof(elf32_header)) {
77+
return -1; /* image too small */
78+
}
79+
7380
/* Verify ELF header */
7481
if (memcmp(h32->ident, ELF_IDENT_STR, 4) != 0) {
7582
return -1; /* not valid header identifier */
@@ -80,6 +87,11 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *pentry, elf_mmu_map_cb mmu_cb)
8087
is_le = (h32->ident[5] == ELF_ENDIAN_LITTLE);
8188
(void)is_le;
8289

90+
/* Verify image is large enough for the actual ELF header type */
91+
if (!is_elf32 && image_sz < sizeof(elf64_header)) {
92+
return -1; /* image too small for elf64 header */
93+
}
94+
8395
/* Verify this is an executable */
8496
if (GET_H16(type) != ELF_HET_EXEC) {
8597
return -2; /* not executable */
@@ -94,9 +106,19 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *pentry, elf_mmu_map_cb mmu_cb)
94106
*pentry = GET_H64(entry);
95107

96108
/* programs */
97-
entry_off = image + GET_H32(ph_offset);
109+
ph_offset = GET_H32(ph_offset);
98110
entry_size = GET_H16(ph_entry_size);
99111
entry_count = GET_H16(ph_entry_count);
112+
113+
/* Validate program header table is within image bounds */
114+
if (ph_offset >= image_sz ||
115+
entry_size == 0 ||
116+
entry_count > (image_sz / entry_size) ||
117+
ph_offset + ((uint32_t)entry_count * entry_size) > image_sz) {
118+
return -3; /* program header table out of bounds */
119+
}
120+
entry_off = image + ph_offset;
121+
100122
#ifdef DEBUG_ELF
101123
wolfBoot_printf("Program Headers %d (size %d)\r\n", entry_count, entry_size);
102124
#endif
@@ -115,6 +137,12 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *pentry, elf_mmu_map_cb mmu_cb)
115137
continue;
116138
}
117139

140+
/* Validate segment data is within image bounds */
141+
if (file_size > 0 &&
142+
(offset >= image_sz || file_size > image_sz - offset)) {
143+
return -4; /* segment offset/size out of bounds */
144+
}
145+
118146
#ifdef DEBUG_ELF
119147
if (file_size > 0) {
120148
wolfBoot_printf(

src/update_disk.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,8 @@ void RAMFUNCTION wolfBoot_start(void)
487487
#if defined(WOLFBOOT_ELF) && !defined(WOLFBOOT_FSP)
488488
/* Load elf sections and return the new entry point */
489489
/* Skip for FSP, since it expects ELF image directly */
490-
if (elf_load_image_mmu((uint8_t*)load_address, (uintptr_t*)&load_address, NULL) != 0){
490+
if (elf_load_image_mmu((uint8_t*)load_address, os_image.fw_size,
491+
(uintptr_t*)&load_address, NULL) != 0){
491492
wolfBoot_printf("Invalid elf, falling back to raw binary\n");
492493
}
493494
#endif

src/update_ram.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ void RAMFUNCTION wolfBoot_start(void)
298298

299299
#ifdef WOLFBOOT_ELF
300300
/* Load elf */
301-
if (elf_load_image_mmu((uint8_t*)load_address, (uintptr_t*)&load_address, NULL) != 0){
301+
if (elf_load_image_mmu((uint8_t*)load_address, os_image.fw_size,
302+
(uintptr_t*)&load_address, NULL) != 0){
302303
wolfBoot_printf("Invalid elf, falling back to raw binary\n");
303304
}
304305
#endif

tools/elf-parser/elf-parser.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
7070
fclose(f);
7171

7272
if (ret == 0) {
73-
ret = elf_load_image_mmu(image, &entry, NULL);
73+
ret = elf_load_image_mmu(image, (uint32_t)imageSz, &entry, NULL);
7474
}
7575

7676
printf("Return %d, Load %p\n", ret, (void*)entry);

0 commit comments

Comments
 (0)