public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
From: "simark at simark dot ca" <sourceware-bugzilla@sourceware.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: Sun, 29 Nov 2020 14:53:03 +0000	[thread overview]
Message-ID: <bug-26614-4717-qXUy64AaEj@http.sourceware.org/bugzilla/> (raw)
In-Reply-To: <bug-26614-4717@http.sourceware.org/bugzilla/>

https://sourceware.org/bugzilla/show_bug.cgi?id=26614

Simon Marchi <simark at simark dot ca> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simark at simark dot ca

--- Comment #12 from Simon Marchi <simark at simark dot ca> ---
It looks very similar to a problem I hit while doing some unrelated changes.  I
think the reason is:

static void
remote_async_inferior_event_handler (gdb_client_data data)
{
  inferior_event_handler (INF_REG_EVENT);  <--- remote target can get destroyed
anywhere here

  remote_target *remote = (remote_target *) data;
  remote_state *rs = remote->get_remote_state ();  <--- we dereference the
remote target here

  /* inferior_event_handler may have consumed an event pending on the
     infrun side without calling target_wait on the REMOTE target, or
     may have pulled an event out of a different target.  Keep trying
     for this remote target as long it still has either pending events
     or unacknowledged notifications.  */

  if (rs->notif_state->pending_event[notif_client_stop.id] != NULL
      || !rs->stop_reply_queue.empty ())
    mark_async_event_handler (rs->remote_async_inferior_event_token);
}


inferior_event_target can lead to the remote target to be destroyed.  An "exit"
stop reply from the target can lead to it, but communication failure is another
one.

The reason why it is difficult to reproduce is that inferior_event_handler is
also called from remote_async_serial_handler, which doesn't have the same code
that dereferences the remote target.  So the bug can only trigger when
inferior_event_handler is called through remote_async_inferior_event_handler,
which likely happens less often than being called through
remote_async_serial_handler.

I did write this patch below to make it so inferior_event_handler is always
called through remote_async_inferior_event_handler, that automatically triggers
the bug in the simplest cases (the inferior exits with "target remote").  It
makes it so remote_async_serial_handler doesn't call
remote_async_inferior_event_handler anymore, but just marks the remote target's
async handler.

What I like from this patch is that there's now a single path from the remote
target to inferior_event_handler, so less variations to consider, more
determinism.  In the patch log, I talk about an exit event, but you can replace
that in your head by "communication failure" which leads to the remote target
being destroyed, which is can really happen at any time.


>From 5c358d0604e0ac3e2bd9aca02234cb20f1caea42 Mon Sep 17 00:00:00 2001
From: Simon Marchi <simon.marchi@polymtl.ca>
Date: Fri, 27 Nov 2020 13:32:55 -0500
Subject: [PATCH] gdb: make remote_async_serial_handler just mark remote
 target's async event

The purpose of this patch is to uncover an existing bug that is
difficult to trigger otherwise.  But it makes the remote target flow a
bit simpler to understand, which is in my opinion a welcome change.

The bug is a possible use-after-free 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 = (remote_target *) data;
      remote_state *rs = remote->get_remote_state ();

      ...
    }

These are the steps that lead to it:

1. inferior_event_handler is called, deep down that calls
   remote_target::wait, then infrun handles the returned event
2. the event returned by remote_target::wait is an exit event
3. remote_target::mourn_inferior gets called, which leads to the remote
   target getting unpushed and deleted, because its refcount drops to 0
4. back to remote_async_inferior_event_handler, the
   `remote->get_remote_state ()` line uses the remote target object
   after it was deleted.

The reason why we don't see this bug on master (at least not often) is
that inferior_event_handler is most often called through
remote_async_inferior_event_handler, as a reaction of the file
descriptor used to talk to the remote side being readable:

    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);
    }

I don't how exactly, but I am pretty sure (as I hit it in some rare
occasion) that some particular scheduling and event sequence can lead to
the exit event being handled through the inferior_event_handler call in
remote_async_inferior_event_token and to the bug described above.

Change-Id: If8d0daab97aa5338fe60d9e9b5a4ba3b5746eaea
---
 gdb/remote.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

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 = (remote_state *) context;
+
+  mark_async_event_handler (rs->remote_async_inferior_event_token);
 }

 static void
-- 
2.29.2

