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

[patch] Fix crash on process name "(sd-pam)" (PR 16594)


Hi,

info os processes -fsanitize=address error
https://sourceware.org/bugzilla/show_bug.cgi?id=16594

info os processes
=================================================================
==5795== ERROR: AddressSanitizer: heap-use-after-free on address
0x600600214974 at pc 0x757a92 bp 0x7fff95dd9f00 sp 0x7fff95dd9ef0
READ of size 4 at 0x600600214974 thread T0
    #0 0x757a91 in get_cores_used_by_process (.../gdb/gdb+0x757a91)

At least Fedora 20 has process(es):
 6678 ?        Ss     0:00 /usr/lib/systemd/systemd --user
 6680 ?        S      0:00  \_ (sd-pam)

and GDB "info os processes" crashes on it as /proc/6680/stat contains:

6680 ((sd-pam)) S 6678 6678 6678 0 -1 1077961024 33 0 0 0 0 0 0 0 20 0 1 0 18568 73768960 120 18446744073709551615 1 1 0 0 0 0 0 4096 0 18446744073709551615 0 0 17 6 0 0 0 0 0 0 0 0 0 0 0 0 0

and GDB fails to find the proper end of the process name "((sd-pam))".
Therefore it reads core number off-by-one (it reads 17 instead of 6) and
overruns the array.

(1) Make the process name parsing more foolproof.

(2) Do not trust the parsed number from /proc/PID/stat and verify it against
    the array size.


Thanks,
Jan
gdb/
2014-02-17  Jan Kratochvil  <jan.kratochvil@redhat.com>

	PR gdb/16594
	* common/linux-osdata.c (linux_common_core_of_thread): Find the end of
	process name.
	(get_cores_used_by_process): New parameter num_cores, use it.
	(linux_xfer_osdata_processes): Pass num_cores to it.

diff --git a/gdb/common/linux-osdata.c b/gdb/common/linux-osdata.c
index 805850c..37d78a0 100644
--- a/gdb/common/linux-osdata.c
+++ b/gdb/common/linux-osdata.c
@@ -98,10 +98,10 @@ linux_common_core_of_thread (ptid_t ptid)
 
   p = strchr (content, '(');
 
-  /* Skip ")".  */
+  /* Skip ")".  Handle also process names like "((sd-pam))".  */
   if (p != NULL)
     p = strchr (p, ')');
-  if (p != NULL)
+  while (p != NULL && *p != 0 && *p != ' ')
     p++;
 
   /* If the first field after program name has index 0, then core number is
@@ -258,11 +258,10 @@ get_process_owner (uid_t *owner, PID_T pid)
 }
 
 /* Find the CPU cores used by process PID and return them in CORES.
-   CORES points to an array of at least sysconf(_SC_NPROCESSOR_ONLN)
-   elements.  */
+   CORES points to an array of NUM_CORES elements.  */
 
 static int
-get_cores_used_by_process (PID_T pid, int *cores)
+get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
 {
   char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
   DIR *dir;
@@ -286,7 +285,7 @@ get_cores_used_by_process (PID_T pid, int *cores)
 	  core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
 							  (pid_t) tid, 0));
 
-	  if (core >= 0)
+	  if (core >= 0 && core < num_cores)
 	    {
 	      ++cores[core];
 	      ++task_count;
@@ -350,7 +349,7 @@ linux_xfer_osdata_processes (gdb_byte *readbuf,
 
 	      /* Find CPU cores used by the process.  */
 	      cores = (int *) xcalloc (num_cores, sizeof (int));
-	      task_count = get_cores_used_by_process (pid, cores);
+	      task_count = get_cores_used_by_process (pid, cores, num_cores);
 	      cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
 
 	      for (i = 0; i < num_cores && task_count > 0; ++i)

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