This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix use-after-free in gdbserver


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d105de22fc385da878e8db44c9503a7f30419322

commit d105de22fc385da878e8db44c9503a7f30419322
Author: Tom Tromey <tom@tromey.com>
Date:   Sun Jul 29 19:21:01 2018 -0600

    Fix use-after-free in gdbserver
    
    -fsanitize=address pointed out a use-after-free in gdbserver.  In
    particular, handle_detach could reference "process" after it was
    deleted by detach_inferior.  Avoiding this also necessitated changing
    target_ops::join to take a pid rather than a process_info*.
    
    Tested by the buildbot using a few of the gdbserver builders.
    
    gdb/gdbserver/ChangeLog
    2018-11-29  Tom Tromey  <tom@tromey.com>
    
    	* win32-low.c (win32_join): Take pid, not process.
    	* target.h (struct target_ops) <join>: Change argument type.
    	(join_inferior): Change argument name.
    	* spu-low.c (spu_join): Take pid, not process.
    	* server.c (handle_detach): Preserve pid before destroying
    	process.
    	* lynx-low.c (lynx_join): Take pid, not process.
    	* linux-low.c (linux_join): Take pid, not process.

Diff:
---
 gdb/gdbserver/ChangeLog   | 11 +++++++++++
 gdb/gdbserver/linux-low.c |  4 ++--
 gdb/gdbserver/lynx-low.c  |  2 +-
 gdb/gdbserver/server.c    | 10 +++++++---
 gdb/gdbserver/spu-low.c   |  4 ++--
 gdb/gdbserver/target.h    |  8 ++++----
 gdb/gdbserver/win32-low.c |  4 ++--
 7 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 91a62b6..ec4d72f 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,14 @@
+2018-11-29  Tom Tromey  <tom@tromey.com>
+
+	* win32-low.c (win32_join): Take pid, not process.
+	* target.h (struct target_ops) <join>: Change argument type.
+	(join_inferior): Change argument name.
+	* spu-low.c (spu_join): Take pid, not process.
+	* server.c (handle_detach): Preserve pid before destroying
+	process.
+	* lynx-low.c (lynx_join): Take pid, not process.
+	* linux-low.c (linux_join): Take pid, not process.
+
 2018-11-23  Alan Hayward  <alan.hayward@arm.com>
 
 	* linux-aarch64-low.c (aarch64_cannot_store_register): Remove.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 701f3e8..4d84927 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -1670,12 +1670,12 @@ linux_mourn (struct process_info *process)
 }
 
 static void
-linux_join (process_info *proc)
+linux_join (int pid)
 {
   int status, ret;
 
   do {
-    ret = my_waitpid (proc->pid, &status, 0);
+    ret = my_waitpid (pid, &status, 0);
     if (WIFEXITED (status) || WIFSIGNALED (status))
       break;
   } while (ret != -1 || errno != ECHILD);
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 6c5933b..3bf3588 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -562,7 +562,7 @@ lynx_mourn (struct process_info *proc)
 /* Implement the join target_ops method.  */
 
 static void
-lynx_join (process_info *proc)
+lynx_join (int pid)
 {
   /* The PTRACE_DETACH is sufficient to detach from the process.
      So no need to do anything extra.  */
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 4ec3548..a0be0d4 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -1255,11 +1255,15 @@ handle_detach (char *own_buf)
 
   fprintf (stderr, "Detaching from process %d\n", process->pid);
   stop_tracing ();
+
+  /* We'll need this after PROCESS has been destroyed.  */
+  int pid = process->pid;
+
   if (detach_inferior (process) != 0)
     write_enn (own_buf);
   else
     {
-      discard_queued_stop_replies (ptid_t (process->pid));
+      discard_queued_stop_replies (ptid_t (pid));
       write_ok (own_buf);
 
       if (extended_protocol || target_running ())
@@ -1269,7 +1273,7 @@ handle_detach (char *own_buf)
 	     and instead treat this like a normal program exit.  */
 	  cs.last_status.kind = TARGET_WAITKIND_EXITED;
 	  cs.last_status.value.integer = 0;
-	  cs.last_ptid = ptid_t (process->pid);
+	  cs.last_ptid = ptid_t (pid);
 
 	  current_thread = NULL;
 	}
@@ -1281,7 +1285,7 @@ handle_detach (char *own_buf)
 	  /* If we are attached, then we can exit.  Otherwise, we
 	     need to hang around doing nothing, until the child is
 	     gone.  */
-	  join_inferior (process);
+	  join_inferior (pid);
 	  exit (0);
 	}
     }
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index 83a31a2..239c212 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -362,12 +362,12 @@ spu_mourn (struct process_info *process)
 }
 
 static void
-spu_join (process_info *proc)
+spu_join (int pid)
 {
   int status, ret;
 
   do {
-    ret = waitpid (proc->pid, &status, 0);
+    ret = waitpid (pid, &status, 0);
     if (WIFEXITED (status) || WIFSIGNALED (status))
       break;
   } while (ret != -1 || errno != ECHILD);
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index fce54e0..6f810b6 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -103,9 +103,9 @@ struct target_ops
 
   void (*mourn) (struct process_info *proc);
 
-  /* Wait for process PROC to exit.  */
+  /* Wait for process PID to exit.  */
 
-  void (*join) (process_info *proc);
+  void (*join) (int pid);
 
   /* Return 1 iff the thread with process ID PID is alive.  */
 
@@ -530,8 +530,8 @@ int kill_inferior (process_info *proc);
 #define store_inferior_registers(regcache, regno) \
   (*the_target->store_registers) (regcache, regno)
 
-#define join_inferior(proc) \
-  (*the_target->join) (proc)
+#define join_inferior(pid) \
+  (*the_target->join) (pid)
 
 #define target_supports_non_stop() \
   (the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0)
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 4aed58d..1ad71c7 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -873,9 +873,9 @@ win32_mourn (struct process_info *process)
 /* Implementation of target_ops::join.  */
 
 static void
-win32_join (process_info *proc)
+win32_join (int pid)
 {
-  HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, proc->pid);
+  HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
   if (h != NULL)
     {
       WaitForSingleObject (h, INFINITE);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]