[llvm] [llvm-objdump][ELF] Ensure offset to verdaux entry array does not go past size (PR #115284)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 7 01:36:00 PST 2024
https://github.com/antoniofrighetto created https://github.com/llvm/llvm-project/pull/115284
Validate `vd_aux` while parsing `Elf_Verdef` structure.
Fixes: https://github.com/llvm/llvm-project/issues/86611.
>From f87571ae4f7284a88756723844b14934d4812f4f Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 7 Nov 2024 10:26:39 +0100
Subject: [PATCH 1/2] [ObjectYAML][ELF] Allow verdaux entry offset to be
user-defined
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 1 +
llvm/lib/ObjectYAML/ELFEmitter.cpp | 12 ++++++------
llvm/lib/ObjectYAML/ELFYAML.cpp | 1 +
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 8f045d6383623b..5383037582124c 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -582,6 +582,7 @@ struct VerdefEntry {
std::optional<uint16_t> Flags;
std::optional<uint16_t> VersionNdx;
std::optional<uint32_t> Hash;
+ std::optional<uint16_t> AuxVOffset;
std::vector<StringRef> VerNames;
};
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index fc234581a45a70..a379a3e0d4a596 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1655,7 +1655,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
VerDef.vd_flags = E.Flags.value_or(0);
VerDef.vd_ndx = E.VersionNdx.value_or(0);
VerDef.vd_hash = E.Hash.value_or(0);
- VerDef.vd_aux = sizeof(Elf_Verdef);
+ VerDef.vd_aux = E.AuxVOffset.value_or(sizeof(Elf_Verdef));
VerDef.vd_cnt = E.VerNames.size();
if (I == Section.Entries->size() - 1)
VerDef.vd_next = 0;
@@ -1665,13 +1665,13 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
CBA.write((const char *)&VerDef, sizeof(Elf_Verdef));
for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) {
- Elf_Verdaux VernAux;
- VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);
+ Elf_Verdaux VerdAux;
+ VerdAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);
if (J == E.VerNames.size() - 1)
- VernAux.vda_next = 0;
+ VerdAux.vda_next = 0;
else
- VernAux.vda_next = sizeof(Elf_Verdaux);
- CBA.write((const char *)&VernAux, sizeof(Elf_Verdaux));
+ VerdAux.vda_next = sizeof(Elf_Verdaux);
+ CBA.write((const char *)&VerdAux, sizeof(Elf_Verdaux));
}
}
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index e97248cbcf5682..821f48723b35e5 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1921,6 +1921,7 @@ void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO,
IO.mapOptional("Flags", E.Flags);
IO.mapOptional("VersionNdx", E.VersionNdx);
IO.mapOptional("Hash", E.Hash);
+ IO.mapOptional("AuxVOffset", E.AuxVOffset);
IO.mapRequired("Names", E.VerNames);
}
>From f94b7912f9f7677be1116c89dcab90b19b53108b Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 7 Nov 2024 10:22:41 +0100
Subject: [PATCH 2/2] [llvm-objdump][ELF] Ensure offset to verdaux entry array
does not go past size
Validate `vd_aux` while parsing `Elf_Verdef` structure.
Fixes: https://github.com/llvm/llvm-project/issues/86611.
---
.../llvm-objdump/ELF/invalid-verdef.test | 29 +++++++++++++++++++
llvm/tools/llvm-objdump/ELFDump.cpp | 17 ++++++++---
2 files changed, 42 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test
diff --git a/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test b/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test
new file mode 100644
index 00000000000000..abf9a2829f248c
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test
@@ -0,0 +1,29 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objdump -p %t 2>&1 | FileCheck --check-prefix=BROKEN-VERDEF -DFILE=%t %s
+
+# BROKEN-VERDEF: Version definitions:
+# BROKEN-VERDEF-NEXT: warning: '[[FILE]]': out-of-bound while parsing verdaux entries, corrupted verdef section
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x0000000000001000
+Sections:
+ - Name: .gnu.version_d
+ Type: SHT_GNU_verdef
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000000230
+ AddressAlign: 0x0000000000000004
+ Entries:
+ - Version: 1
+ Flags: 44
+ VersionNdx: 0
+ Hash: 12345
+ AuxVOffset: 0x45
+ Names:
+ - VERSION_1
+DynamicSymbols: []
+...
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index 5ac13495662faf..3c5d11ef8ba751 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -39,6 +39,9 @@ template <typename ELFT> class ELFDumper : public Dumper {
void printProgramHeaders();
void printSymbolVersion();
void printSymbolVersionDependency(const typename ELFT::Shdr &Sec);
+ void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
+ ArrayRef<uint8_t> Contents,
+ StringRef StrTab);
};
} // namespace
@@ -380,9 +383,9 @@ void ELFDumper<ELFT>::printSymbolVersionDependency(
}
template <class ELFT>
-static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
- ArrayRef<uint8_t> Contents,
- StringRef StrTab) {
+void ELFDumper<ELFT>::printSymbolVersionDefinition(
+ const typename ELFT::Shdr &Shdr, ArrayRef<uint8_t> Contents,
+ StringRef StrTab) {
outs() << "\nVersion definitions:\n";
const uint8_t *Buf = Contents.data();
@@ -398,6 +401,12 @@ static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
<< format("0x%08" PRIx32 " ", (uint32_t)Verdef->vd_hash);
const uint8_t *BufAux = Buf + Verdef->vd_aux;
+ if (BufAux > Contents.end()) {
+ reportWarning("out-of-bound while parsing verdaux entries, corrupted "
+ "verdef section",
+ Obj.getFileName());
+ break;
+ }
uint16_t VerdauxIndex = 0;
while (BufAux) {
auto *Verdaux = reinterpret_cast<const typename ELFT::Verdaux *>(BufAux);
@@ -430,7 +439,7 @@ template <class ELFT> void ELFDumper<ELFT>::printSymbolVersion() {
if (Shdr.sh_type == ELF::SHT_GNU_verneed)
printSymbolVersionDependency(Shdr);
else
- printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
+ printSymbolVersionDefinition(Shdr, Contents, StrTab);
}
}
More information about the llvm-commits
mailing list