Patchwork Disable check for NUL bytes in /proc/pid/cmdline

login
register
mail settings
Submitter Vladimir Nikulichev
Date April 11, 2014, 2:28 p.m.
Message ID <web-7508899@mx2.tbricks.com>
Download mbox | patch
Permalink /patch/506/
State Under Review
Headers show

Comments

Vladimir Nikulichev - April 11, 2014, 2:28 p.m.
When I execute gcore on a process, it prints warning that 
/proc/pid/cmdline
contains null characters:

$ gcore 18706
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x00007fa23be3c5c3 in __select_nocancel () from /lib64/libc.so.6
warning: target file /proc/18706/cmdline contained unexpected null 
characters
Saved corefile core.18706

There's nothing wrong, null characters separate command line arguments 
from
each other. This fix disables the check when reading cmdline.

gdb:

2014-04-10  Vladimir Nikulichev  <nvs@tbricks.com>

	* target.h (target_fileio_read_stralloc): Add
	'check_null' argument.
	* target.c (target_fileio_read_stralloc): Make
	check for NULs optional.
	* linux-tdep.c (linux_info_proc, linux_fill_prpsinfo):
	Disable check for NULs in /proc/pid/cmdline.

---

  /* Tracepoint-related operations.  */
Sergio Durigan Junior - April 11, 2014, 4:36 p.m.
On Friday, April 11 2014, Vladimir Nikulichev wrote:

> When I execute gcore on a process, it prints warning that
> /proc/pid/cmdline
> contains null characters:
>
> $ gcore 18706
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
> 0x00007fa23be3c5c3 in __select_nocancel () from /lib64/libc.so.6
> warning: target file /proc/18706/cmdline contained unexpected null
> characters
> Saved corefile core.18706
>
> There's nothing wrong, null characters separate command line arguments
> from
> each other. This fix disables the check when reading cmdline.

Thanks for the patch.

> index 1b48f79..e6f9c3c 100644
> --- a/gdb/target.c
> +++ b/gdb/target.c
> @@ -2895,7 +2895,7 @@ target_fileio_read_alloc (const char *filename,
> gdb_byte **buf_p)
>     if the result contains any embedded NUL bytes.  */
>
>  char *
> -target_fileio_read_stralloc (const char *filename)
> +target_fileio_read_stralloc (const char *filename, int check_null)
>  {

Shouldn't this argument be named "check_nul", since we are talking about
the NUL byte?

> diff --git a/gdb/target.h b/gdb/target.h
> index d7c6c3d..2d11a99 100644
> --- a/gdb/target.h
> +++ b/gdb/target.h
> @@ -1890,7 +1890,8 @@ extern LONGEST target_fileio_read_alloc (const
> char *filename,
>     or the transfer is unsupported, NULL is returned.  Empty objects
>     are returned as allocated but empty strings.  A warning is issued
>     if the result contains any embedded NUL bytes.  */
> -extern char *target_fileio_read_stralloc (const char *filename);
> +extern char *target_fileio_read_stralloc (const char *filename,
> +					  int check_null);

The comment could be expanded to explain what "check_nul" does.

Thanks,
Pedro Alves - April 11, 2014, 6:18 p.m.
On 04/11/2014 03:28 PM, Vladimir Nikulichev wrote:
> When I execute gcore on a process, it prints warning that 
> /proc/pid/cmdline
> contains null characters:
> 
> $ gcore 18706
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
> 0x00007fa23be3c5c3 in __select_nocancel () from /lib64/libc.so.6
> warning: target file /proc/18706/cmdline contained unexpected null 
> characters
> Saved corefile core.18706
> 
> There's nothing wrong, null characters separate command line arguments 
> from
> each other. This fix disables the check when reading cmdline.

This also affects "info proc cmdline", which ignores all arguments
but the first.  Seems to me we should stop thinking of cmdline
as a single string at all, thus read it with
target_fileio_read_alloc as one block, and then "parsing" the
result, extracting/printing all arguments.

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 45a94a8..8da7244 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@ 
+2014-04-10  Vladimir Nikulichev  <nvs@tbricks.com>
+
+	* target.h (target_fileio_read_stralloc): Add
+	'check_null' argument.
+	* target.c (target_fileio_read_stralloc): Make
+	check for NULs optional.
+	* linux-tdep.c (linux_info_proc, linux_fill_prpsinfo):
+	Disable check for NULs in /proc/pid/cmdline.
+
  2014-04-10  Pedro Alves  <palves@redhat.com>

  	* breakpoint.c (single_step_breakpoints)
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index c10b8ee..4391e1a 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -351,7 +351,7 @@  linux_info_proc (struct gdbarch *gdbarch, char 
*args,
    if (cmdline_f)
      {
        xsnprintf (filename, sizeof filename, "/proc/%ld/cmdline", 
pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (filename, 0);
        if (data)
  	{
  	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -390,7 +390,7 @@  linux_info_proc (struct gdbarch *gdbarch, char 
*args,
    if (mappings_f)
      {
        xsnprintf (filename, sizeof filename, "/proc/%ld/maps", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (filename, 1);
        if (data)
  	{
  	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -451,7 +451,7 @@  linux_info_proc (struct gdbarch *gdbarch, char 
*args,
    if (status_f)
      {
        xsnprintf (filename, sizeof filename, "/proc/%ld/status", 
pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (filename, 1);
        if (data)
  	{
  	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -464,7 +464,7 @@  linux_info_proc (struct gdbarch *gdbarch, char 
*args,
    if (stat_f)
      {
        xsnprintf (filename, sizeof filename, "/proc/%ld/stat", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (filename, 1);
        if (data)
  	{
  	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -753,13 +753,13 @@  linux_find_memory_regions_full (struct gdbarch 
*gdbarch,

    xsnprintf (mapsfilename, sizeof mapsfilename,
  	     "/proc/%d/smaps", current_inferior ()->pid);
-  data = target_fileio_read_stralloc (mapsfilename);
+  data = target_fileio_read_stralloc (mapsfilename, 1);
    if (data == NULL)
      {
        /* Older Linux kernels did not support /proc/PID/smaps.  */
        xsnprintf (mapsfilename, sizeof mapsfilename,
  		 "/proc/%d/maps", current_inferior ()->pid);
-      data = target_fileio_read_stralloc (mapsfilename);
+      data = target_fileio_read_stralloc (mapsfilename, 1);
      }
    if (data)
      {
@@ -1273,7 +1273,7 @@  linux_fill_prpsinfo (struct 
elf_internal_linux_prpsinfo *p)
    /* Obtaining PID and filename.  */
    pid = ptid_get_pid (inferior_ptid);
    xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) 
pid);
-  fname = target_fileio_read_stralloc (filename);
+  fname = target_fileio_read_stralloc (filename, 0);

    if (fname == NULL || *fname == '\0')
      {
@@ -1306,7 +1306,7 @@  linux_fill_prpsinfo (struct 
elf_internal_linux_prpsinfo *p)
    p->pr_psargs[sizeof (p->pr_psargs) - 1] = '\0';

    xsnprintf (filename, sizeof (filename), "/proc/%d/stat", (int) 
pid);
-  proc_stat = target_fileio_read_stralloc (filename);
+  proc_stat = target_fileio_read_stralloc (filename, 1);
    make_cleanup (xfree, proc_stat);

    if (proc_stat == NULL || *proc_stat == '\0')
@@ -1387,7 +1387,7 @@  linux_fill_prpsinfo (struct 
elf_internal_linux_prpsinfo *p)
    /* Finally, obtaining the UID and GID.  For that, we read and 
parse the
       contents of the `/proc/PID/status' file.  */
    xsnprintf (filename, sizeof (filename), "/proc/%d/status", (int) 
pid);
-  proc_status = target_fileio_read_stralloc (filename);
+  proc_status = target_fileio_read_stralloc (filename, 1);
    make_cleanup (xfree, proc_status);

    if (proc_status == NULL || *proc_status == '\0')
diff --git a/gdb/target.c b/gdb/target.c
index 1b48f79..e6f9c3c 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2895,7 +2895,7 @@  target_fileio_read_alloc (const char *filename, 
gdb_byte **buf_p)
     if the result contains any embedded NUL bytes.  */

  char *
-target_fileio_read_stralloc (const char *filename)
+target_fileio_read_stralloc (const char *filename, int check_null)
  {
    gdb_byte *buffer;
    char *bufstr;
@@ -2912,6 +2912,9 @@  target_fileio_read_stralloc (const char 
*filename)

    bufstr[transferred] = 0;

+  if (!check_null)
+    return bufstr;
+
    /* Check for embedded NUL bytes; but allow trailing NULs.  */
    for (i = strlen (bufstr); i < transferred; i++)
      if (bufstr[i] != 0)
diff --git a/gdb/target.h b/gdb/target.h
index d7c6c3d..2d11a99 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1890,7 +1890,8 @@  extern LONGEST target_fileio_read_alloc (const 
char *filename,
     or the transfer is unsupported, NULL is returned.  Empty objects
     are returned as allocated but empty strings.  A warning is issued
     if the result contains any embedded NUL bytes.  */
-extern char *target_fileio_read_stralloc (const char *filename);
+extern char *target_fileio_read_stralloc (const char *filename,
+					  int check_null);