-- 
You are receiving this mail because:
You are on the CC list for the bug.

  parent reply	other threads:[~2020-11-29 14:53 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-14 14:50 [Bug gdb/26614] New: UNRESOLVED: gdb.multi/multi-target.exp: continue: non-stop=on: inferior 5 vries at gcc dot gnu.org
2020-09-14 14:52 ` [Bug gdb/26614] " vries at gcc dot gnu.org
2020-09-14 14:52 ` vries at gcc dot gnu.org
2020-09-14 14:56 ` vries at gcc dot gnu.org
2020-09-14 15:14 ` vries at gcc dot gnu.org
2020-09-15  9:41 ` vries at gcc dot gnu.org
2020-09-15  9:42 ` vries at gcc dot gnu.org
2020-09-15 10:14 ` [Bug remote/26614] AddressSanitizer: heap-use-after-free of extended_remote_target in remote_async_inferior_event_handler vries at gcc dot gnu.org
2020-09-25 23:58 ` palves at redhat dot com
2020-09-29 13:25 ` vries at gcc dot gnu.org
2020-11-29  9:19 ` vries at gcc dot gnu.org
2020-11-29 10:20 ` vries at gcc dot gnu.org
2020-11-29 11:24 ` vries at gcc dot gnu.org
2020-11-29 14:53 ` simark at simark dot ca [this message]
2020-11-29 15:15 ` simark at simark dot ca
2020-11-30 10:32 ` vries at gcc dot gnu.org
2020-11-30 11:02 ` vries at gcc dot gnu.org
2020-11-30 12:06 ` vries at gcc dot gnu.org
2020-11-30 14:11 ` simark at simark dot ca
2020-11-30 14:35 ` vries at gcc dot gnu.org
2020-11-30 14:57 ` simark at simark dot ca
2020-11-30 15:00 ` palves at redhat dot com
2020-11-30 15:10 ` simark at simark dot ca
2021-01-07 12:27 ` vries at gcc dot gnu.org
2021-01-07 12:34 ` vries at gcc dot gnu.org
2021-01-07 13:40 ` vries at gcc dot gnu.org
2021-01-07 16:10 ` vries at gcc dot gnu.org
2021-01-07 20:41 ` cvs-commit at gcc dot gnu.org
2021-01-31  6:16 ` brobecker at gnat dot com
2021-01-31  6:58 ` vries at gcc dot gnu.org
2021-01-31  7:16 ` vries at gcc dot gnu.org
2021-02-04 18:43 ` simark at simark dot ca
2021-06-27 17:52 ` ahmedsayeed1982 at yahoo dot com
2021-08-10 11:45 ` ucelsanicin at yahoo dot com
2021-08-18 13:42 ` jamesrogan59 at gmail dot com
2021-08-19  5:53 ` ucelsanicin at yahoo dot com
2021-09-02 11:00 ` donipah907 at mtlcz dot com
2021-09-02 11:18 ` mark at klomp dot org
2021-09-06  9:09 ` focixujo at livinginsurance dot co.uk
2021-09-10 19:40 ` mehmetgelisin at aol dot com
2021-09-14 17:29 ` johnb6174 at gmail dot com
2021-09-26 13:31 ` tes.vik1986 at gmail dot com
2021-10-09 11:00 ` gulsenenginar at aol dot com
2021-10-17 19:48 ` vmireskazki at gmail dot com
2021-10-19  7:15 ` progonsaytu at gmail dot com
2021-10-23 13:46 ` fiteva5725 at bomoads dot com
2021-10-24 10:03 ` glassmtech at ukr dot net
2021-11-06 21:12 ` paneki8601 at dukeoo dot com
2021-11-10 14:11 ` bryanmcsp at gmail dot com
2021-11-13 19:31 ` tesaso8237 at funboxcn dot com
2021-11-16 11:05 ` mrsrvic at yahoo dot com
2021-11-16 19:04 ` xecana8007 at funboxcn dot com
2021-11-16 19:08 ` xecana8007 at funboxcn dot com
2021-11-16 19:12 ` xecana8007 at funboxcn dot com
2021-11-22  7:38 ` gexed96894 at keagenan dot com

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-26614-4717-qXUy64AaEj@http.sourceware.org/bugzilla/ \
    --to=sourceware-bugzilla@sourceware.org \
    --cc=gdb-prs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).