From cec06ec8282c538a40bde968ae36fe8356daffaa Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Tue, 10 Apr 2012 13:31:55 +0200
Subject: [PATCH] Warn when we fail to trace and SELinux boolean deny_ptrace
is in effect
---
ChangeLog | 7 ++++++
common.h | 4 +++
configure.ac | 5 ++++
proc.c | 1 +
sysdeps/linux-gnu/trace.c | 51 ++++++++++++++++++++++++++++++++++++--------
5 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/common.h b/common.h
index fa80076..2399e29 100644
--- a/common.h
+++ b/common.h
@@ -359,2 +359,6 @@ extern int linkmap_init(Process *, struct ltelf *);
+/* 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);
+
diff --git a/configure.ac b/configure.ac
index 7fcfda5..42d6158 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,11 @@ AC_CHECK_LIB([supc++], [__cxa_demangle], [
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 @@ open_pid(pid_t pid)
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
@@ -10,2 +10,7 @@
+#include "config.h"
+#ifdef HAVE_LIBSELINUX
+# include <selinux/selinux.h>
+#endif
+
/* If the system headers did not provide the constants, hard-code the normal
@@ -69,10 +75,32 @@ umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
#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 @@ I'll now try to proceed with tracing, but this shouldn't be happening.\n");
}
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
--
1.7.7.6