Summary: | heap-use-after-free in symtab | ||
---|---|---|---|
Product: | gdb | Reporter: | Hannes Domani <ssbssa> |
Component: | symtab | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | ssbssa, vries |
Priority: | P2 | ||
Version: | HEAD | ||
Target Milestone: | 15.1 | ||
Host: | Target: | ||
Build: | Last reconfirmed: | ||
Attachments: |
valgrind log
heob output as html asan.log |
Description
Hannes Domani
2024-05-03 11:43:50 UTC
Created attachment 15487 [details]
heob output as html
With current trunk build on aarch64-linux and a hello world a.out, I run into a segmentation fault using: ... $ gdb -q -batch a.out -ex "tui enable" -ex "shell touch a.out" -ex start ... Created attachment 15489 [details]
asan.log
Produced using:
...
$ ( export TERM=xterm-mono; export ASAN_OPTIONS=detect_leaks=0:log_path=asan.log; ./gdb.sh -q -batch a.out -ex "tui enable" -ex "shell touch a.out" -ex start )
...
Workaround: Use "maint flush symbol-cache". At first glance, seems to be an ordering problem. tui_all_objfiles_removed should be executed after symtab_all_objfiles_removed. This demonstrator patch fixes it by calling symtab_all_objfiles_removed at the start of tui_all_objfiles_removed: ... diff --git a/gdb/symtab.c b/gdb/symtab.c index 58648a8779d..f79c1641cab 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1726,9 +1726,11 @@ symtab_new_objfile_observer (struct objfile *objfile) symbol_cache_flush (objfile->pspace); } +extern void symtab_all_objfiles_removed (program_space *pspace); + /* This module's 'all_objfiles_removed' observer. */ -static void +void symtab_all_objfiles_removed (program_space *pspace) { symbol_cache_flush (pspace); diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c index cf48e709ed8..7baebb5e6a8 100644 --- a/gdb/tui/tui-hooks.c +++ b/gdb/tui/tui-hooks.c @@ -58,9 +58,14 @@ static void tui_new_objfile_hook (struct objfile* objfile) { tui_on_objfiles_changed (); } +extern void symtab_all_objfiles_removed (program_space *pspace); + static void tui_all_objfiles_removed (program_space *pspace) -{ tui_on_objfiles_changed (); } +{ + symtab_all_objfiles_removed (pspace); + tui_on_objfiles_changed (); +} /* Observer for the register_changed notification. */ ... (In reply to Tom de Vries from comment #5) > At first glance, seems to be an ordering problem. Yes, I came to the same conclusion. I can 'fix' it by simply removing the tui_all_objfiles_removed hook, and I wonder if it is even needed at all. The master branch has been updated by Hannes Domani <ssbssa@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d68f983f88c7469befddcf221228070990cf25e1 commit d68f983f88c7469befddcf221228070990cf25e1 Author: Hannes Domani <ssbssa@yahoo.de> Date: Tue May 7 19:29:21 2024 +0200 Fix heap-use-after-free because all_objfiles_removed triggers tui_display_main Since gdb-10 there is a heap-use-after free happening if starting the target in TUI triggers a re-reading of symbols. It can be reproduced with: $ gdb -q -batch a.out -ex "tui enable" -ex "shell touch a.out" -ex start ==28392== Invalid read of size 1 ==28392== at 0x79E97E: lookup_global_or_static_symbol(char const*, block_enum, objfile*, domain_enum) (symtab.h:503) ==28392== by 0x79F859: lookup_global_symbol(char const*, block const*, domain_enum) (symtab.c:2641) ==28392== by 0x79F8E9: language_defn::lookup_symbol_nonlocal(char const*, block const*, domain_enum) const (symtab.c:2473) ==28392== by 0x7A66EE: lookup_symbol_aux(char const*, symbol_name_match_type, block const*, domain_enum, language, field_of_this_result*) (symtab.c:2150) ==28392== by 0x7A68C9: lookup_symbol_in_language(char const*, block const*, domain_enum, language, field_of_this_result*) (symtab.c:1958) ==28392== by 0x7A6A25: lookup_symbol(char const*, block const*, domain_enum, field_of_this_result*) (symtab.c:1970) ==28392== by 0x77120F: select_source_symtab() (source.c:319) ==28392== by 0x7EE2D5: tui_get_begin_asm_address(gdbarch**, unsigned long*) (tui-disasm.c:401) ==28392== by 0x807558: tui_display_main() (tui-winsource.c:55) ==28392== by 0x7937B5: clear_symtab_users(enum_flags<symfile_add_flag>) (functional:2464) ==28392== by 0x794F40: reread_symbols(int) (symfile.c:2690) ==28392== by 0x6497D1: run_command_1(char const*, int, run_how) (infcmd.c:398) ==28392== Address 0x4e67848 is 3,864 bytes inside a block of size 4,064 free'd ==28392== at 0x4A0A430: free (vg_replace_malloc.c:446) ==28392== by 0x936B63: _obstack_free (obstack.c:280) ==28392== by 0x79541E: reread_symbols(int) (symfile.c:2579) ==28392== by 0x6497D1: run_command_1(char const*, int, run_how) (infcmd.c:398) ==28392== by 0x4FFC45: cmd_func(cmd_list_element*, char const*, int) (cli-decode.c:2735) ==28392== by 0x7DAB50: execute_command(char const*, int) (top.c:575) ==28392== by 0x5D2B43: command_handler(char const*) (event-top.c:552) ==28392== by 0x5D3A50: command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) (event-top.c:788) ==28392== by 0x5D1F4B: gdb_rl_callback_handler(char*) (event-top.c:259) ==28392== by 0x857B3F: rl_callback_read_char (callback.c:290) ==28392== by 0x5D215D: gdb_rl_callback_read_char_wrapper_noexcept() (event-top.c:195) ==28392== by 0x5D232F: gdb_rl_callback_read_char_wrapper(void*) (event-top.c:234) The problem is that tui_display_main is called by the all_objfiles_removed hook, which tries to access the symbol cache. This symbol cache is actually stale at this point, and would have been flushed immediately afterwards by that same all_objfiles_removed hook. It's not possible to tell the hook to call the observers in a specific order, but in this case the tui_all_objfiles_removed observer is actually not needed, since it only calls tui_display_main, and a 'main' can only be found if objfiles are added, not removed. So the fix is to simply remove the tui_all_objfiles_removed observer. The clearing of the source window (if symbols were removed by e.g. 'file' without arguments) still works, since this is done by the tui_before_prompt observer. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31697 Approved-By: Tom Tromey <tom@tromey.com> Fixed. The master branch has been updated by Tom de Vries <vries@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0fd705062ee0bb570ac7a1201d6f3cc2ed96f95d commit 0fd705062ee0bb570ac7a1201d6f3cc2ed96f95d Author: Tom de Vries <tdevries@suse.de> Date: Wed May 8 17:02:15 2024 +0200 [gdb/testsuite] Add gdb.tui/reread.exp Add a regression test for commit d68f983f88c ("Fix heap-use-after-free because all_objfiles_removed triggers tui_display_main"). When building with address sanitizer, and reverting the commit it triggers the heap-use-after-free. Tested on aarch64-linux. PR symtab/31697 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31697 |