Blame SOURCES/gdb-attach-fail-reasons-5of5.patch

2c2fa1
http://sourceware.org/ml/gdb-patches/2012-03/msg00171.html
2c2fa1
Subject: [patch 3/3] attach-fail-reasons: SELinux deny_ptrace
2c2fa1
2c2fa1
Hi,
2c2fa1
2c2fa1
and here is the last bit for new SELinux 'deny_ptrace':
2c2fa1
	https://bugzilla.redhat.com/show_bug.cgi?id=786878
2c2fa1
2c2fa1
As even PTRACE_TRACEME fails in such case it needs to install hook for even
2c2fa1
that event.
2c2fa1
2c2fa1
2c2fa1
Thanks,
2c2fa1
Jan
2c2fa1
2c2fa1
2c2fa1
gdb/
2c2fa1
2012-03-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
2c2fa1
2c2fa1
	* common/linux-ptrace.c [HAVE_SELINUX_SELINUX_H]: include
2c2fa1
	selinux/selinux.h.
2c2fa1
	(linux_ptrace_attach_warnings): Call linux_ptrace_create_warnings.
2c2fa1
	(linux_ptrace_create_warnings): New.
2c2fa1
	* common/linux-ptrace.h (linux_ptrace_create_warnings): New declaration.
2c2fa1
	* config.in: Regenerate.
2c2fa1
	* configure: Regenerate.
2c2fa1
	* configure.ac: Check selinux/selinux.h and the selinux library.
2c2fa1
	* inf-ptrace.c (inf_ptrace_me): Check the ptrace result.
2c2fa1
	* linux-nat.c (linux_nat_create_inferior): New variable ex.  Wrap
2c2fa1
	to_create_inferior into TRY_CATCH, call linux_ptrace_create_warnings.
2c2fa1
2c2fa1
gdb/gdbserver/
2c2fa1
	* config.in: Regenerate.
2c2fa1
	* configure: Regenerate.
2c2fa1
	* configure.ac: Check selinux/selinux.h and the selinux library.
2c2fa1
	* linux-low.c (linux_traceme): New function.
2c2fa1
	(linux_create_inferior, linux_tracefork_child): Call it instead of
2c2fa1
	direct ptrace.
2c2fa1
2c2fa1
Index: gdb-7.5.50.20130215/gdb/common/linux-ptrace.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/common/linux-ptrace.c	2013-01-08 20:38:51.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/common/linux-ptrace.c	2013-02-15 22:38:05.782456279 +0100
2c2fa1
@@ -29,6 +29,10 @@
2c2fa1
 #include "gdb_assert.h"
2c2fa1
 #include "gdb_wait.h"
2c2fa1
 
2c2fa1
+#ifdef HAVE_SELINUX_SELINUX_H
2c2fa1
+# include <selinux/selinux.h>
2c2fa1
+#endif /* HAVE_SELINUX_SELINUX_H */
2c2fa1
+
2c2fa1
 /* Find all possible reasons we could fail to attach PID and append these
2c2fa1
    newline terminated reason strings to initialized BUFFER.  '\0' termination
2c2fa1
    of BUFFER must be done by the caller.  */
2c2fa1
@@ -48,6 +52,8 @@ linux_ptrace_attach_warnings (pid_t pid,
2c2fa1
     buffer_xml_printf (buffer, _("warning: process %d is a zombie "
2c2fa1
 				 "- the process has already terminated\n"),
2c2fa1
 		       (int) pid);
2c2fa1
+
2c2fa1
+  linux_ptrace_create_warnings (buffer);
2c2fa1
 }
2c2fa1
 
2c2fa1
 #if defined __i386__ || defined __x86_64__
2c2fa1
@@ -243,3 +249,19 @@ linux_ptrace_init_warnings (void)
2c2fa1
 
2c2fa1
   linux_ptrace_test_ret_to_nx ();
2c2fa1
 }
2c2fa1
+
2c2fa1
+/* Print all possible reasons we could fail to create a traced process.  */
2c2fa1
+
2c2fa1
+void
2c2fa1
+linux_ptrace_create_warnings (struct buffer *buffer)
2c2fa1
+{
2c2fa1
+#ifdef HAVE_LIBSELINUX
2c2fa1
+  /* -1 is returned for errors, 0 if it has no effect, 1 if PTRACE_ATTACH is
2c2fa1
+     forbidden.  */
2c2fa1
+  if (security_get_boolean_active ("deny_ptrace") == 1)
2c2fa1
+    buffer_xml_printf (buffer,
2c2fa1
+		       _("the SELinux boolean 'deny_ptrace' is enabled, "
2c2fa1
+			 "you can disable this process attach protection by: "
2c2fa1
+			 "(gdb) shell sudo setsebool deny_ptrace=0"));
2c2fa1
+#endif /* HAVE_LIBSELINUX */
2c2fa1
+}
2c2fa1
Index: gdb-7.5.50.20130215/gdb/common/linux-ptrace.h
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/common/linux-ptrace.h	2013-01-01 07:32:54.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/common/linux-ptrace.h	2013-02-15 22:38:05.782456279 +0100
2c2fa1
@@ -69,5 +69,6 @@ struct buffer;
2c2fa1
 
