[PATCH 1/5] elf-parse: avoid an undefined shift when checking the ELF type
From: Leizhen Zhang
Date: Sun Oct 18 2026 - 20:03:21 EST
elf_parse() takes a bitmap of permitted ELF types and tests it with
type = elf_parser.r2(&ehdr->e32.e_type);
if (!((1 << type) & types)) {
e_type is a 16-bit field read straight out of the file, so a type of 32
or more shifts by at least the width of int and the result is undefined;
31 shifts into the sign bit. All three users of the parser -- kallsyms,
sorttable and tracepoint-update -- reach this with e_type unvalidated.
Found by fuzzing the host ELF tools with mutated object files under
ASan/UBSan. Reproducer, on any vmlinux (or any ET_REL object for
tracepoint-update), setting only e_type:
$ python3 -c 'import struct
d = bytearray(open("vmlinux","rb").read())
struct.pack_into("<H", d, 0x10, 40)
open("t.elf","wb").write(bytes(d))'
$ ./kallsyms --sysmap=/dev/null t.elf
scripts/elf-parse.c:94:11: runtime error: shift exponent 40 is too
large for 32-bit type 'int'
#0 in elf_parse scripts/elf-parse.c:94
(host tools built with -fsanitize=address,undefined)
Reject a type that cannot be in the bitmap, and shift an unsigned 1 so
that a type of 31 stays defined. No valid object changes behaviour: every
ET_* value the callers put in the bitmap is far below 32, and a file with
a larger e_type already took the error path -- it just took it through
undefined behaviour.
Fixes: b055f4c431e3 ("sorttable: Move ELF parsing into scripts/elf-parse.[ch]")
Assisted-by: LLM ASan UBSan
Signed-off-by: Leizhen Zhang <lzsx618@xxxxxxxxx>
---
scripts/elf-parse.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/elf-parse.c b/scripts/elf-parse.c
index ce1c2a670244..9e7d1a4f263f 100644
--- a/scripts/elf-parse.c
+++ b/scripts/elf-parse.c
@@ -91,7 +91,8 @@ static int elf_parse(const char *fname, void *addr, uint32_t types)
}
type = elf_parser.r2(&ehdr->e32.e_type);
- if (!((1 << type) & types)) {
+ /* e_type comes from the file and the bitmap only has 32 slots. */
+ if (type >= 32 || !((1U << type) & types)) {
fprintf(stderr, "Invalid ELF type file %s\n", fname);
return -1;
}
--
2.34.1