From 906588ac22375ae9973c23987be3e58a33ee85d0 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 2 Oct 2019 14:11:35 +0000 Subject: [PATCH] [llvm-readelf] - Report a warning when .hash section contains a chain with a cycle. It is possible to craft a .hash section that triggers an infinite loop in llvm-readelf code. This patch fixes the issue and introduces a warning. Differential revision: https://reviews.llvm.org/D68086 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@373476 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/llvm-readobj/elf-hash-symbols.test | 40 +++++++++++++++++++++++++++ tools/llvm-readobj/ELFDumper.cpp | 11 ++++++++ 2 files changed, 51 insertions(+) diff --git a/test/tools/llvm-readobj/elf-hash-symbols.test b/test/tools/llvm-readobj/elf-hash-symbols.test index b0140a2e9c1..4ffecf9fcc6 100644 --- a/test/tools/llvm-readobj/elf-hash-symbols.test +++ b/test/tools/llvm-readobj/elf-hash-symbols.test @@ -361,3 +361,43 @@ ProgramHeaders: PAddr: 0x1000 Sections: - Section: .dynamic + +## Show that we report a warning for a hash table which contains an entry of +## the bucket array pointing to a cycle. + +# RUN: yaml2obj --docnum=6 %s -o %t6.so +# RUN: llvm-readelf --hash-symbols %t6.so 2>&1 | FileCheck %s -DFILE=%t6.so --check-prefix=BROKEN + +# BROKEN: Symbol table of .hash for image: +# BROKEN-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name +# BROKEN-NEXT: 1 0: 00000000 0 NOTYPE LOCAL DEFAULT UND aaa +# BROKEN: warning: '[[FILE]]': .hash section is invalid: bucket 1: a cycle was detected in the linked chain + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .hash + Type: SHT_HASH + Link: .dynsym + Bucket: [ 1 ] + Chain: [ 1, 1 ] + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: +## llvm-readelf will read the hash table from the file offset +## p_offset + (p_vaddr - DT_HASH) = p_offset + (0 - 0) = p_offset, +## which is the start of PT_LOAD, i.e. the file offset of .hash. + - Tag: DT_HASH + Value: 0x0 +DynamicSymbols: + - Name: aaa + - Name: bbb +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .hash + - Section: .dynamic diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index af3d0e967d1..1b3e8f4851d 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -3437,10 +3437,21 @@ template void GNUStyle::printHashSymbols(const ELFO *Obj) { for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) { if (Buckets[Buc] == ELF::STN_UNDEF) continue; + std::vector Visited(SysVHash->nchain); for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) { if (Ch == ELF::STN_UNDEF) break; + + if (Visited[Ch]) { + reportWarning( + createError(".hash section is invalid: bucket " + Twine(Ch) + + ": a cycle was detected in the linked chain"), + this->FileName); + break; + } + printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); + Visited[Ch] = true; } } } -- 2.11.4.GIT