Skip to content

Improve resilience of ELF parser to malformed input#2026

Merged
dylandreimerink merged 5 commits into
mainfrom
feature/handle-elf-malformed-input
May 29, 2026
Merged

Improve resilience of ELF parser to malformed input#2026
dylandreimerink merged 5 commits into
mainfrom
feature/handle-elf-malformed-input

Conversation

@dylandreimerink

Copy link
Copy Markdown
Member

Inspired by #2024 I decided to run our existing FuzzLoadCollectionSpec fuzz test until it didn't return panics for an hour.

This surfaced quite a number of places where "user input" in the form of an ELF file would cause a panic. These were out of bounds reads from slices, nil pointer dereferenceing, and out of memory exceptions. The out of bounds reads were often caused by integer overflows in bounds checks.

All in all, this should make the library panic less often and throw normal errors instead when faced with bad or unexpected input.

Struct_ops programs need BTF, but when an ELF is presented without BTF,
the struct ops reloc logic would panic. Adding a nil check and throwing
a clear error when BTF is missing when its required.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
When ELF sections are compressed the debug/elf package does not populate
the `ReaderAt` field of the `elf.Section` struct. When we do not check
for its presence, we end up with a nil pointer dereference when trying
to read the section data.

So check for the presence of the `ReaderAt` field and return an error if
it is nil. We do not support compressed ELF sections.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
@dylandreimerink dylandreimerink requested a review from a team as a code owner May 29, 2026 14:33
@dylandreimerink dylandreimerink requested a review from Copilot May 29, 2026 14:33
@dylandreimerink dylandreimerink force-pushed the feature/handle-elf-malformed-input branch from ec0877b to 6a9069c Compare May 29, 2026 14:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens ELF/BTF parsing against malformed inputs by replacing panic-prone reads and arithmetic with validation errors.

Changes:

  • Adds bounds checks for symbol offsets/sizes and compressed sections in ELF loading paths.
  • Adds missing guards for BTF-dependent struct ops and zero section alignment.
  • Changes line-info parsing to avoid a single large allocation from untrusted record counts.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
elf_reader.go Adds validation around ELF sections, symbols, BTF map values, data variables, and struct ops metadata.
btf/ext_info.go Parses line-info records in bounded chunks instead of allocating the full record slice upfront.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread btf/ext_info.go
Part of the .BTF.ext header contains the number of line info records.
We were blindly taking this number and allocating x mount of records in
go. If this number is malformed it causes an out of memory error.

So instead of pre-allocating memory for all the records, lets do so for
1024 at a time. If we run out of section data, we stop and return an
error, going from an OOM to a more reasonable error.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
Fuzzing the ELF reader revealed that it can be made to read out of
bounds data if a symbol's size extends beyond the end of its section.
Adding a bounds check to throw a proper error instead of panicking.

Limit symbol values and sizes to 32 bits to prevent 64 bit integer
overflow. This limits the maximum size of a symbol to 4GB, which is more
than enough.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
A final round of fuzzing surfaced 3 more edge cases. First is an
integer overflow, handled by limiting both integers to 32 bit so they
do not overflow a 64 bit integer when compared.

Second is a division by zero, handled by checking if the divisor is zero
before performing the division.

Third is a compressed section, which is not supported.

After these the fuzzer surfaced nothing within an hour of fuzzing, so I
consider this good enough for now.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
@dylandreimerink dylandreimerink force-pushed the feature/handle-elf-malformed-input branch from 6a9069c to 3b62881 Compare May 29, 2026 14:39
@dylandreimerink dylandreimerink merged commit 765fc1d into main May 29, 2026
21 checks passed
@dylandreimerink dylandreimerink deleted the feature/handle-elf-malformed-input branch May 29, 2026 14:42
@ti-mo

ti-mo commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Great, thanks. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants