Blame SOURCES/gdb-rhbz1186918-gdbserver-in-container-6of8.patch

2c2fa1
commit 015de6884f6fdebaffd4b7d4c7f14fb4d5fc0bb1
2c2fa1
Author: Daniel Colascione <dancol@dancol.org>
2c2fa1
Date:   Tue Nov 11 14:18:23 2014 +0000
2c2fa1
2c2fa1
    Warn users about mismatched PID namespaces
2c2fa1
    
2c2fa1
    Linux supports multiple "PID namespaces".  Processes in different PID
2c2fa1
    namespaces have different views of the system process list.  Sometimes,
2c2fa1
    a single process can appear in more than one PID namespace, but with a
2c2fa1
    different PID in each.  When GDB and its target are in different PID
2c2fa1
    namespaces, various features can break due to the mismatch between
2c2fa1
    what the target believes its PID to be and what GDB believes its PID
2c2fa1
    to be.  The most visible broken functionality is thread enumeration
2c2fa1
    silently failing.
2c2fa1
    
2c2fa1
    This patch explicitly warns users against trying to debug across PID
2c2fa1
    namespaces.
2c2fa1
    
2c2fa1
    The patch introduced no new failures in my test suite run on an x86_64
2c2fa1
    installation of Ubuntu 14.10.  It doesn't include a test: writing an
2c2fa1
    automated test that exercises this code would be very involved because
2c2fa1
    CLONE_NEWNS requires CAP_SYS_ADMIN; the easier way to reproduce the
2c2fa1
    problem is to start a new lxc container.
2c2fa1
    
2c2fa1
    gdb/
2c2fa1
    2014-11-11  Daniel Colascione  <dancol@dancol.org>
2c2fa1
    
2c2fa1
    	Warn about cross-PID-namespace debugging.
2c2fa1
    	* nat/linux-procfs.h (linux_proc_pid_get_ns): New prototype.
2c2fa1
    	* nat/linux-procfs.c (linux_proc_pid_get_ns): New function.
2c2fa1
    	* linux-thread-db.c (check_pid_namespace_match): New function.
2c2fa1
    	(thread_db_inferior_created): Call it.
2c2fa1
2c2fa1
### a/gdb/ChangeLog
2c2fa1
### b/gdb/ChangeLog
2c2fa1
## -1,3 +1,11 @@
2c2fa1
+2014-11-11  Daniel Colascione  <dancol@dancol.org>
2c2fa1
+
2c2fa1
+	Warn about cross-PID-namespace debugging.
2c2fa1
+	* nat/linux-procfs.h (linux_proc_pid_get_ns): New prototype.
2c2fa1
+	* nat/linux-procfs.c (linux_proc_pid_get_ns): New function.
2c2fa1
+	* linux-thread-db.c (check_pid_namespace_match): New function.
2c2fa1
+	(thread_db_inferior_created): Call it.
2c2fa1
+
2c2fa1
 2014-11-10  Doug Evans  <xdje42@gmail.com>
2c2fa1
 
2c2fa1
 	* symmisc.c (print_objfile_statistics): Remove trailing whitespace.
2c2fa1
Index: gdb-7.6.1/gdb/linux-thread-db.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/linux-thread-db.c	2016-03-17 20:43:34.001735230 +0100
2c2fa1
+++ gdb-7.6.1/gdb/linux-thread-db.c	2016-03-17 21:54:32.233661083 +0100
2c2fa1
@@ -1216,12 +1216,70 @@
2c2fa1
     check_for_thread_db ();
2c2fa1
 }
2c2fa1
 
2c2fa1
+// RHEL: gdb/nat/linux-procfs.h
2c2fa1
+
2c2fa1
+/* Return an opaque string identifying PID's NS namespace or NULL if
2c2fa1
+ * the information is unavailable.  The returned string must be
2c2fa1
+ * released with xfree.  */
2c2fa1
+
2c2fa1
+extern char *linux_proc_pid_get_ns (pid_t pid, const char *ns);
2c2fa1
+
2c2fa1
+// RHEL: gdb/nat/linux-procfs.c
2c2fa1
+
2c2fa1
+/* See linux-procfs.h declaration.  */
2c2fa1
+
2c2fa1
+char *
2c2fa1
+linux_proc_pid_get_ns (pid_t pid, const char *ns)
2c2fa1
+{
2c2fa1
+  char buf[100];
2c2fa1
+  char nsval[64];
2c2fa1
+  int ret;
2c2fa1
+  xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
2c2fa1
+  ret = readlink (buf, nsval, sizeof (nsval));
2c2fa1
+  if (0 < ret && ret < sizeof (nsval))
2c2fa1
+    {
2c2fa1
+      nsval[ret] = '\0';
2c2fa1
+      return xstrdup (nsval);
2c2fa1
+    }
2c2fa1
+
2c2fa1
+  return NULL;
2c2fa1
+}
2c2fa1
+
2c2fa1
+static void
2c2fa1
+check_pid_namespace_match (void)
2c2fa1
+{
2c2fa1
+  /* Check is only relevant for local targets targets.  */
2c2fa1
+  if (target_can_run (&current_target))
2c2fa1
+    {
2c2fa1
+      /* If the child is in a different PID namespace, its idea of its
2c2fa1
+	 PID will differ from our idea of its PID.  When we scan the
2c2fa1
+	 child's thread list, we'll mistakenly think it has no threads
2c2fa1
+	 since the thread PID fields won't match the PID we give to
2c2fa1
+	 libthread_db.  */
2c2fa1
+      char *our_pid_ns = linux_proc_pid_get_ns (getpid (), "pid");
2c2fa1
+      char *inferior_pid_ns = linux_proc_pid_get_ns (
2c2fa1
+	ptid_get_pid (inferior_ptid), "pid");
2c2fa1
+
2c2fa1
+      if (our_pid_ns != NULL && inferior_pid_ns != NULL
2c2fa1
+	  && strcmp (our_pid_ns, inferior_pid_ns) != 0)
2c2fa1
+	{
2c2fa1
+	  warning (_ ("Target and debugger are in different PID "
2c2fa1
+		      "namespaces; thread lists and other data are "
2c2fa1
+		      "likely unreliable"));
2c2fa1
+	}
2c2fa1
+
2c2fa1
+      xfree (our_pid_ns);
2c2fa1
+      xfree (inferior_pid_ns);
2c2fa1
+    }
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* This function is called via the inferior_created observer.
2c2fa1
    This handles the case of debugging statically linked executables.  */
2c2fa1
 
2c2fa1
 static void
2c2fa1
 thread_db_inferior_created (struct target_ops *target, int from_tty)
2c2fa1
 {
2c2fa1
+  check_pid_namespace_match ();
2c2fa1
   check_for_thread_db ();
2c2fa1
 }
2c2fa1