Skip to content

BTF string offset boundary check can panic parser on malformed ELF/BTF input #2019

Description

@thesmartshadow

Describe the bug

github.com/cilium/ebpf can panic while parsing malformed BTF / BTF.ext metadata through public parser APIs such as LoadCollectionSpec and LoadCollectionSpecFromReader.

The issue is in shared BTF string-table lookup logic. A malformed .BTF or .BTF.ext record can set a non-zero string offset equal to BTF StringLen. This boundary value is incorrectly treated as valid, even though it points to the end of the string table. The parser then searches for a NUL byte in an empty slice, receives -1, and reaches an invalid slice bound, causing a Go panic instead of returning a parse error.

Expected behavior:

Malformed BTF / BTF.ext input should return an error.

Actual behavior:

The parser panics. In a process that parses less-trusted eBPF ELF/BTF artifacts, this can cause process-level denial of service.

I validated the same boundary issue through multiple fields:

  • .BTF btf_type.NameOff
  • .BTF.ext func_info SecNameOff
  • .BTF.ext line_info SecNameOff
  • .BTF.ext line_info FileNameOff
  • .BTF.ext line_info LineOff

The demonstrated impact is denial of service only.

How to reproduce

I prepared a compact reproduction package with PoC source, commands, observed results, and evidence mapping:

https://gist.github.com/thesmartshadow/256bff0f8042c584f993ace89074a815

From the root of a github.com/cilium/ebpf checkout:

chmod +x ghsa-btf-string-offset-gist/reproduce.sh
./ghsa-btf-string-offset-gist/reproduce.sh

Manual steps:

go run ghsa-btf-string-offset-gist/mutate_elf.go \
  -in cmd/bpf2go/testdata/minimal-el.elf \
  -out /tmp/cilium-ebpf-btf-nameoff-eq-stringlen.elf

go run ghsa-btf-string-offset-gist/worker_dos_poc.go \
  -input cmd/bpf2go/testdata/minimal-el.elf

go run ghsa-btf-string-offset-gist/variants_check.go \
  cmd/bpf2go/testdata/minimal-el.elf

Observed behavior:

  • the unmodified ELF fixture parses successfully
  • the mutated ELF differs by one 32-bit BTF string offset field
  • the malformed input causes a panic instead of a returned error
  • the worker PoC exits after parsing the malformed artifact
  • a follow-up benign artifact cannot be processed because the worker process is already gone

Key observed output includes:

control: one-shot scanner on benign input
exit_code: 0
stdout:
  ACCEPT 01-benign.elf

control: one-shot scanner on malformed ELF should reject, but currently panics
exit_code: 2
stderr:
  panic: runtime error: slice bounds out of range [376:375]

impact: long-running artifact scanner worker
worker_response: ACCEPT 01-benign.elf
worker_exit_code_after_malicious: 2
follow_up_write_error: write |1: file already closed
worker_process_state_exited: true

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions