Summary
llvm::object::WasmObjectFile::parseRelocSection segfaults on a relocation
whose symbol index is out of range: the badReloc error path dereferences
Symbols[Reloc.Index] with no bounds check. Every llvm::object-based tool
(llvm-objcopy, llvm-readobj, llvm-objdump, llvm-nm) and wasm-ld
crash instead of emitting the intended "invalid function relocation" diagnostic.
Toolchain: brintos/llvm-project @ 8c4f4586e (clang 22.0.0git).
Where
llvm/lib/Object/WasmObjectFile.cpp, parseRelocSection():
auto badReloc = [&](StringRef msg) {
return make_error<GenericBinaryError>(
msg + ": " + Twine(Symbols[Reloc.Index].Info.Name), // OOB if Reloc.Index >= Symbols.size()
object_error::parse_failed);
};
For a function/table-index reloc, isValidFunctionSymbol(Reloc.Index) is
Index < Symbols.size() && ...; when Index >= Symbols.size() it returns
false, badReloc(...) runs, and Symbols[Reloc.Index] reads far out of bounds
(observed index 0xFFFFFFFF) -> SIGSEGV.
Reproduce
Preserved object on the shared builder host:
build@sergmir.emcraft.com:/work/yocto/brintos-81-repro/vmlinux.o.capget-crash
(a wasm32 kernel vmlinux.o carrying 4 reloc.CODE entries at symbol index
0xFFFFFFFF):
llvm-objcopy -j .modinfo -O binary vmlinux.o.capget-crash /tmp/x # SIGSEGV
llvm-readobj --file-headers vmlinux.o.capget-crash # SIGSEGV
wasm-ld vmlinux.o.capget-crash -o /tmp/x -r --allow-undefined # SIGSEGV
A clean counterpart parses fine 50/50: .../vmlinux.o.ni-clean.
Backtrace: parseRelocSection +541 -> parseCustomSection -> parseSection
-> WasmObjectFile ctor -> createWasmObjectFile.
Fix (robustness)
Bounds-check before building the message:
auto badReloc = [&](StringRef msg) {
StringRef n = Reloc.Index < Symbols.size()
? Symbols[Reloc.Index].Info.Name : "<invalid symbol index>";
return make_error<GenericBinaryError>(msg + ": " + Twine(n),
object_error::parse_failed);
};
Then an invalid reloc is a clean parse error, not a crash. (The invalid reloc
is produced by a separate kernel-side bug — see the brintos/linux
capget/capset alias issue.)