Skip to content

llvm-objdump: printDynamicSection() out-of-bounds read #86612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
emaste opened this issue Mar 26, 2024 · 6 comments · Fixed by #125679
Closed

llvm-objdump: printDynamicSection() out-of-bounds read #86612

emaste opened this issue Mar 26, 2024 · 6 comments · Fixed by #125679

Comments

@emaste
Copy link
Member

emaste commented Mar 26, 2024

Reported against FreeBSD at https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277885, with attached ELF reproducer.

# llvm-objdump --version
LLVM (http://llvm.org/):
  LLVM version 17.0.6
  Optimized build with assertions.
...
# llvm-objdump -x objdump10a.exe
...
Dynamic Section:
  NEEDED       PLEASE submit a bug report to https://bugs.freebsd.org/submit/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llvm-objdump -x objdump10a.exe
 #0 0x0000000001230c41 PrintStackTrace /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:602:13
 #1 0x000000000122f0b5 RunSignalHandlers /usr/src/contrib/llvm-project/llvm/lib/Support/Signals.cpp:105:18
 #2 0x0000000001231365 SignalHandler /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
 #3 0x00000008267d55ff handle_signal /usr/src/lib/libthr/thread/thr_sig.c:0:3
 #4 0x00000008267d4bbb thr_sighandler /usr/src/lib/libthr/thread/thr_sig.c:244:1
 #5 0x0000000822def2d3 ([vdso]+0x2d3)
 #6 0x0000000828b3a7eb /usr/src/lib/libc/amd64/string/strlen.S:95:0
 #7 0x0000000000df28c9 __constexpr_strlen /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__string/constexpr_c_functions.h:49:10
 #8 0x0000000000df28c9 length /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__string/char_traits.h:222:14
 #9 0x0000000000df28c9 StringRef /usr/src/contrib/llvm-project/llvm/include/llvm/ADT/StringRef.h:90:33
#10 0x0000000000df28c9 operator<< /usr/src/contrib/llvm-project/llvm/include/llvm/Support/raw_ostream.h:244:29
#11 0x0000000000df28c9 printDynamicSection /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:233:16
#12 0x0000000000df28c9 printPrivateHeaders /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:431:3
#13 0x0000000000e6a13c dumpObject /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:2815:7
#14 0x0000000000e654b0 dumpInput /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:0:5
#15 0x0000000000e654b0 for_each<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > *>, void (*)(llvm::StringRef)> /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__algorithm/for_each.h:26:5
#16 0x0000000000e654b0 for_each<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > &, void (*)(llvm::StringRef)> /usr/src/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1731:10
#17 0x0000000000e654b0 main /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:3248:3
#18 0x0000000828a660aa __libc_start1 /usr/src/lib/libc/csu/libc_start1.c:157:2
Segmentation fault (core dumped)
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2024

@llvm/issue-subscribers-tools-llvm-objdump

Author: Ed Maste (emaste)

Reported against FreeBSD at https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277885, with attached ELF reproducer.
# llvm-objdump --version
LLVM (http://llvm.org/):
  LLVM version 17.0.6
  Optimized build with assertions.
...
# llvm-objdump -x objdump10a.exe
...
Dynamic Section:
  NEEDED       PLEASE submit a bug report to https://bugs.freebsd.org/submit/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llvm-objdump -x objdump10a.exe
 #<!-- -->0 0x0000000001230c41 PrintStackTrace /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:602:13
 #<!-- -->1 0x000000000122f0b5 RunSignalHandlers /usr/src/contrib/llvm-project/llvm/lib/Support/Signals.cpp:105:18
 #<!-- -->2 0x0000000001231365 SignalHandler /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
 #<!-- -->3 0x00000008267d55ff handle_signal /usr/src/lib/libthr/thread/thr_sig.c:0:3
 #<!-- -->4 0x00000008267d4bbb thr_sighandler /usr/src/lib/libthr/thread/thr_sig.c:244:1
 #<!-- -->5 0x0000000822def2d3 ([vdso]+0x2d3)
 #<!-- -->6 0x0000000828b3a7eb /usr/src/lib/libc/amd64/string/strlen.S:95:0
 #<!-- -->7 0x0000000000df28c9 __constexpr_strlen /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__string/constexpr_c_functions.h:49:10
 #<!-- -->8 0x0000000000df28c9 length /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__string/char_traits.h:222:14
 #<!-- -->9 0x0000000000df28c9 StringRef /usr/src/contrib/llvm-project/llvm/include/llvm/ADT/StringRef.h:90:33
#<!-- -->10 0x0000000000df28c9 operator&lt;&lt; /usr/src/contrib/llvm-project/llvm/include/llvm/Support/raw_ostream.h:244:29
#<!-- -->11 0x0000000000df28c9 printDynamicSection /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:233:16
#<!-- -->12 0x0000000000df28c9 printPrivateHeaders /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:431:3
#<!-- -->13 0x0000000000e6a13c dumpObject /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:2815:7
#<!-- -->14 0x0000000000e654b0 dumpInput /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:0:5
#<!-- -->15 0x0000000000e654b0 for_each&lt;std::__1::__wrap_iter&lt;std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt; *&gt;, void (*)(llvm::StringRef)&gt; /usr/obj/usr/src/amd64.amd64/tmp/usr/include/c++/v1/__algorithm/for_each.h:26:5
#<!-- -->16 0x0000000000e654b0 for_each&lt;std::__1::vector&lt;std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt;, std::__1::allocator&lt;std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt; &gt; &gt; &amp;, void (*)(llvm::StringRef)&gt; /usr/src/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1731:10
#<!-- -->17 0x0000000000e654b0 main /usr/src/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:3248:3
#<!-- -->18 0x0000000828a660aa __libc_start1 /usr/src/lib/libc/csu/libc_start1.c:157:2
Segmentation fault (core dumped)

@jh7370
Copy link
Collaborator

jh7370 commented Mar 26, 2024

Possible duplicate of #85568? Could you check against HEAD, please?

@antoniofrighetto
Copy link
Contributor

Think this should work:

--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -233,7 +233,13 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() {
       Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf);
       if (StrTabOrErr) {
         const char *Data = StrTabOrErr.get().data();
-        outs() << (Data + Dyn.d_un.d_val) << "\n";
+        const auto SecSize =
+            unwrapOrError(Elf.getSection(ELF::SHT_DYNAMIC), Obj.getFileName())
+                ->sh_size;
+        if (Dyn.d_un.d_val > SecSize)
+          reportWarning("string table offset out-of-bound", Obj.getFileName());
+        else
+          outs() << Data + Dyn.d_un.d_val << "\n";
         continue;
       }
       reportWarning(toString(StrTabOrErr.takeError()), Obj.getFileName());

@emaste
Copy link
Member Author

emaste commented Mar 26, 2024

Possible duplicate of #85568? Could you check against HEAD, please?

These were submitted as separate FreeBSD issues, and indeed it is still reproducible at bf4fc00

Dynamic Section:
  NEEDED       PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/llvm-objdump -x attachment.cgi?id=249399
 #0 0x0000000001ab76e8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/emaste/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:731:8
 #1 0x0000000001ab5b25 llvm::sys::RunSignalHandlers() /home/emaste/src/llvm-project/llvm/lib/Support/Signals.cpp:106:18
 #2 0x0000000001ab7e76 SignalHandler(int) /home/emaste/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
 #3 0x0000000822e686ef handle_signal /usr/home/emaste/src/freebsd/lib/libthr/thread/thr_sig.c:0:3
 #4 0x0000000822e67cab thr_sighandler /usr/home/emaste/src/freebsd/lib/libthr/thread/thr_sig.c:244:1
 #5 0x00000008229612d3 ([vdso]+0x2d3)
 #6 0x00000008270b672b /usr/home/emaste/src/freebsd/lib/libc/amd64/string/strlen.S:95:0
 #7 0x00000000015faf9f std::__1::__constexpr_strlen[abi:un170006](char const*) /usr/include/c++/v1/__string/constexpr_c_functions.h:49:10
 #8 0x00000000015faf9f std::__1::char_traits<char>::length[abi:un170006](char const*) /usr/include/c++/v1/__string/char_traits.h:222:14
 #9 0x00000000015faf9f llvm::StringRef::StringRef(char const*) /home/emaste/src/llvm-project/llvm/include/llvm/ADT/StringRef.h:90:33
#10 0x00000000015faf9f llvm::raw_ostream::operator<<(char const*) /home/emaste/src/llvm-project/llvm/include/llvm/Support/raw_ostream.h:260:29
#11 0x00000000015faf9f (anonymous namespace)::ELFDumper<llvm::object::ELFType<(llvm::endianness)1, true>>::printDynamicSection() /home/emaste/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:236:16
#12 0x00000000015faf9f (anonymous namespace)::ELFDumper<llvm::object::ELFType<(llvm::endianness)1, true>>::printPrivateHeaders() /home/emaste/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp:434:3
#13 0x00000000015c7835 dumpObject(llvm::object::ObjectFile*, llvm::object::Archive const*, llvm::object::Archive::Child const*) /home/emaste/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:3236:7
#14 0x00000000015beca0 dumpInput(llvm::StringRef) /home/emaste/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:0:5
#15 0x00000000015beca0 void (*std::__1::for_each[abi:un170006]<std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*>, void (*)(llvm::StringRef)>(std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*>, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*>, void (*)(llvm::StringRef)))(llvm::StringRef) /usr/include/c++/v1/__algorithm/for_each.h:26:5
#16 0x00000000015beca0 void (*llvm::for_each<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, void (*)(llvm::StringRef)>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, void (*)(llvm::StringRef)))(llvm::StringRef) /home/emaste/src/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1725:10
#17 0x00000000015beca0 llvm_objdump_main(int, char**, llvm::ToolContext const&) /home/emaste/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp:3685:3
#18 0x0000000001651b44 main /home/emaste/src/llvm-project/build/tools/llvm-objdump/llvm-objdump-driver.cpp:17:10
#19 0x0000000826fe17ca __libc_start1 /usr/home/emaste/src/freebsd/lib/libc/csu/libc_start1.c:157:2
Segmentation fault (core dumped)

and no crash with @antoniofrighetto's patch:

...
         filesz 0x0000000000000048 memsz 0x0000000000000048 flags r--

Dynamic Section:
  NEEDED       bin/llvm-objdump: warning: 'attachment.cgi?id=249399': string table offset out-of-bound
  FLAGS_1      0x0000000008000000
  DEBUG        0x0000000000000000
...

artagnon added a commit to artagnon/llvm-project that referenced this issue Apr 3, 2024
When reading the dynamic string table, llvm-objdump used to crash if
the ELF was malformed, due to an erroneous consumption of error status.
Instead, propogate the error status to the caller, fixing the crash, and
printing a warning.

Fixes llvm#86612.
@MaskRay
Copy link
Member

MaskRay commented Apr 3, 2024

llvm/tools/llvm-objdump/ELFDump.cpp:70 consumeError(MappedAddrOrError.takeError()); has a bug. If DT_STRTAB is a wrong address, *MappedAddrOrError may crash.

@artagnon We need a minimal reproduce file. obj2yaml gives a start, but you need to scrub unneeded parts from the YAML file. A test filename like pr86612 is not descriptive. Reusing dynamic-section.test may be a good idea.

cabbaken added a commit to cabbaken/llvm-project that referenced this issue Jan 26, 2025
This change make the check of the section size to
avoid crashing of llvm-objdump when processing
misformated elf file.

Signed-off-by: cabbaken <[email protected]>
cabbaken added a commit to cabbaken/llvm-project that referenced this issue Jan 26, 2025
This change make the check of the section size to
avoid crashing of llvm-objdump when processing
misformated elf file.

Signed-off-by: cabbaken <[email protected]>
cabbaken added a commit to cabbaken/llvm-project that referenced this issue Jan 28, 2025
This change make the check of the section size to
avoid crashing of llvm-objdump when processing
misformated elf file.

Signed-off-by: cabbaken <[email protected]>
cabbaken added a commit to cabbaken/llvm-project that referenced this issue Feb 4, 2025
…ng for malformed ELF file(llvm#86612)

This change introduces a check for the strtab offset
to prevent llvm-objdump from crashing when processing
malformed ELF files.
Additionally, it modifies how llvm-objdump handles and
outputs malformed ELF files with invalid string offsets.
More info: https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391

Signed-off-by: cabbaken <[email protected]>
@cabbaken
Copy link
Contributor

cabbaken commented Feb 4, 2025

llvm/tools/llvm-objdump/ELFDump.cpp:70 consumeError(MappedAddrOrError.takeError()); has a bug. If DT_STRTAB is a wrong address, *MappedAddrOrError may crash.

@artagnon We need a minimal reproduce file. obj2yaml gives a start, but you need to scrub unneeded parts from the YAML file. A test filename like pr86612 is not descriptive. Reusing dynamic-section.test may be a good idea.

I tested the binary file of above link, the cause of the crashing is the huge value of Dyn.getVal()(exceed valid memory access range). I edited dynamic-section.test so problem can be reproduced now.
And I provide a patch for the error handling and reproduce test about this problem.

cabbaken added a commit to cabbaken/llvm-project that referenced this issue Feb 5, 2025
…6612)

This change introduces a check for the strtab offset
to prevent llvm-objdump from crashing when processing
malformed ELF files.
Additionally, it modifies how llvm-objdump handles and
outputs malformed ELF files with invalid string offsets.
More info: https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391

Signed-off-by: cabbaken <[email protected]>
MaskRay pushed a commit that referenced this issue Mar 10, 2025
This change introduces a check for the strtab offset to prevent
llvm-objdump from crashing when processing malformed ELF files.
It provide a minimal reproduce test for
#86612 (comment).
Additionally, it modifies how llvm-objdump handles and outputs malformed
ELF files with invalid string offsets.(More info:
https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391)

Fixes: #86612

Co-authored-by: James Henderson <[email protected]>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this issue Mar 10, 2025
…nstr (#125679)

This change introduces a check for the strtab offset to prevent
llvm-objdump from crashing when processing malformed ELF files.
It provide a minimal reproduce test for
llvm/llvm-project#86612 (comment).
Additionally, it modifies how llvm-objdump handles and outputs malformed
ELF files with invalid string offsets.(More info:
https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391)

Fixes: #86612

Co-authored-by: James Henderson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants