|
|
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 (¤t_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 |
|