This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc 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]

GNU C Library master sources branch, master, updated. glibc-2.14-176-g2772459


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  2772459841f32f2d5866672145f533975ebec717 (commit)
      from  174baab3f9c3dfff4e16fd5b9eb2e5fb5c27db74 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2772459841f32f2d5866672145f533975ebec717

commit 2772459841f32f2d5866672145f533975ebec717
Author: Ulrich Drepper <drepper@gmail.com>
Date:   Wed Aug 17 09:41:23 2011 -0400

    Prevent possible race conditions by attaching pldd to all threads

diff --git a/ChangeLog b/ChangeLog
index 6dbab2e..ffb2ad3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-08-17  Ulrich Drepper  <drepper@gmail.com>
+
+	* elf/pldd.c (main): Attach to all threads in the process.
+	Rewrite /proc handling to use *at functions.
+
 2011-08-16  Ulrich Drepper  <drepper@gmail.com>
 
 	* elf/dl-open.c (_dl_show_scope): Take additional parameter which
diff --git a/elf/pldd.c b/elf/pldd.c
index 9fac19e..ef3621c 100644
--- a/elf/pldd.c
+++ b/elf/pldd.c
@@ -20,6 +20,8 @@
 
 #include <alloca.h>
 #include <argp.h>
+#include <assert.h>
+#include <dirent.h>
 #include <elf.h>
 #include <errno.h>
 #include <error.h>
@@ -83,7 +85,7 @@ static int memfd;
 static char *exe;
 
 /* Local functions.  */
-static int get_process_info (pid_t pid);
+static int get_process_info (int dfd, long int pid);
 
 
 int
@@ -101,33 +103,96 @@ main (int argc, char *argv[])
       return 1;
     }
 
+  assert (sizeof (pid_t) == sizeof (int)
+	  || sizeof (pid_t) == sizeof (long int));
   char *endp;
   errno = 0;
