1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[llvm-readelf] - Do not crash when the PT_INTERP has a broken offset.

We do not verify the p_offset of the PT_INTERP header and tool may
crash when a program interpreter name string goes past the end of the file.

Differential revision: https://reviews.llvm.org/D79013
This commit is contained in:
Georgii Rymar 2020-04-28 18:16:00 +03:00
parent 6239837b28
commit e1adf90ced
2 changed files with 80 additions and 6 deletions

View File

@ -1,7 +1,7 @@
## Check how llvm-readelf dumps program headers and prints sections to segments mapping.
## Check that -l, --program-headers and --segments are the same option.
# RUN: yaml2obj -DBITS=32 -DMACHINE=EM_386 %s -o %t32.elf
# RUN: yaml2obj --docnum=1 -DBITS=32 -DMACHINE=EM_386 %s -o %t32.elf
# RUN: llvm-readelf -l %t32.elf 2>&1 > %t.readelf-l.txt
# RUN: llvm-readelf --program-headers %t32.elf 2>&1 > %t.readelf-pheaders.txt
# RUN: cmp %t.readelf-l.txt %t.readelf-pheaders.txt
@ -12,7 +12,7 @@
# RUN: llvm-readelf -l %t32.elf | \
# RUN: FileCheck %s --check-prefixes=ELF32,MAPPING --strict-whitespace --match-full-lines
# RUN: yaml2obj -DBITS=64 -DMACHINE=EM_X86_64 %s -o %t64.elf
# RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_X86_64 %s -o %t64.elf
# RUN: llvm-readelf -l %t64.elf | \
# RUN: FileCheck %s --check-prefixes=ELF64,MAPPING --strict-whitespace --match-full-lines
@ -288,7 +288,7 @@ ProgramHeaders:
- Section: .foo.end
## Check how we dump ARM specific program headers.
# RUN: yaml2obj -DBITS=64 -DMACHINE=EM_ARM %s -o %tarm.elf
# RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_ARM %s -o %tarm.elf
# RUN: llvm-readelf --program-headers %tarm.elf | FileCheck %s --check-prefix=ARM
# ARM: <unknown>: 0x70000000 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
@ -296,10 +296,61 @@ ProgramHeaders:
# ARM-NEXT: <unknown>: 0x70000002 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
## Check how we dump MIPS specific program headers.
# RUN: yaml2obj -DBITS=64 -DMACHINE=EM_MIPS %s -o %tmips.elf
# RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_MIPS %s -o %tmips.elf
# RUN: llvm-readelf --program-headers %tmips.elf | FileCheck %s --check-prefix=MIPS
# MIPS: REGINFO 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
# MIPS-NEXT: RTPROC 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
# MIPS-NEXT: OPTIONS 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
# MIPS-NEXT: ABIFLAGS 0x000548 0x0000000000001000 0x0000000000001000 0x000003 0x000003 0x1
## Check we report a warning when a program interpreter name is non-null-terminated or when
## PT_INTERP has an offset that goes past the end of the file.
# RUN: yaml2obj --docnum=2 %s -o %t.err
## Show the size of the output produced. It is used in the YAML below.
# RUN: wc -c < %t.err | FileCheck %s --check-prefix=SIZE
# SIZE: 560
## Write the additional 'C', '\0, 'C' bytes to the end.
# RUN: echo -n -e "C\x00C" >> %t.err
# RUN: llvm-readelf --program-headers %t.err 2>&1 | \
# RUN: FileCheck %s -DFILE=%t.err --check-prefix=ERROR-INTERP
# ERROR-INTERP: Type Offset
# ERROR-INTERP-NEXT: INTERP 0x000[[#%x,OFFSET:0x230]]
# ERROR-INTERP-NEXT: [Requesting program interpreter: C]
# ERROR-INTERP-NEXT: INTERP 0x000[[#OFFSET + 1]]
# ERROR-INTERP-NEXT: [Requesting program interpreter: ]
# ERROR-INTERP-NEXT: INTERP 0x000[[#OFFSET + 2]]
# ERROR-INTERP-NEXT: warning: '[[FILE]]': unable to read program interpreter name at offset 0x[[#OFFSET+2]]: it is not null-terminated
# ERROR-INTERP-NEXT: INTERP 0x000[[#OFFSET + 3]]
# ERROR-INTERP-NEXT: warning: '[[FILE]]': unable to read program interpreter name at offset 0x[[#OFFSET+3]]: it goes past the end of the file (0x[[#OFFSET + 3]])
# ERROR-INTERP-NEXT: INTERP 0xaabbccddeeff1122
# ERROR-INTERP-NEXT: warning: '[[FILE]]': unable to read program interpreter name at offset 0xaabbccddeeff1122: it goes past the end of the file (0x[[#OFFSET + 3]])
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
ProgramHeaders:
## Case 1: the offset points to the first additional byte.
- Type: PT_INTERP
Offset: 560
## Case 1: the offset points to the second additional byte,
## which is a null byte.
- Type: PT_INTERP
Offset: 561
## Case 3: the offset points to the third additional
## byte, which is the last byte in the file.
- Type: PT_INTERP
Offset: 562
## Case 4: the offset goes 1 byte past the end of the file.
- Type: PT_INTERP
Offset: 563
## Case 5: an arbitrary large offset that goes past the end of the file.
- Type: PT_INTERP
Offset: 0xAABBCCDDEEFF1122

View File

@ -4128,8 +4128,31 @@ void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
for (auto Field : Fields)
printField(Field);
if (Phdr.p_type == ELF::PT_INTERP) {
OS << "\n [Requesting program interpreter: ";
OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]";
OS << "\n";
auto ReportBadInterp = [&](const Twine &Msg) {
reportWarning(
createError("unable to read program interpreter name at offset 0x" +
Twine::utohexstr(Phdr.p_offset) + ": " + Msg),
this->FileName);
};
if (Phdr.p_offset >= Obj->getBufSize()) {
ReportBadInterp("it goes past the end of the file (0x" +
Twine::utohexstr(Obj->getBufSize()) + ")");
continue;
}
const char *Data =
reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset;
size_t MaxSize = Obj->getBufSize() - Phdr.p_offset;
size_t Len = strnlen(Data, MaxSize);
if (Len == MaxSize) {
ReportBadInterp("it is not null-terminated");
continue;
}
OS << " [Requesting program interpreter: ";
OS << StringRef(Data, Len) << "]";
}
OS << "\n";
}