From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 62380386F427; Thu, 7 Jan 2021 20:41:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 62380386F427 From: "cvs-commit at gcc dot gnu.org" To: gdb-prs@sourceware.org Subject: [Bug remote/26614] AddressSanitizer: heap-use-after-free of extended_remote_target in remote_async_inferior_event_handler Date: Thu, 07 Jan 2021 20:41:06 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gdb X-Bugzilla-Component: remote X-Bugzilla-Version: HEAD X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at sourceware dot org X-Bugzilla-Target-Milestone: 10.2 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gdb-prs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-prs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jan 2021 20:41:07 -0000 https://sourceware.org/bugzilla/show_bug.cgi?id=3D26614 --- Comment #26 from cvs-commit at gcc dot gnu.org --- The gdb-10-branch branch has been updated by Tom de Vries : https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Df498adf03ff6= c9ee76a8bdb8078ece11c176798c commit f498adf03ff6c9ee76a8bdb8078ece11c176798c Author: Pedro Alves Date: Thu Jan 7 21:41:03 2021 +0100 [gdb/remote] Fix invalid pointer in remote_async_serial_handler On rare occasions, we run into this ERROR/UNRESOLVED on gdb-10-branch: ... (gdb) PASS: gdb.multi/multi-target.exp: continue: non-stop=3Don: inferi= or 2 Remote debugging from host ::1, port 34088^M Process outputs/gdb.multi/multi-target/multi-target created; pid =3D 86= 49^M monitor exit^M (gdb) Killing process(es): 8649^M ERROR: GDB process no longer exists GDB process exited with wait status 8627 exp14 0 0 CHILDKILLED SIGABRT SIGABRT UNRESOLVED: gdb.multi/multi-target.exp: continue: non-stop=3Don: inferi= or 5 ... A trigger patch makes the crash happen all the time: ... diff --git a/gdb/remote.c b/gdb/remote.c index 71f814efb365..53ff8b63a1dc 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -14161,14 +14161,12 @@ remote_target::is_async_p () will be able to delay notifying the client of an event until the point where an entire packet has been received. */ -static serial_event_ftype remote_async_serial_handler; - static void remote_async_serial_handler (struct serial *scb, void *context) { - /* Don't propogate error information up to the client. Instead let - the client find out about the error by querying the target. */ - inferior_event_handler (INF_REG_EVENT); + remote_state *rs =3D (remote_state *) context; + + mark_async_event_handler (rs->remote_async_inferior_event_token); } static void ... And using -fsanitizer=3Daddress we can get a more elaborate error messa= ge: ... =3D=3D7196=3D=3DERROR: AddressSanitizer: heap-use-after-free on address= \ 0x6170000bf258 at pc 0x000001481755 bp 0x7fff05b20840 sp 0x7fff05b208= 38 READ of size 8 at 0x6170000bf258 thread T0 #0 0x1481754 in std::_Hashtable, std::allocator >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_M_bucket_index(unsigned long) const /usr/include/c++/11/bits/hashtable.h:719 #1 0x147c8ab in std::_Hashtable, std::allocator >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::find(gdbarc= h* const&) /usr/include/c++/11/bits/hashtable.h:1500 #2 0x147852c in std::unordered_map, std::equal_to, std::allocator > >::find(gdbarch* const&) /usr/include/c++/11/bits/unordered_map.h:8= 69 #3 0x14306db in remote_state::get_remote_arch_state(gdbarch*) src/gdb/remote.c:1203 #4 0x14309dc in remote_target::get_remote_state() src/gdb/remote.c:= 1232 #5 0x1470c08 in remote_async_inferior_event_handler src/gdb/remote.c:14169 #6 0xaa9f6b in check_async_event_handlers() src/gdb/async-event.c:2= 95 #7 0x1e93ab4 in gdb_do_one_event() src/gdbsupport/event-loop.cc:194 #8 0x118f5f9 in start_event_loop src/gdb/main.c:356 #9 0x118f8ed in captured_command_loop src/gdb/main.c:416 #10 0x1192d6a in captured_main src/gdb/main.c:1253 #11 0x1192dfa in gdb_main(captured_main_args*) src/gdb/main.c:1268 #12 0x97b380 in main src/gdb/gdb.c:32 #13 0x7f550c211349 in __libc_start_main ../csu/libc-start.c:308 #14 0x97b199 in _start (build/gdb/gdb+0x97b199) 0x6170000bf258 is located 600 bytes inside of 648-byte region \ [0x6170000bf000,0x6170000bf288) freed by thread T0 here: #0 0x7f550f516a57 in operator delete(void*, unsigned long) (/usr/lib64/libasan.so.6+0xaea57) #1 0x148b1fe in extended_remote_target::~extended_remote_target() src/gdb/remote.c:958 #2 0x143b483 in remote_target::close() src/gdb/remote.c:4074 #3 0x16cb90f in target_close(target_ops*) src/gdb/target.c:3230 #4 0x16a2635 in decref_target(target_ops*) src/gdb/target.c:557 #5 0x16a2abb in target_stack::unpush(target_ops*) src/gdb/target.c:= 645 #6 0x16d01ef in inferior::unpush_target(target_ops*) src/gdb/inferior.h:356 #7 0x16a2877 in unpush_target(target_ops*) src/gdb/target.c:607 #8 0x16a2adf in unpush_target_and_assert src/gdb/target.c:655 #9 0x16a2c57 in pop_all_targets_at_and_above(strata) src/gdb/target.c:678 #10 0x1442749 in remote_unpush_target src/gdb/remote.c:5522 #11 0x1458c16 in remote_target::readchar(int) src/gdb/remote.c:9137 #12 0x145b25b in remote_target::getpkt_or_notif_sane_1(std::vector > >*, int, i= nt, int*) src/gdb/remote.c:9683 #13 0x145bc9a in remote_target::getpkt_sane(std::vector > >*, int) src/gdb/remote.c:9790 #14 0x145b040 in remote_target::getpkt(std::vector > >*, int) src/gdb/remote.c:9623 #15 0x145780b in remote_target::remote_read_bytes_1(unsigned long, unsigned char*, unsigned long, int, unsigned long*) src/gdb/remote.c:8860 #16 0x145805e in remote_target::remote_read_bytes(unsigned long, unsigned char*, unsigned long, int, unsigned long*) src/gdb/remote.c:8987 #17 0x146113a in remote_target::xfer_partial(target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) src/gdb/remote.c:10987 #18 0x16a4004 in raw_memory_xfer_partial(target_ops*, unsigned char= *, unsigned char const*, unsigned long, long, unsigned long*) src/gdb/target.c:918 #19 0x16a4fcf in target_xfer_partial(target_ops*, target_object, ch= ar const*, unsigned char*, unsigned char const*, unsigned long, unsign= ed long, unsigned long*) src/gdb/target.c:1156 #20 0x16a5d65 in target_read_partial src/gdb/target.c:1387 #21 0x16a5f19 in target_read(target_ops*, target_object, char const= *, unsigned char*, unsigned long, long) src/gdb/target.c:1427 #22 0x16a5666 in target_read_raw_memory(unsigned long, unsigned cha= r*, long) src/gdb/target.c:1260 #23 0xd22f2a in dcache_read_line src/gdb/dcache.c:336 #24 0xd232b7 in dcache_peek_byte src/gdb/dcache.c:403 #25 0xd23845 in dcache_read_memory_partial(target_ops*, dcache_stru= ct*, unsigned long, unsigned char*, unsigned long, unsigned long*) src/gdb/dcache.c:484 #26 0x16a47da in memory_xfer_partial_1 src/gdb/target.c:1041 #27 0x16a4a1e in memory_xfer_partial src/gdb/target.c:1084 #28 0x16a4f44 in target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) src/gdb/target.c:1141 #29 0x18203d4 in read_value_memory(value*, long, int, unsigned long, unsigned char*, unsigned long) src/gdb/valops.c:956 previously allocated by thread T0 here: #0 0x7f550f515c37 in operator new(unsigned long) (/usr/lib64/libasan.so.6+0xadc37) #1 0x14429f0 in remote_target::open_1(char const*, int, int) src/gdb/remote.c:5562 #2 0x14405e6 in extended_remote_target::open(char const*, int) src/gdb/remote.c:4907 #3 0x16a0f3c in open_target src/gdb/target.c:242 #4 0xc19ff5 in do_sfunc src/gdb/cli/cli-decode.c:111 #5 0xc221db in cmd_func(cmd_list_element*, char const*, int) src/gdb/cli/cli-decode.c:2181 #6 0x16feda6 in execute_command(char const*, int) src/gdb/top.c:668 #7 0xee9dc9 in command_handler(char const*) src/gdb/event-top.c:588 #8 0xeea6a8 in command_line_handler(std::unique_ptr >&&) src/gdb/event-top.c:773 #9 0xee8a12 in gdb_rl_callback_handler src/gdb/event-top.c:219 #10 0x7f550f24aead in rl_callback_read_char (/lib64/libreadline.so.7+0x31ead) ... The problem is here in remote_async_inferior_event_handler: ... static void remote_async_inferior_event_handler (gdb_client_data data) { inferior_event_handler (INF_REG_EVENT); remote_target *remote =3D (remote_target *) data; remote_state *rs =3D remote->get_remote_state (); ... The remote target (passed in the data argument) can be destroyed during= the call to inferior_event_handler. If so, the call to remote->get_remote_state () is done using a dangling pointer. Fix this by increasing the reference count on the remote target before calling inferior_event_handler, such that it won't get destroyed until right be= fore returning from remote_async_inferior_event_handler. Tested on x86_64-linux. Intended for gdb-10-branch. The problem has stopped reproducing with the trigger patch since master commit 79952e69634 "Make scoped_restore_current_thread's cdtors exception free (RFC)". We could still apply this to master though. gdb/ChangeLog: 2021-01-07 Pedro Alves Simon Marchi Tom de Vries PR remote/26614 * remote.c (remote_async_inferior_event_handler): Hold a strong reference to the remote target while handling an event. --=20 You are receiving this mail because: You are on the CC list for the bug.=