Skip to content

Module converter utilities misparse ELF files when built for a 64-bit host #585

Description

@fdesbiens

The three module converter utilities in common_modules/module_manager/utilities/ declare the ELF header, program header, section header and symbol table entry structures with unsigned long for fields that are 32 bits wide in ELF32. That is only correct where long is 4 bytes, which is Windows with MSVC. On any LP64 host, including the project's default Linux/GCC toolchain, every one of those fields becomes 8 bytes and the structures no longer match the file format.

Evidence

Compiling the structures as declared:

Build ELF_HEADER ELF_SECTION_HEADER
64 bit, the Linux/GCC default 80 80
32 bit, matching MSVC 52 40
Real ELF32 (Elf32_Ehdr / Elf32_Shdr) 52 40

So a 32 bit build is correct and a 64 bit build is not. The tools read the file with elf_object_read(), which copies raw bytes into these structures, so on a 64 bit host every field after the first two shorts is read from the wrong offset.

Impact

The failure is silent rather than loud. The tools do not validate the ELF magic, so they will read whatever the misaligned offsets happen to contain, and can emit a plausible looking but wrong module binary or C array. Anyone who builds these tools on Linux, which is what AGENTS.md names as the project's default toolchain, gets that behaviour with no warning.

The hardening in #580 does not address this. It makes the tools fail cleanly on a truncated or malformed file, but a correct ELF32 read through mismatched structures is not malformed from the reader's point of view.

Suggested fix

Declare the ELF structures with fixed width types from <stdint.h>: uint32_t for the word fields, uint16_t for the half fields, uint8_t for the identification bytes. That makes the layout correct on any host and removes the dependency on how wide long happens to be.

Worth adding while in there:

  • Validate the ELF identification bytes at the start of the file and reject anything that is not an ELF32 little endian object, so a mismatch is reported instead of silently misparsed.
  • Add a _Static_assert on the structure sizes (52 and 40) so this cannot regress unnoticed.

Notes

Found while working on #571 and #580. Not fixed there because it is a different defect from the leak and the malformed input handling, and it changes the parsing itself rather than the error paths.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions