[3/3] debugging with yama: check for yama ptrace_scope

Message ID 047d7b1121b7dbb3190520d3ca0f@google.com
State New, archived
Headers

Commit Message

Doug Evans Sept. 28, 2015, 7:34 p.m. UTC
  Hi.

This patch augments the attach fail error text if ptrace_scope
is the problem.

Regression tested on amd64-linux.

2015-09-28  Doug Evans  <dje@google.com>

	* inf-ptrace.c (inf_ptrace_attach): Call throw_perror_with_name
	passing SYSCALL_FAILED_ERROR and errno.
	* linux-nat.c (linux_nat_attach): Rewrite attach fail error processing.
	* nat/linux-ptrace.c: #include <ctype.h>, "filestuff.h".
	(ptrace_scope_file): New static global.
	(linux_yama_ptrace_scope_is_on): New function.
	(linux_ptrace_attach_fail_reason): Make static.
	Prepend ", " to messages.  Add yama ptrace_scope check.
	(linux_ptrace_attach_fail_reason_string): Rewrite message construction.
	Add kernel.yama.ptrace_scope suggestion.
	* nat/linux-ptrace.h (linux_ptrace_attach_fail_reason): Delete.

     with (an errno).  The result is stored in a static buffer.  This
  

Comments

Pedro Alves Sept. 29, 2015, 11:20 a.m. UTC | #1
Hi Doug,

Thanks for doing this.

On 09/28/2015 08:34 PM, Doug Evans wrote:
> Hi.
> 
> This patch augments the attach fail error text if ptrace_scope
> is the problem.
> 
> Regression tested on amd64-linux.

LGTM, all 3 patches.

(IMHO, it'd be nice if the example you posted in 0/3 ended up
in the commit log too.)

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index c98de4a..7fbd8a3 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -197,7 +197,7 @@  inf_ptrace_attach (struct target_ops *ops, const char  
*args, int from_tty)
    errno = 0;
    ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
    if (errno != 0)
-    perror_with_name (("ptrace"));
+    throw_perror_with_name (SYSCALL_FAILED_ERROR, errno, _("ptrace"));
  #else
    error (_("This system does not support attaching to a process"));
  #endif
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 6423ecc..bdea141 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1280,23 +1280,18 @@  linux_nat_attach (struct target_ops *ops, const  
char *args, int from_tty)
    CATCH (ex, RETURN_MASK_ERROR)
      {
        pid_t pid = parse_pid_to_attach (args);
-      struct buffer buffer;
-      char *message, *buffer_s;
+      char *reason;

-      message = xstrdup (ex.message);
-      make_cleanup (xfree, message);
-
-      buffer_init (&buffer);
-      linux_ptrace_attach_fail_reason (pid, &buffer);
-
-      buffer_grow_str0 (&buffer, "");
-      buffer_s = buffer_finish (&buffer);
-      make_cleanup (xfree, buffer_s);
-
-      if (*buffer_s != '\0')
-	throw_error (ex.error, "warning: %s\n%s", buffer_s, message);
+      if (ex.error == SYSCALL_FAILED_ERROR)
+	{
+	  ptid = ptid_build (pid, pid, 0);
+	  reason = linux_ptrace_attach_fail_reason_string (ptid, ex.suberror);
+	  throw_error_with_suberror (ex.error, ex.suberror,
+				     "Cannot attach to process %ld: %s",
+				     (unsigned long) pid, reason);
+	}
        else
-	throw_error (ex.error, "%s", message);
+	throw_error (ex.error, "%s", ex.message);
      }
    END_CATCH

diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c
index 97331a4..deff050 100644
--- a/gdb/nat/linux-ptrace.c
+++ b/gdb/nat/linux-ptrace.c
@@ -17,37 +17,81 @@ 
     along with this program.  If not, see <http://www.gnu.org/licenses/>.   
*/

  #include "common-defs.h"
+#include <ctype.h>
  #include "linux-ptrace.h"
  #include "linux-procfs.h"
  #include "linux-waitpid.h"
  #include "buffer.h"
  #include "gdb_wait.h"
  #include "gdb_ptrace.h"
