You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.2 KiB
123 lines
4.2 KiB
6 years ago
|
commit 015de6884f6fdebaffd4b7d4c7f14fb4d5fc0bb1
|
||
|
Author: Daniel Colascione <dancol@dancol.org>
|
||
|
Date: Tue Nov 11 14:18:23 2014 +0000
|
||
|
|
||
|
Warn users about mismatched PID namespaces
|
||
|
|
||
|
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.
|
||
|
|
||
|
### a/gdb/ChangeLog
|
||
|
### b/gdb/ChangeLog
|
||
|
## -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: gdb-7.6.1/gdb/linux-thread-db.c
|
||
|
===================================================================
|
||
|
--- gdb-7.6.1.orig/gdb/linux-thread-db.c 2016-03-17 20:43:34.001735230 +0100
|
||
|
+++ gdb-7.6.1/gdb/linux-thread-db.c 2016-03-17 21:54:32.233661083 +0100
|
||
|
@@ -1216,12 +1216,70 @@
|
||
|
check_for_thread_db ();
|
||
|
}
|
||
|
|
||
|
+// RHEL: gdb/nat/linux-procfs.h
|
||
|
+
|
||
|
+/* 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);
|
||
|
+
|
||
|
+// RHEL: gdb/nat/linux-procfs.c
|
||
|
+
|
||
|
+/* 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;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+check_pid_namespace_match (void)
|
||
|
+{
|
||
|
+ /* Check is only relevant for local targets targets. */
|
||
|
+ if (target_can_run (¤t_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 ();
|
||
|
}
|
||
|
|