1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[llvm-readobj/elf] - Fix a crash when dumping a dynamic relocation that refer to a symbol past the EOF.

There is a possible scenario when we crash when dumping dynamic relocations.
For that we should have no section headers (to take the number of synamic symbols from)
and a dynamic relocation that refers to a symbol with an index that is too large to be in a file.

The patch fixes it.

Differential revision: https://reviews.llvm.org/D90214
This commit is contained in:
Georgii Rymar 2020-10-27 12:15:09 +03:00
parent 88e6321d6b
commit 74b8b0d6b8
2 changed files with 107 additions and 4 deletions

View File

@ -319,3 +319,97 @@ ProgramHeaders:
- Section: .rela.dyn
- Section: .rel.dyn
- Section: .dynamic
## Check that llvm-readobj/llvm-readelf reports a warning when dumping a relocation
## which refers to a symbol past the end of the file.
# RUN: yaml2obj --docnum=7 %s -o %t7
# RUN: llvm-readobj --dyn-relocations %t7 2>&1 | \
# RUN: FileCheck %s -DFILE=%t7 --check-prefix=PAST-EOF-LLVM
# RUN: llvm-readelf --dyn-relocations %t7 2>&1 | \
# RUN: FileCheck %s -DFILE=%t7 --check-prefix=PAST-EOF-GNU
# PAST-EOF-LLVM: Dynamic Relocations {
# PAST-EOF-LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1) is past the end of the string table of size 0x0
# PAST-EOF-LLVM-NEXT: 0x0 R_X86_64_NONE <corrupt> 0x0
# PAST-EOF-LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 2: symbol at 0x330 goes past the end of the file (0x330)
# PAST-EOF-LLVM-NEXT: 0x0 R_X86_64_NONE <corrupt> 0x0
# PAST-EOF-LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 4294967295: symbol at 0x18000002e8 goes past the end of the file (0x330)
# PAST-EOF-LLVM-NEXT: 0x0 R_X86_64_NONE <corrupt> 0x0
# PAST-EOF-LLVM-NEXT: }
# PAST-EOF-GNU: 'RELA' relocation section at offset 0x200 contains 72 bytes:
# PAST-EOF-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
# PAST-EOF-GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: st_name (0x1) is past the end of the string table of size 0x0
# PAST-EOF-GNU-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000000000000 <corrupt> + 0
# PAST-EOF-GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 2: symbol at 0x330 goes past the end of the file (0x330)
# PAST-EOF-GNU-NEXT: 0000000000000000 0000000200000000 R_X86_64_NONE <corrupt> + 0
# PAST-EOF-GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 4294967295: symbol at 0x18000002e8 goes past the end of the file (0x330)
# PAST-EOF-GNU-NEXT: 0000000000000000 ffffffff00000000 R_X86_64_NONE <corrupt> + 0
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynamic
Type: SHT_DYNAMIC
Flags: [ SHF_ALLOC ]
Address: 0x100
Offset: 0x100
Entries:
- Tag: DT_RELA
Value: 0x200
- Tag: DT_SYMTAB
Value: 0x300
- Tag: DT_RELASZ
Value: 0x48
- Tag: DT_RELAENT
Value: 0x18
- Tag: DT_NULL
Value: 0x0
- Name: .rela.dyn
Type: SHT_RELA
Flags: [ SHF_ALLOC ]
Address: 0x200
Offset: 0x200
Relocations:
## This symbol is located right before the EOF, so we can dump it.
- Symbol: 0x1
Type: R_X86_64_NONE
## The next symbol, which goes past the EOF.
- Symbol: 0x2
Type: R_X86_64_NONE
## One more symbol that goes past the EOF
## with the maximal possible index.
- Symbol: 0xFFFFFFFF
Type: R_X86_64_NONE
## Place all implicit sections here to make the .dynsym section to be the
## last in the file. This makes the task of validating offsets a bit easier.
- Name: .dynstr
Type: SHT_STRTAB
- Name: .strtab
Type: SHT_STRTAB
- Name: .shstrtab
Type: SHT_STRTAB
- Name: .dynsym
Type: SHT_DYNSYM
Flags: [ SHF_ALLOC ]
Address: 0x300
Offset: 0x300
DynamicSymbols:
- Name: foo
ProgramHeaders:
- Type: PT_LOAD
Offset: 0x0
Sections:
- Section: .dynamic
- Section: .rela.dyn
- Section: .dynsym
- Type: PT_DYNAMIC
Sections:
- Section: .dynamic
SectionHeaderTable:
NoHeaders: true

View File

@ -4493,7 +4493,8 @@ template <class ELFT>
RelSymbol<ELFT> getSymbolForReloc(const ELFFile<ELFT> &Obj, StringRef FileName,
const ELFDumper<ELFT> &Dumper,
const Relocation<ELFT> &Reloc) {
auto WarnAndReturn = [&](const typename ELFT::Sym *Sym,
using Elf_Sym = typename ELFT::Sym;
auto WarnAndReturn = [&](const Elf_Sym *Sym,
const Twine &Reason) -> RelSymbol<ELFT> {
reportWarning(
createError("unable to get name of the dynamic symbol with index " +
@ -4502,8 +4503,8 @@ RelSymbol<ELFT> getSymbolForReloc(const ELFFile<ELFT> &Obj, StringRef FileName,
return {Sym, "<corrupt>"};
};
ArrayRef<typename ELFT::Sym> Symbols = Dumper.dynamic_symbols();
const typename ELFT::Sym *FirstSym = Symbols.begin();
ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols();
const Elf_Sym *FirstSym = Symbols.begin();
if (!FirstSym)
return WarnAndReturn(nullptr, "no dynamic symbol table found");
@ -4516,7 +4517,15 @@ RelSymbol<ELFT> getSymbolForReloc(const ELFFile<ELFT> &Obj, StringRef FileName,
"index is greater than or equal to the number of dynamic symbols (" +
Twine(Symbols.size()) + ")");
const typename ELFT::Sym *Sym = FirstSym + Reloc.Symbol;
const uint64_t FileSize = Obj.getBufSize();
const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) +
(uint64_t)Reloc.Symbol * sizeof(Elf_Sym);
if (SymOffset + sizeof(Elf_Sym) > FileSize)
return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) +
" goes past the end of the file (0x" +
Twine::utohexstr(FileSize) + ")");
const Elf_Sym *Sym = FirstSym + Reloc.Symbol;
Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable());
if (!ErrOrName)
return WarnAndReturn(Sym, toString(ErrOrName.takeError()));