Warn when we fail to trace and SELinux boolean deny_ptrace is in effect
diff --git a/ChangeLog b/ChangeLog
index c095263..6107a12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2012-04-10  Petr Machata  <pmachata@redhat.com>
+
+	* common.h (trace_fail_warning): New backend hook.
+	* sysdeps/linux-gnu/trace.c: Implement it.
+	* proc.c: Call it.
+	* configure.ac: Add support for libselinux.
+
 2012-02-07  Petr Machata  <pmachata@redhat.com>
 
 	* common.h (wait_for_proc): New interface.
diff --git a/common.h b/common.h
index fa80076..2399e29 100644
--- a/common.h
+++ b/common.h
@@ -359,6 +359,10 @@
 extern void arch_check_dbg(Process *proc);
 extern int task_kill (pid_t pid, int sig);
 
+/* Called when trace_me or primary trace_pid fail.  This may plug in
+ * any platform-specific knowledge of why it could be so.  */
+void trace_fail_warning(pid_t pid);
+
 
 extern struct ltelf main_lte;
 
diff --git a/configure.ac b/configure.ac
index 7fcfda5..42d6158 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,11 @@
 AC_SUBST(libsupcxx_LIBS)
 
 
+dnl Check security_get_boolean_active availability.
+AC_CHECK_HEADERS(selinux/selinux.h)
+AC_CHECK_LIB(selinux, security_get_boolean_active)
+
+
 # HAVE_LIBUNWIND
 AC_ARG_WITH(libunwind,
   AS_HELP_STRING([--with-libunwind], [Use libunwind frame unwinding support]),
diff --git a/proc.c b/proc.c
index 106b6a0..ded0c95 100644
--- a/proc.c
+++ b/proc.c
@@ -94,6 +94,7 @@
 	if (open_one_pid(pid)) {
 		fprintf(stderr, "Cannot attach to pid %u: %s\n",
 			pid, strerror(errno));
+		trace_fail_warning(pid);
 		return;
 	}
 
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index 67e1f93..82a4154 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -1,14 +1,20 @@
+#include "config.h"
+
+#include <asm/unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include "ptrace.h"
-#include <asm/unistd.h>
-#include <assert.h>
 
+#ifdef HAVE_LIBSELINUX
+# include <selinux/selinux.h>
+#endif
+
+#include "ptrace.h"
 #include "common.h"
 
 /* If the system headers did not provide the constants, hard-code the normal
@@ -69,10 +75,32 @@
 #endif
 
 void
-trace_me(void) {
+trace_fail_warning(pid_t pid)
+{
+	/* This was adapted from GDB.  */
+#ifdef HAVE_LIBSELINUX
+	static int checked = 0;
+	if (checked)
+		return;
+	checked = 1;
+
+	/* -1 is returned for errors, 0 if it has no effect, 1 if
+	 * PTRACE_ATTACH is forbidden.  */
+	if (security_get_boolean_active("deny_ptrace") == 1)
+		fprintf(stderr,
+"The SELinux boolean 'deny_ptrace' is enabled, which may prevent ltrace from\n"
+"tracing other processes.  You can disable this process attach protection by\n"
+"issuing 'setsebool deny_ptrace=0' in the superuser context.\n");
+#endif /* HAVE_LIBSELINUX */
+}
+
+void
+trace_me(void)
+{
 	debug(DEBUG_PROCESS, "trace_me: pid=%d", getpid());
 	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
 		perror("PTRACE_TRACEME");
+		trace_fail_warning(getpid());
 		exit(1);
 	}
 }
@@ -101,11 +129,14 @@
 }
 
 int
-trace_pid(pid_t pid) {
+trace_pid(pid_t pid)
+{
 	debug(DEBUG_PROCESS, "trace_pid: pid=%d", pid);
-	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
+	/* This shouldn't emit error messages, as there are legitimate
+	 * reasons that the PID can't be attached: like it may have
+	 * already ended.  */
+	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0)
 		return -1;
-	}
 
 	/* man ptrace: PTRACE_ATTACH attaches to the process specified
 	   in pid.  The child is sent a SIGSTOP, but will not