Warn users about mismatched PID namespaces
authorDaniel Colascione <dancol@dancol.org>
Tue, 11 Nov 2014 14:18:23 +0000 (14:18 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 11 Nov 2014 14:18:23 +0000 (14:18 +0000)
Linux supports multiple "PID namespaces".  Processes in different PID
namespaces have different views of the system process list.  Sometimes,
a single process can appear in more than one PID namespace, but with a
different PID in each.  When GDB and its target are in different PID
namespaces, various features can break due to the mismatch between
what the target believes its PID to be and what GDB believes its PID
to be.  The most visible broken functionality is thread enumeration
silently failing.

This patch explicitly warns users against trying to debug across PID
namespaces.

The patch introduced no new failures in my test suite run on an x86_64
installation of Ubuntu 14.10.  It doesn't include a test: writing an
automated test that exercises this code would be very involved because
CLONE_NEWNS requires CAP_SYS_ADMIN; the easier way to reproduce the
problem is to start a new lxc container.

gdb/
2014-11-11  Daniel Colascione  <dancol@dancol.org>

Warn about cross-PID-namespace debugging.
* nat/linux-procfs.h (linux_proc_pid_get_ns): New prototype.
* nat/linux-procfs.c (linux_proc_pid_get_ns): New function.
* linux-thread-db.c (check_pid_namespace_match): New function.
(thread_db_inferior_created): Call it.

gdb/ChangeLog
gdb/linux-thread-db.c
gdb/nat/linux-procfs.c
gdb/nat/linux-procfs.h

index 6a9b66014fc69ca6267729b824be04048c7adf92..10321fde8db992a373eb9cb820a2097b7fa5e745 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-11  Daniel Colascione  <dancol@dancol.org>
+
+       Warn about cross-PID-namespace debugging.
+       * nat/linux-procfs.h (linux_proc_pid_get_ns): New prototype.
+       * nat/linux-procfs.c (linux_proc_pid_get_ns): New function.
+       * linux-thread-db.c (check_pid_namespace_match): New function.
+       (thread_db_inferior_created): Call it.
+
 2014-11-10  Doug Evans  <xdje42@gmail.com>
 
        * symmisc.c (print_objfile_statistics): Remove trailing whitespace.
index 352fac1091323d32bdc2c47cb9127907f32aba3c..c49b5674c4fd3adbb28a86fb99905cd9eb71c0d9 100644 (file)
@@ -1217,12 +1217,41 @@ thread_db_new_objfile (struct objfile *objfile)
     check_for_thread_db ();
 }
 
+static void
+check_pid_namespace_match (void)
+{
+  /* Check is only relevant for local targets targets.  */
+  if (target_can_run (&current_target))
+    {
+      /* If the child is in a different PID namespace, its idea of its
+        PID will differ from our idea of its PID.  When we scan the
+        child's thread list, we'll mistakenly think it has no threads
+        since the thread PID fields won't match the PID we give to
+        libthread_db.  */
+      char *our_pid_ns = linux_proc_pid_get_ns (getpid (), "pid");
+      char *inferior_pid_ns = linux_proc_pid_get_ns (
+       ptid_get_pid (inferior_ptid), "pid");
+
+      if (our_pid_ns != NULL && inferior_pid_ns != NULL
+         && strcmp (our_pid_ns, inferior_pid_ns) != 0)
+       {
+         warning (_ ("Target and debugger are in different PID "
+                     "namespaces; thread lists and other data are "
+                     "likely unreliable"));
+       }
+
+      xfree (our_pid_ns);
+      xfree (inferior_pid_ns);
+    }
+}
+
 /* This function is called via the inferior_created observer.
    This handles the case of debugging statically linked executables.  */
 
 static void
 thread_db_inferior_created (struct target_ops *target, int from_tty)
 {
+  check_pid_namespace_match ();
   check_for_thread_db ();
 }
 
index 30797da343834df232862a8b743fc1b4b8ed6339..00f2f0868ab2e7fd389bd59bd7e88b4a31bd29d9 100644 (file)
@@ -113,3 +113,22 @@ linux_proc_pid_is_zombie (pid_t pid)
 {
   return linux_proc_pid_has_state (pid, "Z (zombie)");
 }
+
+/* See linux-procfs.h declaration.  */
+
+char *
+linux_proc_pid_get_ns (pid_t pid, const char *ns)
+{
+  char buf[100];
+  char nsval[64];
+  int ret;
+  xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
+  ret = readlink (buf, nsval, sizeof (nsval));
+  if (0 < ret && ret < sizeof (nsval))
+    {
+      nsval[ret] = '\0';
+      return xstrdup (nsval);
+    }
+
+  return NULL;
+}
index d13fff75df571719a00989e1c0e510d077dea6ac..5e2a9eadcb08f511c2a39431eb0d358cdfc8f1cb 100644 (file)
@@ -40,4 +40,10 @@ extern int linux_proc_pid_is_stopped (pid_t pid);
 
 extern int linux_proc_pid_is_zombie (pid_t pid);
 
+/* Return an opaque string identifying PID's NS namespace or NULL if
+ * the information is unavailable.  The returned string must be
+ * released with xfree.  */
+
+extern char *linux_proc_pid_get_ns (pid_t pid, const char *ns);
+
 #endif /* COMMON_LINUX_PROCFS_H */
This page took 0.040389 seconds and 4 git commands to generate.