Created attachment 14967 [details] crash seed Hello GDB developers, We recently conducted a fuzzing test on GDB and discovered a dynamic-stack-buffer-overflow bug. We would like to provide a detailed description of the bug and seek your assistance in addressing it. version: gdb:GNU gdb (GDB) 13.0.50.20220805-git gcc:gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) ubuntu: 20.04 command to reproduce: gdb -x command.gdb UAF_2 UAF_2 is attached to this report. command.gdb is attached to the first comment. ASAN report: ================================================================= ==2661699==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7ffe5c3013ff at pc 0x00000057b9bd bp 0x7ffe5c300910 sp 0x7ffe5c300908 READ of size 1 at 0x7ffe5c3013ff thread T0 #0 0x57b9bc in ada_decode[abi:cxx11](char const*, bool, bool) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/ada-lang.c:1388:16 #1 0x61bbd1 in ada_language::sniff_from_mangled_name(char const*, std::unique_ptr<char, gdb::xfree_deleter<char> >*) const /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/ada-lang.c:13574:29 #2 0x1c46d7d in symbol_find_demangled_name(general_symbol_info*, char const*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symtab.c:892:17 #3 0x1c47e70 in general_symbol_info::compute_and_set_names(gdb::basic_string_view<char, std::char_traits<char> >, bool, objfile_per_bfd_storage*, gdb::optional<unsigned int>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symtab.c:980:7 #4 0xb2919d in process_coff_symbol(coff_symbol*, internal_auxent*, objfile*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/coffread.c:1571:8 #5 0xb2604b in coff_symtab_read(minimal_symbol_reader&, long, unsigned int, objfile*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/coffread.c:1183:4 #6 0xb1d5ea in coff_read_minsyms(long, unsigned int, objfile*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/coffread.c:554:7 #7 0xb1abd0 in coff_symfile_read(objfile*, enum_flags<symfile_add_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/coffread.c:702:3 #8 0x1bf6a0e in read_symbols(objfile*, enum_flags<symfile_add_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:772:3 #9 0x1c19531 in syms_from_objfile_1(objfile*, std::vector<other_sections, std::allocator<other_sections> >*, enum_flags<symfile_add_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:968:3 #10 0x1c180fd in syms_from_objfile(objfile*, std::vector<other_sections, std::allocator<other_sections> >*, enum_flags<symfile_add_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:985:3 #11 0x1be663c in symbol_file_add_with_addrs(bfd*, char const*, enum_flags<symfile_add_flag>, std::vector<other_sections, std::allocator<other_sections> >*, enum_flags<objfile_flag>, objfile*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:1088:3 #12 0x1be70b3 in symbol_file_add_from_bfd(bfd*, char const*, enum_flags<symfile_add_flag>, std::vector<other_sections, std::allocator<other_sections> >*, enum_flags<objfile_flag>, objfile*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:1168:10 #13 0x1be7459 in symbol_file_add(char const*, enum_flags<symfile_add_flag>, std::vector<other_sections, std::allocator<other_sections> >*, enum_flags<objfile_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:1181:10 #14 0x1be873e in symbol_file_add_main_1(char const*, enum_flags<symfile_add_flag>, enum_flags<objfile_flag>, unsigned long) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:1205:29 #15 0x1be82ea in symbol_file_add_main(char const*, enum_flags<symfile_add_flag>) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symfile.c:1196:3 #16 0x15c8b73 in symbol_file_add_main_adapter(char const*, int) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/main.c:540:3 #17 0x15c6d2c in catch_command_errors(void (*)(char const*, int), char const*, int, bool) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/main.c:513:7 #18 0x15c433a in captured_main_1(captured_main_args*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/main.c:1212:8 #19 0x15be28d in captured_main(void*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/main.c:1319:3 #20 0x15be058 in gdb_main(captured_main_args*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/main.c:1344:7 #21 0x4e4f12 in main /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/gdb.c:32:10 #22 0x7f63cb655082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16 #23 0x433ebd in _start (/home/root/sp/Fuzz/aflpp_fuzz/Binutils/document_group/batch_x/gdb_1/gdb+0x433ebd) Address 0x7ffe5c3013ff is located in stack of thread T0 at offset 479 in frame #0 0x1c4685f in symbol_find_demangled_name(general_symbol_info*, char const*) /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/symtab.c:872 This frame has 1 object(s): [32, 40) 'demangled' (line 873) <== Memory access at offset 479 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow /home/root/sp/Dataset/Binutils/binutils_aflpp/gdb/ada-lang.c:1388:16 in ada_decode[abi:cxx11](char const*, bool, bool) Shadow bytes around the buggy address: 0x10004b858220: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 0x10004b858230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10004b858240: 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 0x10004b858250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10004b858260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x10004b858270: 00 00 00 00 00 00 00 00 00 00 00 00 ca ca ca[ca] 0x10004b858280: 03 cb cb cb cb cb cb cb f1 f1 f1 f1 00 00 f2 f2 0x10004b858290: 00 00 00 00 f2 f2 f2 f2 00 00 f2 f2 f8 f2 00 f2 0x10004b8582a0: f2 f2 00 00 f2 f2 f8 f8 f2 f2 00 f2 f2 f2 00 00 0x10004b8582b0: f2 f2 00 00 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x10004b8582c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==2661699==ABORTING Thank you for your attention and support. Best regards, Michael Zhang.
Created attachment 14968 [details] input file of -x option input file of -x option
The supplied executable does not segfault gdb in the reported location: $ ./gdb -nx -q --data-directory data-directory UAF_2 Reading symbols from UAF_2... Fatal signal: Segmentation fault ----- Backtrace ----- 0x599064 gdb_internal_backtrace_1 ../../src/gdb/bt-utils.c:122 0x599107 _Z22gdb_internal_backtracev ../../src/gdb/bt-utils.c:168 0x782fd4 handle_fatal_signal ../../src/gdb/event-top.c:889 0x783140 handle_sigsegv ../../src/gdb/event-top.c:962 0x7fe5a7d7eb6f ??? 0x6107a5 process_coff_symbol ../../src/gdb/coffread.c:1572 0x60f847 coff_symtab_read ../../src/gdb/coffread.c:1190 0x60e0dd coff_read_minsyms ../../src/gdb/coffread.c:549 0x60e629 coff_symfile_read ../../src/gdb/coffread.c:698 0xbd975e read_symbols ../../src/gdb/symfile.c:772 0xbd9e0b syms_from_objfile_1 ../../src/gdb/symfile.c:966 0xbd9ecf syms_from_objfile ../../src/gdb/symfile.c:983 0xbda3aa symbol_file_add_with_addrs ../../src/gdb/symfile.c:1086 0xbda6eb _Z24symbol_file_add_from_bfdRKN3gdb7ref_ptrI3bfd18gdb_bfd_ref_policyEEPKc10enum_flagsI16symfile_add_flagEPSt6vectorI14other_sectionsSaISC_EES8_I12objfile_flagEP7objfile ../../src/gdb/symfile.c:1166 0xbda73a _Z15symbol_file_addPKc10enum_flagsI16symfile_add_flagEPSt6vectorI14other_sectionsSaIS5_EES1_I12objfile_flagE ../../src/gdb/symfile.c:1179 0xbda7ff symbol_file_add_main_1 ../../src/gdb/symfile.c:1203 0xbda7a6 _Z20symbol_file_add_mainPKc10enum_flagsI16symfile_add_flagE ../../src/gdb/symfile.c:1194 0x90b1d7 symbol_file_add_main_adapter ../../src/gdb/main.c:549 0x90b0ed catch_command_errors ../../src/gdb/main.c:518 0x90c20e captured_main_1 ../../src/gdb/main.c:1203 0x90c820 captured_main ../../src/gdb/main.c:1310 0x90c8bf _Z8gdb_mainP18captured_main_args ../../src/gdb/main.c:1339 0x418c3c main ../../src/gdb/gdb.c:32 --------------------- A fatal error internal to GDB has been detected, further debugging is not possible. GDB will now terminate. This is a bug, please report it. For instructions, see: <https://www.gnu.org/software/gdb/bugs/>. Segmentation fault (core dumped) Did you attach the correct binary to this bug?
(In reply to Keith Seitz from comment #2) > The supplied executable does not segfault gdb in the reported location: > > $ ./gdb -nx -q --data-directory data-directory UAF_2 > Reading symbols from UAF_2... > > > Fatal signal: Segmentation fault > ----- Backtrace ----- > 0x599064 gdb_internal_backtrace_1 > ../../src/gdb/bt-utils.c:122 > 0x599107 _Z22gdb_internal_backtracev > ../../src/gdb/bt-utils.c:168 > 0x782fd4 handle_fatal_signal > ../../src/gdb/event-top.c:889 > 0x783140 handle_sigsegv > ../../src/gdb/event-top.c:962 > 0x7fe5a7d7eb6f ??? > 0x6107a5 process_coff_symbol > ../../src/gdb/coffread.c:1572 > 0x60f847 coff_symtab_read > ../../src/gdb/coffread.c:1190 > 0x60e0dd coff_read_minsyms > ../../src/gdb/coffread.c:549 > 0x60e629 coff_symfile_read > ../../src/gdb/coffread.c:698 > 0xbd975e read_symbols > ../../src/gdb/symfile.c:772 > 0xbd9e0b syms_from_objfile_1 > ../../src/gdb/symfile.c:966 > 0xbd9ecf syms_from_objfile > ../../src/gdb/symfile.c:983 > 0xbda3aa symbol_file_add_with_addrs > ../../src/gdb/symfile.c:1086 > 0xbda6eb > _Z24symbol_file_add_from_bfdRKN3gdb7ref_ptrI3bfd18gdb_bfd_ref_policyEEPKc10en > um_flagsI16symfile_add_flagEPSt6vectorI14other_sectionsSaISC_EES8_I12objfile_ > flagEP7objfile > ../../src/gdb/symfile.c:1166 > 0xbda73a > _Z15symbol_file_addPKc10enum_flagsI16symfile_add_flagEPSt6vectorI14other_sect > ionsSaIS5_EES1_I12objfile_flagE > ../../src/gdb/symfile.c:1179 > 0xbda7ff symbol_file_add_main_1 > ../../src/gdb/symfile.c:1203 > 0xbda7a6 _Z20symbol_file_add_mainPKc10enum_flagsI16symfile_add_flagE > ../../src/gdb/symfile.c:1194 > 0x90b1d7 symbol_file_add_main_adapter > ../../src/gdb/main.c:549 > 0x90b0ed catch_command_errors > ../../src/gdb/main.c:518 > 0x90c20e captured_main_1 > ../../src/gdb/main.c:1203 > 0x90c820 captured_main > ../../src/gdb/main.c:1310 > 0x90c8bf _Z8gdb_mainP18captured_main_args > ../../src/gdb/main.c:1339 > 0x418c3c main > ../../src/gdb/gdb.c:32 > --------------------- > A fatal error internal to GDB has been detected, further > debugging is not possible. GDB will now terminate. > > This is a bug, please report it. For instructions, see: > <https://www.gnu.org/software/gdb/bugs/>. > > Segmentation fault (core dumped) > > Did you attach the correct binary to this bug? To reproduce this bug, please use the following command: gdb -x command.gdb UAF_2. The necessary files for this command are as follows: command.gdb (attachment_14968) and UAF_2 (attachment_14967). You can find command.gdb attached to the first comment, and UAF_2 attached as attachment_14967. If you encounter any issues during the reproduction process, please feel free to let me know.
Created attachment 15019 [details] UAF_2
Created attachment 15020 [details] command.gdb
I uploaded the command.gdb and UAF_2 file in the comment below.
For me this crashes in read_pe_truncate_name because read_pe_exported_syms seems to make a pointer to invalid memory. If there's a crash in the Ada decoder, that isn't a case of GIGO, what I'd really like to know is the name being decoded.
My apologies, this DOES reproduce (as Tom notes). The thing I ignored was ASAN. [The crash I reported was recently fixed by Alan Modra's "gdb: warn unused result for bfd IO functions".] [Probably TMI for Tom, but for anyone following along...] In process_coff_symbol, we are processing a symbol with name "44", i.e, just digits. The language of this objfile is language_unknown. process_coff_symbol calls general_symbol_info::compute_and_set_names. This eventually calls symbol_find_demangled_name with linkage_name_copy set to "44". Since the objfile's language is unknown, symbol_find_linkage_name iterates over all languages, calling the language's sniff_from_mangled_name method. This does nothing for all the languages until it hits language_ada. ada_language::sniff_from_mangled immediately calls ada_decode. The code here essentially skips to the last block which attempts to remove trailing digits: 1370 /* Remove trailing __{digit}+ or trailing ${digit}+. */ 1371 1372 if (len0 > 1 && isdigit (encoded[len0 - 1])) 1373 { 1374 i = len0 - 2; 1375 while ((i >= 0 && isdigit (encoded[i])) 1376 || (i >= 1 && encoded[i] == '_' && isdigit (encoded[i - 1]))) 1377 i -= 1; 1378 if (i > 1 && encoded[i] == '_' && encoded[i - 1] == '_') 1379 len0 = i - 1; 1380 else if (encoded[i] == '$') 1381 len0 = i; 1382 } When we get to 1372, len0 is strlen("44") which is 2. encoded[2 - 1] = "4" is a digit, and we set i = len0 - 2 = 0. Now the while loop: i == 0 and encoded[0] is "4", so that passes the first test, and we subtract 1 from i, setting it to -1. Now i is no longer >= 0 or >= 1, so the while loop escapes. Finally, we hit the final "else if" encoded[-1] == '$' on line 1380, which causes the observed buffer overflow.
Thanks for the analysis, Keith. I'll send a patch soon.
The master branch has been updated by Tom Tromey <tromey@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=033bc52bb6190393c8eed80925fa78cc35b40c6d commit 033bc52bb6190393c8eed80925fa78cc35b40c6d Author: Tom Tromey <tromey@adacore.com> Date: Wed Aug 16 11:29:19 2023 -0600 Avoid buffer overflow in ada_decode A bug report pointed out a buffer overflow in ada_decode, which Keith helpfully analyzed. ada_decode had a logic error when the input was all digits. While this isn't valid -- and would probably only appear in fuzzer tests -- it still should be handled properly. This patch adds a missing bounds check. Tested with the self-tests in an asan build. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30639 Reviewed-by: Keith Seitz <keiths@redhat.com>
Fixed.