brintos

brintos / llvm-project public Read only

0
0

WasmObjectFile::parseRelocSection: SIGSEGV (unchecked Symbols[Reloc.Index]) on an out-of-range reloc index #4

Open sasha opened this issue · 1 comment
S sasha commented

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.)

S sasha commented

Resolving the back-reference in the body: the brintos/linux capget/capset alias issue that produces the invalid 0xFFFFFFFF relocation this crashes on → https://brintos.io/brintos/linux/issues/10