2c2fa1
 extern void linux_ptrace_attach_warnings (pid_t pid, struct buffer *buffer);
2c2fa1
 extern void linux_ptrace_init_warnings (void);
2c2fa1
+extern void linux_ptrace_create_warnings (struct buffer *buffer);
2c2fa1
 
2c2fa1
 #endif /* COMMON_LINUX_PTRACE_H */
2c2fa1
Index: gdb-7.5.50.20130215/gdb/configure.ac
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/configure.ac	2013-02-15 22:37:57.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/configure.ac	2013-02-15 22:38:05.783456281 +0100
2c2fa1
@@ -2068,6 +2068,10 @@ then
2c2fa1
 	      [Define if you support the personality syscall.])
2c2fa1
 fi
2c2fa1
 
2c2fa1
+dnl Check security_get_boolean_active availability.
2c2fa1
+AC_CHECK_HEADERS(selinux/selinux.h)
2c2fa1
+AC_CHECK_LIB(selinux, security_get_boolean_active)
2c2fa1
+
2c2fa1
 dnl Handle optional features that can be enabled.
2c2fa1
 
2c2fa1
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
2c2fa1
Index: gdb-7.5.50.20130215/gdb/gdbserver/configure.ac
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/gdbserver/configure.ac	2013-01-01 07:33:00.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/gdbserver/configure.ac	2013-02-15 22:38:05.783456281 +0100
2c2fa1
@@ -451,6 +451,10 @@ if $want_ipa ; then
2c2fa1
    fi
2c2fa1
 fi
2c2fa1
 
2c2fa1
+dnl Check security_get_boolean_active availability.
2c2fa1
+AC_CHECK_HEADERS(selinux/selinux.h)
2c2fa1
+AC_CHECK_LIB(selinux, security_get_boolean_active)
2c2fa1
+
2c2fa1
 AC_SUBST(GDBSERVER_DEPFILES)
2c2fa1
 AC_SUBST(GDBSERVER_LIBS)
2c2fa1
 AC_SUBST(USE_THREAD_DB)
2c2fa1
Index: gdb-7.5.50.20130215/gdb/gdbserver/linux-low.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/gdbserver/linux-low.c	2013-02-04 18:47:00.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/gdbserver/linux-low.c	2013-02-15 22:39:54.256591069 +0100
2c2fa1
@@ -602,6 +602,29 @@ add_lwp (ptid_t ptid)
2c2fa1
   return lwp;
2c2fa1
 }
2c2fa1
 