+#include "filestuff.h"

  /* Stores the ptrace options supported by the running kernel.
     A value of -1 means we did not check for features yet.  A value
     of 0 means there are no supported features.  */
  static int supported_ptrace_options = -1;

+/* The file containing the current setting of yama ptrace_scope.  */
+static const char ptrace_scope_file[]  
= "/proc/sys/kernel/yama/ptrace_scope";
+
+/* Return non-zero if yama ptrace_scope is on.  */
+
+static int
+linux_yama_ptrace_scope_is_on (void)
+{
+  FILE *f;
+  char buffer[100];
+  struct cleanup *cleanup;
+  int is_on = 0;
+
+  f = gdb_fopen_cloexec (ptrace_scope_file, "r");
+  if (f == NULL)
+    return 0;
+  cleanup = make_cleanup_fclose (f);
+
+  if (fgets (buffer, sizeof (buffer), f) != NULL)
+    {
+      char *p;
+      long l;
+
+      l = strtoul (buffer, &p, 10);
+      if (*buffer != '\0' && (*p == '\0' || isspace (*p)))
+	is_on = l != 0;
+    }
+
+  do_cleanups (cleanup);
+  return is_on;
+}
+
  /* Find all possible reasons we could fail to attach PID and append
     these as strings to the already initialized BUFFER.  '\0'
-   termination of BUFFER must be done by the caller.  */
+   termination of BUFFER must be done by the caller.
+   ERR is the errno value of the failure.  */

-void
-linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer)
+static void
+linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer, int err)
  {
    pid_t tracerpid;

    tracerpid = linux_proc_get_tracerpid_nowarn (pid);
    if (tracerpid > 0)
-    buffer_xml_printf (buffer, _("process %d is already traced "
+    buffer_xml_printf (buffer, _(", process %d is already traced "
  				 "by process %d"),
  		       (int) pid, (int) tracerpid);

    if (linux_proc_pid_is_zombie_nowarn (pid))
-    buffer_xml_printf (buffer, _("process %d is a zombie "
+    buffer_xml_printf (buffer, _(", process %d is a zombie "
  				 "- the process has already terminated"),
  		       (int) pid);
+  if (err == EPERM && linux_yama_ptrace_scope_is_on ())
+    {
+      buffer_xml_printf (buffer, _("\n\
+It looks like yama ptrace_scope is enabled.\n\
+See %s.\n\
+You can lift the restriction with:\n\
+sudo sysctl -w kernel.yama.ptrace_scope=0"),
+			 ptrace_scope_file);
+    }
  }

  /* See linux-ptrace.h.  */
@@ -57,22 +101,15 @@  linux_ptrace_attach_fail_reason_string (ptid_t ptid,  
int err)
  {
    static char *reason_string;
    struct buffer buffer;
-  char *warnings;
    long lwpid = ptid_get_lwp (ptid);

    xfree (reason_string);

    buffer_init (&buffer);
-  linux_ptrace_attach_fail_reason (lwpid, &buffer);
+  buffer_xml_printf (&buffer, "%s (%d)", safe_strerror (err), err);
+  linux_ptrace_attach_fail_reason (lwpid, &buffer, err);
    buffer_grow_str0 (&buffer, "");
-  warnings = buffer_finish (&buffer);
-  if (warnings[0] != '\0')
-    reason_string = xstrprintf ("%s (%d), %s",
-				safe_strerror (err), err, warnings);
-  else
-    reason_string = xstrprintf ("%s (%d)",
-				safe_strerror (err), err);
-  xfree (warnings);
+  reason_string = buffer_finish (&buffer);
    return reason_string;
  }

diff --git a/gdb/nat/linux-ptrace.h b/gdb/nat/linux-ptrace.h
index 1be38fe..3b5dbd6 100644
--- a/gdb/nat/linux-ptrace.h
+++ b/gdb/nat/linux-ptrace.h
@@ -154,8 +154,6 @@  struct buffer;
  # define TRAP_HWBKPT 4
  #endif

-extern void linux_ptrace_attach_fail_reason (pid_t pid, struct buffer  
*buffer);
-
  /* Find all possible reasons we could have failed to attach to PTID
     and return them as a string.  ERR is the error PTRACE_ATTACH failed