ELF loader should validate before load - #687
Conversation
| static int elf_validate_header(const void *elf_info) | ||
| { | ||
| if (elf_is_64(elf_info) == 0) { | ||
| const Elf32_Ehdr *ehdr = elf_info; |
There was a problem hiding this comment.
I think we can ignore the compliance check failures for the camel case ELF header names. They are defined in the ELF spec this way.
| #include <openamp/elf_loader.h> | ||
| #include <openamp/remoteproc.h> | ||
|
|
||
| static int elf_mul_size(size_t a, size_t b, size_t *out) |
There was a problem hiding this comment.
This applies to all the newly defined functions. They need Doxygen comments to describe them.
| return 0; | ||
| } | ||
|
|
||
| static int elf_range_in_chunk(size_t chunk_offset, size_t chunk_len, |
There was a problem hiding this comment.
This function really needs the Doxygen comment to describe its return values. I think it returns zero on success, -RPROC_EINVAL for overflows, and 1 for just wrong values. If this is the case, then why can't it just return -RPROC_EINVAL for all error cases? This would simplify the code flow for users of this function.
| } | ||
| } | ||
|
|
||
| static int elf_validate_header(const void *elf_info) |
There was a problem hiding this comment.
Doxygen comments would be nice.
| shdrs_size); | ||
| if (range_in_chunk < 0) | ||
| return range_in_chunk; | ||
| if (!range_in_chunk) { |
There was a problem hiding this comment.
What happens if elf_range_in_chunk() returns 1? I think that means that the inputs are wrong, but don't overflow.
| shstrtab_size); | ||
| if (range_in_chunk < 0) | ||
| return range_in_chunk; | ||
| if (!range_in_chunk) { |
There was a problem hiding this comment.
Again, what happens if elf_range_in_chunk() returns 1? Some values don't get assigned.
|
Hi @edmooring Addressed in the updated series: For the ELF type-name compliance findings, I left the Agreed that these come from the ELF spec and should not be renamed just to satisfy the camel-case check. For the newly added helper functions, I added Doxygen comments. In particular,
So I also renamed the local variables at the call sites from If it returns |
064b04a to
bbf3dfa
Compare
There was a problem hiding this comment.
minor comments .
@bentheredonethat: Did you try to verify with an IA if some other overflows are detected ?
@arnopo can you please clarify what is meant by this ? i did some impact analysys by passing in overflowing values |
My point behind my question is the validation part. Could you share test you performed. |
|
7/15/2026 OpenAMP System Reference call: |
I initially performed a functional regression test using a valid ELF image loaded by the R5 onto the A53. The image was parsed, loaded, and executed successfully. In addition, I performed negative tests with deliberately malformed ELF images covering the validation paths introduced by this series: @arnopo below are additional tests performed:
with latest tree. and AFAIK the earlier review comments have been addressed |
bbf3dfa to
9413fbd
Compare
arnopo
left a comment
There was a problem hiding this comment.
few proposal, on concern that can be addressed later, else close to be good to me
| memcpy(*img_info, img_data, tmpsize); | ||
| ret = elf_validate_header(*img_info); | ||
| if (ret < 0) | ||
| return ret; |
There was a problem hiding this comment.
img_info is never free, if allocated. But it seems that is it also the case for some other allocations. I'm ok that we address error management later, in such case please create an issue to log the issue.
|
@arnopo Thanks for the review and the proposed helpers. I updated the series accordingly. The changes are split across their original commit boundaries:
I also addressed the img_info cleanup concern directly. elf_load_header() now tracks whether the current invocation allocated img_info. If header validation fails, it frees and nulls only that I tested the updated series with:
All tests and builds passed, and checkpatch reports no errors or warnings. |
9413fbd to
89a9da4
Compare
|
@bentheredonethat : need to address CI build issue |
89a9da4 to
33b4756
Compare
|
8/12/26 System reference call: Ben to rebase to resolve the last remaining CI failure |
33b4756 to
3e0033e
Compare
3e0033e to
73c4330
Compare
Add generic checked addition, subtraction, and multiplication helpers with consistent input validation across builtin and fallback implementations. Add a generic range-containment helper which reports arithmetic overflow separately from non-containment. This lets the ELF loader distinguish malformed ranges from data absent from the current image chunk. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
73c4330 to
f4530ee
Compare
arnopo
left a comment
There was a problem hiding this comment.
LGTM after removing the checkpatch.conf update
| --ignore NEW_TYPEDEFS | ||
| --ignore ARRAY_SIZE No newline at end of file | ||
| --ignore ARRAY_SIZE | ||
| --ignore CAMELCASE |
There was a problem hiding this comment.
I'm not in favor of adding this that will mask cameCase issue for the rest of the code.
Remove this and kust ignore the CI check patch issue for this PR. It is Ok for me to merge with the CI camel case issue reported.
There was a problem hiding this comment.
@arnopo ok pushed with that as only change
Reject malformed ELF headers before using program or section table metadata from the firmware image. Validate the ELF class, ELF header size, program header entry size, section header entry size, and section string-table index. Release an image-info object allocated by this call if validation fails, while leaving caller-owned objects untouched. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Use checked multiplication when computing ELF program and section header table sizes from e_phnum/e_phentsize and e_shnum/e_shentsize. Also replace wrapping offset-plus-length range checks with overflow-safe image chunk validation before allocation and memcpy. Malformed firmware images with impossible table sizes now fail with -RPROC_EINVAL. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Use overflow-safe range validation before copying the ELF section string table from the firmware image. The section string-table offset and size are read from untrusted section headers. Validate that the full table is present in the current image chunk without relying on wrapping offset arithmetic. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Store the loaded section string-table size in the ELF image information for both ELF32 and ELF64 images. Keeping the size alongside the string-table pointer allows later section name lookups to validate sh_name offsets against the actual loaded table bounds. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Make ELF section-name lookup validate sh_name before reading from the loaded section string table. Skip malformed section names whose sh_name offset is outside the table or whose string is not NUL-terminated within the remaining table bytes. Use bounded comparison for valid candidates so .resource_table lookup cannot read past the loaded string table. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Replace the non-seekable loader offset comparison that used offset + len with an overflow-safe equivalent. This preserves existing behavior for normal ranges while avoiding a wraparound case when deciding whether required image data is contiguous with the current chunk. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
f4530ee to
5072f5e
Compare
|
Checkpatch complains about camelcase. Ok to ignore for this PR |
OpenAMP’s ELF loader should reject malformed firmware images before using ELF header metadata to size allocations, copy header tables, or look up section names.
OpenAMP’s remoteproc ELF loader trusts several ELF header and section-header fields while parsing firmware images. These fields control program-header and section-header table sizes, table
offsets, segment copy ranges, and section string-table lookups.
The main issue is in the header-table loading path. The loader computes program and section table sizes from firmware-controlled values such as e_phnum * e_phentsize and e_shnum * e_shentsize.
Those computed sizes are then used for allocation and memcpy(), while later code walks the copied buffers as native Elf32_Phdr, Elf64_Phdr, Elf32_Shdr, or Elf64_Shdr arrays. If the count, entry
size, or offset metadata is malformed, the allocation/copy size can diverge from the way the loader later indexes the table.
The range checks around these copies also rely on offset-plus-length arithmetic. With malformed offsets or sizes, unchecked addition can wrap and make an invalid range appear valid. Similar range
assumptions apply when loading the section string table and when the loader asks the backing image store for the next chunk of firmware data.
Section-name lookup has a separate parser-side read issue. The loader searches for sections such as .resource_table by using each section header’s sh_name as an offset into the loaded section
string table. Because sh_name is firmware-controlled, the loader must not form or compare name_table + sh_name unless the offset is within the loaded string table and the referenced string is NUL-
terminated before the end of that table.
The fix makes the ELF loader fail closed on malformed metadata:
With these changes, valid firmware images continue to load normally, while malformed images with inconsistent table metadata, overflowing ranges, invalid entry sizes, or out-of-bounds section
names are rejected before allocation, copy, or table lookup proceeds.