2c2fa1
+/* Execute PTRACE_TRACEME with error checking.  */
2c2fa1
+
2c2fa1
+static void
2c2fa1
+linux_traceme (const char *program)
2c2fa1
+{
2c2fa1
+  int save_errno;
2c2fa1
+  struct buffer buffer;
2c2fa1
+
2c2fa1
+  errno = 0;
2c2fa1
+  if (ptrace (PTRACE_TRACEME, 0,
2c2fa1
+	      (PTRACE_ARG3_TYPE) 0, (PTRACE_ARG4_TYPE) 0) == 0)
2c2fa1
+    return;
2c2fa1
+
2c2fa1
+  save_errno = errno;
2c2fa1
+  buffer_init (&buffer);
2c2fa1
+  linux_ptrace_create_warnings (&buffer);
2c2fa1
+  buffer_grow_str0 (&buffer, "");
2c2fa1
+  fprintf (stderr, _("%sCannot trace created process %s: %s.\n"),
2c2fa1
+	   buffer_finish (&buffer), program, strerror (save_errno));
2c2fa1
+  fflush (stderr);
2c2fa1
+  _exit (0177);
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* Start an inferior process and returns its pid.
2c2fa1
    ALLARGS is a vector of program-name and args. */
2c2fa1
 
2c2fa1
@@ -642,7 +665,7 @@ linux_create_inferior (char *program, ch
2c2fa1
 
2c2fa1
   if (pid == 0)
2c2fa1
     {
2c2fa1
-      ptrace (PTRACE_TRACEME, 0, (PTRACE_ARG3_TYPE) 0, (PTRACE_ARG4_TYPE) 0);
2c2fa1
+      linux_traceme (program);
2c2fa1
 
2c2fa1
 #ifndef __ANDROID__ /* Bionic doesn't use SIGRTMIN the way glibc does.  */
2c2fa1
       signal (__SIGRTMIN + 1, SIG_DFL);
2c2fa1
@@ -4587,7 +4610,7 @@ linux_tracefork_grandchild (void *arg)
2c2fa1
 static int
2c2fa1
 linux_tracefork_child (void *arg)
2c2fa1
 {
2c2fa1
-  ptrace (PTRACE_TRACEME, 0, (PTRACE_ARG3_TYPE) 0, (PTRACE_ARG4_TYPE) 0);
2c2fa1
+  linux_traceme ("PTRACE_O_TRACEFORK test");
2c2fa1
   kill (getpid (), SIGSTOP);
2c2fa1
 
2c2fa1
 #if !(defined(__UCLIBC__) && defined(HAS_NOMMU))
2c2fa1
Index: gdb-7.5.50.20130215/gdb/inf-ptrace.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/inf-ptrace.c	2013-01-01 07:32:45.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/inf-ptrace.c	2013-02-15 22:38:05.786456289 +0100
2c2fa1
@@ -104,7 +104,15 @@ static void
2c2fa1
 inf_ptrace_me (void)
2c2fa1
 {
2c2fa1
   /* "Trace me, Dr. Memory!"  */
2c2fa1
+  errno = 0;
2c2fa1
   ptrace (PT_TRACE_ME, 0, (PTRACE_TYPE_ARG3)0, 0);
2c2fa1
+  if (errno != 0)
2c2fa1
+    {
2c2fa1
+      fprintf_unfiltered (gdb_stderr, _("Cannot create process: %s\n"),
2c2fa1
+			  safe_strerror (errno));
2c2fa1
+      gdb_flush (gdb_stderr);
2c2fa1
+      _exit (0177);
2c2fa1
+    }
2c2fa1
 }
2c2fa1
 
2c2fa1
 /* Start a new inferior Unix child process.  EXEC_FILE is the file to
2c2fa1
Index: gdb-7.5.50.20130215/gdb/linux-nat.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.5.50.20130215.orig/gdb/linux-nat.c	2013-02-15 22:34:44.000000000 +0100
2c2fa1
+++ gdb-7.5.50.20130215/gdb/linux-nat.c	2013-02-15 22:38:05.787456291 +0100
2c2fa1
@@ -1557,6 +1557,7 @@ linux_nat_create_inferior (struct target
2c2fa1
 #ifdef HAVE_PERSONALITY
2c2fa1
   int personality_orig = 0, personality_set = 0;
2c2fa1
 #endif /* HAVE_PERSONALITY */
2c2fa1
+  volatile struct gdb_exception ex;
2c2fa1
 
2c2fa1
   /* The fork_child mechanism is synchronous and calls target_wait, so
2c2fa1
      we have to mask the async mode.  */
2c2fa1
@@ -1581,7 +1582,10 @@ linux_nat_create_inferior (struct target
2c2fa1
   /* Make sure we report all signals during startup.  */
2c2fa1
   linux_nat_pass_signals (0, NULL);
2c2fa1
 
2c2fa1
-  linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
2c2fa1
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
2c2fa1
+    {
2c2fa1
+      linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
2c2fa1
+    }
2c2fa1
 
2c2fa1
 #ifdef HAVE_PERSONALITY
2c2fa1
   if (personality_set)
2c2fa1
@@ -1593,6 +1597,24 @@ linux_nat_create_inferior (struct target
2c2fa1
 		 safe_strerror (errno));
2c2fa1
     }
2c2fa1
 #endif /* HAVE_PERSONALITY */
2c2fa1
+
2c2fa1
+  if (ex.reason < 0)
2c2fa1
+    {
2c2fa1
+      struct buffer buffer;
2c2fa1
+      char *message, *buffer_s;
2c2fa1
+
2c2fa1
+      message = xstrdup (ex.message);
2c2fa1
+      make_cleanup (xfree, message);
2c2fa1
+
2c2fa1
+      buffer_init (&buffer);
2c2fa1
+      linux_ptrace_create_warnings (&buffer);
2c2fa1
+
2c2fa1
+      buffer_grow_str0 (&buffer, "");
2c2fa1
+      buffer_s = buffer_finish (&buffer);
2c2fa1
+      make_cleanup (xfree, buffer_s);
2c2fa1
+
2c2fa1
+      throw_error (ex.error, "%s%s", buffer_s, message);
2c2fa1
+    }
2c2fa1
 }
2c2fa1
 
2c2fa1
 static void