-  pid_t pid = strtoul (argv[remaining], &endp, 10);
-  if ((pid == ULONG_MAX && errno == ERANGE) || *endp != '\0')
+  long int pid = strtol (argv[remaining], &endp, 10);
+  if (pid < 0 || (pid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
+      || (sizeof (pid_t) < sizeof (pid) && pid > INT_MAX))
     error (EXIT_FAILURE, 0, gettext ("invalid process ID '%s'"),
 	   argv[remaining]);
 
   /* Determine the program name.  */
-  char buf[11 + 3 * sizeof (pid)];
-  snprintf (buf, sizeof (buf), "/proc/%lu/exe", (unsigned long int) pid);
+  char buf[7 + 3 * sizeof (pid)];
+  snprintf (buf, sizeof (buf), "/proc/%lu", pid);
+  int dfd = open (buf, O_RDONLY | O_DIRECTORY);
+  if (dfd == -1)
+    error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
+
   size_t exesize = 1024;
+#ifdef PATH_MAX
+  exesize = PATH_MAX;
+#endif
   exe = alloca (exesize);
   ssize_t nexe;
-  while ((nexe = readlink (buf, exe, exesize)) == exesize)
+  while ((nexe = readlinkat (dfd, "exe", exe, exesize)) == exesize)
     extend_alloca (exe, exesize, 2 * exesize);
   if (nexe == -1)
     exe = (char *) "<program name undetermined>";
   else
     exe[nexe] = '\0';
 
-  if (ptrace (PTRACE_ATTACH, pid, NULL, NULL) != 0)
-    error (EXIT_FAILURE, errno, gettext ("cannot attach to process %lu"),
-	   (unsigned long int) pid);
+  /* Stop all threads since otherwise the list of loaded modules might
+     change while we are reading it.  */
+  struct thread_list
+  {
+    pid_t tid;
+    struct thread_list *next;
+  } *thread_list = NULL;
+
+  int taskfd = openat (dfd, "task", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+  if (taskfd == 1)
+    error (EXIT_FAILURE, errno, gettext ("cannot open %s/task"), buf);
+  DIR *dir = fdopendir (taskfd);
+  if (dir == NULL)
+    error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
+	   buf);
+
+  struct dirent64 *d;
+  while ((d = readdir64 (dir)) != NULL)
+    {
+      if (! isdigit (d->d_name[0]))
+	continue;
+
+      errno = 0;
+      long int tid = strtol (d->d_name, &endp, 10);
+      if (tid < 0 || (tid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
+	  || (sizeof (pid_t) < sizeof (pid) && tid > INT_MAX))
+	error (EXIT_FAILURE, 0, gettext ("invalid thread ID '%s'"),
+	       d->d_name);
+
+      if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
+	{
+	  /* There might be a race between reading the directory and
+	     threads terminating.  Ignore errors attaching to unknown
+	     threads unless this is the main thread.  */
+	  if (errno == ESRCH && tid != pid)
+	    continue;
+
+	  error (EXIT_FAILURE, errno, gettext ("cannot attach to process %lu"),
+		 tid);
+	}
+
+      struct thread_list *newp = alloca (sizeof (*newp));
+      newp->tid = tid;
+      newp->next = thread_list;
+      thread_list = newp;
+    }
+
+  closedir (dir);
 
-  int status = get_process_info (pid);
+  int status = get_process_info (dfd, pid);
+
+  assert (thread_list != NULL);
+  do
+    {
+      ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
+      thread_list = thread_list->next;
+    }
+  while (thread_list != NULL);
 
-  ptrace (PTRACE_DETACH, pid, NULL, NULL);
+  close (dfd);
 
   return status;
 }
@@ -167,22 +232,18 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 
 
 static int
-get_process_info (pid_t pid)
+get_process_info (int dfd, long int pid)
 {
-  char buf[12 + 3 * sizeof (pid)];
-
-  snprintf (buf, sizeof (buf), "/proc/%lu/mem", (unsigned long int) pid);
-  memfd = open (buf, O_RDONLY);
+  memfd = openat (dfd, "mem", O_RDONLY);
   if (memfd == -1)
     goto no_info;
 
-  snprintf (buf, sizeof (buf), "/proc/%lu/exe", (unsigned long int) pid);
-  int fd = open (buf, O_RDONLY);
+  int fd = openat (dfd, "exe", O_RDONLY);
   if (fd == -1)
     {
     no_info:
       error (0, errno, gettext ("cannot get information about process %lu"),
-	     (unsigned long int) pid);
+	     pid);
       return EXIT_FAILURE;
     }
 
@@ -198,13 +259,11 @@ get_process_info (pid_t pid)
 
   if (memcmp (uehdr.ehdr32.e_ident, ELFMAG, SELFMAG) != 0)
     {
-      error (0, 0, gettext ("process %lu is no ELF program"),
-	     (unsigned long int) pid);
+      error (0, 0, gettext ("process %lu is no ELF program"), pid);
       return EXIT_FAILURE;
     }
 
-  snprintf (buf, sizeof (buf), "/proc/%lu/auxv", (unsigned long int) pid);
-  fd = open (buf, O_RDONLY);
+  fd = openat (dfd, "auxv", O_RDONLY);
   if (fd == -1)
     goto no_info;
 
@@ -227,8 +286,14 @@ get_process_info (pid_t pid)
 
   close (fd);
 
+  int retval;
   if (uehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32)
-    return find_maps32 (pid, &uehdr.ehdr32, auxv, auxv_size);
+    retval = find_maps32 (pid, &uehdr.ehdr32, auxv, auxv_size);
   else
-    return find_maps64 (pid, &uehdr.ehdr64, auxv, auxv_size);
+    retval = find_maps64 (pid, &uehdr.ehdr64, auxv, auxv_size);
+
+  free (auxv);
+  close (memfd);
+
+  return retval;
 }

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog  |    5 +++
 elf/pldd.c |  115 +++++++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 95 insertions(+), 25 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


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