All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] elf-parse: validate what the host ELF tools read from the file
@ 2026-10-19  0:02 Leizhen Zhang
  2026-10-19  0:02 ` [PATCH 1/5] elf-parse: avoid an undefined shift when checking the ELF type Leizhen Zhang
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Leizhen Zhang @ 2026-10-19  0:02 UTC (permalink / raw)
  To: nathan, nsc; +Cc: linux-kbuild, linux-kernel, rostedt, ljs, Leizhen Zhang

scripts/elf-parse.c takes the section header table, the section indices and
the symbol table straight out of the file it maps, without checking any of
them against the mapping. All three users -- kallsyms, sorttable and
tracepoint-update -- then index with those values, so a truncated or
corrupted object file makes the tools read outside the mapping, allocate
from a file-supplied count, or divide by zero instead of printing an error.

These are build-time tools fed by the local toolchain, so under
Documentation/process/threat-model.rst this looks like a robustness problem
rather than a vulnerability: reaching it takes a corrupt or hostile object
in the build tree. I am leaving that classification for you to review.

How this was found: the three tools were built with
-fsanitize=address,undefined and driven by a mutational fuzzer that pokes
ELF structure fields (ELF header, section headers, symbol entries) in
otherwise valid objects. Every crash was then reduced to a reproducer that
changes exactly one field of a valid file, which is what each patch quotes.

  1/5  e_type >= 32 shifts by at least the width of int (UB). Hits all three
       tools, and is in mainline as well as -next.
  2/5  nothing checks that the file is long enough for its ELF header, or
       that e_shoff/e_shnum/e_shstrndx describe a table inside the mapping.
       Also mainline.
  3/5  elf_open_ro() resolves a count and a name index through section 0 and
       a string table through sh_link, all unchecked. -next only.
  4/5  a zero sh_entsize divides by zero, and an sh_size past the end of the
       file yields an unbounded symbol count which the caller allocates.
       -next only.
  5/5  st_name is unbounded, so one symbol can point its name anywhere.
       -next only.

Verification, per patch, on the reproducer it quotes and on a valid vmlinux,
a shared object and a .o: every reproducer now prints one line and exits 1,
and the three tools accept the valid objects unchanged. After the series the
fuzzer no longer reaches any of these paths (3420 kallsyms, 2149 sorttable
and 2594 tracepoint-update iterations). gcc -Wall -Wextra is clean on the
changed files, and checkpatch --strict reports nothing except CamelCase
complaints about the standard ELF type names.

What is NOT fixed, and what I could not do:

 - An unaligned symbol-table sh_offset makes elf_symbol() form a misaligned
   Elf_Sym pointer, which UBSan reports at scripts/elf-parse.h:233. Checking
   alignment here would reject legitimate ELF32 objects, whose symbol tables
   need 4-byte alignment while the Elf_Sym union wants 8, so this wants the
   accessors to read unaligned instead. Patch 4/5 says so in its message.
 - Reading e_shoff itself through get_unaligned_le32() is UB on a byte with
   the top bit set. That is a separate bug in
   tools/include/tools/le_byteshift.h which I have a patch pending for
   ("tools/include: fix signed shift overflow in 32-bit unaligned
   accessors"). Until it lands, the e_shoff reproducer in 2/5 stops at the
   byteshift report first; with it applied the behaviour is as described.
 - sorttable.c and tracepoint-update.c read *section* names the same
   unbounded way through the elf_map() path. Both crash, both have a
   one-field reproducer, and both are sent as separate patches to their own
   maintainers rather than buried in this series.
 - The series is based on next-20261002, the newest linux-next I could fetch
   here. Patches 1 and 2 apply to mainline as well.
 - Per Documentation/process/coding-assistants.rst each patch carries an
   Assisted-by tag recording that an LLM found and drafted it, along with
   the sanitizers used. The Signed-off-by is mine: I reviewed the analysis
   and the code.

Leizhen Zhang (5):
  elf-parse: avoid an undefined shift when checking the ELF type
  elf-parse: check that the section header table is inside the file
  elf-parse: check the section indices that elf_open_ro() takes from the
    file
  elf-parse: check the symbol table before walking it
  elf-parse: bound symbol names by the string table

 scripts/elf-parse.c       | 125 +++++++++++++++++++++++++++++++++++---
 scripts/elf-parse.h       |  14 +++++
 scripts/kallsyms-sysmap.c |   4 +-
 3 files changed, 133 insertions(+), 10 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-10-20  0:03 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19  0:02 [PATCH 0/5] elf-parse: validate what the host ELF tools read from the file Leizhen Zhang
2026-10-19  0:02 ` [PATCH 1/5] elf-parse: avoid an undefined shift when checking the ELF type Leizhen Zhang
2026-10-19 12:47   ` Steven Rostedt
2026-10-19  0:02 ` [PATCH 2/5] elf-parse: check that the section header table is inside the file Leizhen Zhang
2026-10-19 12:55   ` Steven Rostedt
2026-10-20  0:03   ` sashiko-bot
2026-10-19  0:02 ` [PATCH 3/5] elf-parse: check the section indices that elf_open_ro() takes from " Leizhen Zhang
2026-10-19  0:02 ` [PATCH 4/5] elf-parse: check the symbol table before walking it Leizhen Zhang
2026-10-19  0:02 ` [PATCH 5/5] elf-parse: bound symbol names by the string table Leizhen Zhang
2026-10-20  0:03   ` sashiko-bot
2026-10-19 12:57 ` [PATCH 0/5] elf-parse: validate what the host ELF tools read from the file Steven Rostedt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.