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
Describe the bug
github.com/cilium/ebpfcan panic while parsing malformed BTF / BTF.ext metadata through public parser APIs such asLoadCollectionSpecandLoadCollectionSpecFromReader.The issue is in shared BTF string-table lookup logic. A malformed
.BTFor.BTF.extrecord can set a non-zero string offset equal toBTF 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:
.BTFbtf_type.NameOff.BTF.extfunc_infoSecNameOff.BTF.extline_infoSecNameOff.BTF.extline_infoFileNameOff.BTF.extline_infoLineOffThe 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/ebpfcheckout:Manual steps:
Observed behavior:
Key observed output includes: