summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2012-02-03 01:22:44 +0000
committerDmitry V. Levin <ldv@altlinux.org>2012-02-03 01:22:44 +0000
commit8b1524c45f3ff3179ab98bafb866f19e6c632dcf (patch)
tree8b4ee70f242b22a6bce724a2c27c72e353ba9375
parent4f3df078b26899afe0f25d8651b06a5a5b5143e2 (diff)
downloadstrace-ldv/selinux.tar.gz
Enhance diagnostics when ptrace syscall is disabledldv/selinux
When ptrace(PTRACE_TRACEME, ...) is rejected by kernel with EACCES or EPERM, it usually means that there is a kernel security policy in effect that disallowes ptrace syscall. Let's help users by giving them a hint what is going on and how to deal with it. * configure.ac: Check for libselinux. * strace.c (show_security_policy_diagnostics): New function. (test_ptrace_setoptions_followfork, test_ptrace_setoptions_for_all): Use it.
-rw-r--r--configure.ac15
-rw-r--r--strace.c44
2 files changed, 53 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 789a997dd..c6c43c5fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -335,5 +335,20 @@ AC_CACHE_CHECK([for BLKGETSIZE64], [ac_cv_have_blkgetsize64],
AC_PATH_PROG([PERL], [perl])
+AC_ARG_WITH([selinux],
+ AS_HELP_STRING([--without-selinux],
+ [do not use SELinux library (default: use it if available)]),
+ [use_selinux=$withval],
+ [use_selinux=auto])
+
+if test "x$use_selinux" != xno; then
+ AC_CHECK_LIB([selinux], [is_selinux_enabled])
+ if test "x$use_selinux" = xyes; then
+ if test "x$ac_cv_lib_selinux_is_selinux_enabled" != xyes; then
+ AC_MSG_ERROR([SELinux library was not found or not usable])
+ fi
+ fi
+fi
+
AC_CONFIG_FILES([Makefile tests/Makefile])
AC_OUTPUT
diff --git a/strace.c b/strace.c
index 38c8518aa..cd2ef42b3 100644
--- a/strace.c
+++ b/strace.c
@@ -839,6 +839,32 @@ static void kill_save_errno(pid_t pid, int sig)
errno = saved_errno;
}
+#ifdef HAVE_LIBSELINUX
+# include <selinux/selinux.h>
+#endif
+
+static void show_security_policy_diagnostics(void) {
+ if (errno != EACCES && errno != EPERM)
+ return;
+
+#ifdef HAVE_LIBSELINUX
+ if ((is_selinux_enabled() > 0)
+ && (security_get_boolean_active("deny_ptrace") == 1)) {
+ fprintf(stderr,
+ "The SELinux boolean 'deny_ptrace' is enabled, preventing arbitrary processes\n"
+ "from snooping on each other (as a layered defense against intruders).\n"
+ "This protection can be disabled by running the following shell command as root:\n"
+ "\tsetsebool deny_ptrace 0\n"
+ "See https://fedoraproject.org/wiki/Features/SELinuxDenyPtrace for more information.\n");
+ return;
+ }
+#endif
+ fprintf(stderr,
+ "A kernel security policy that disallows ptrace syscalls, preventing arbitrary\n"
+ "processes from snooping on each other as a layered defense against intruders,\n"
+ "seems to be in effect.\n");
+}
+
/*
* Test whether the kernel support PTRACE_O_TRACECLONE et al options.
* First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
@@ -857,9 +883,12 @@ test_ptrace_setoptions_followfork(void)
perror_msg_and_die("fork");
if (pid == 0) {
pid = getpid();
- if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
- perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
- __func__);
+ if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
+ perror_msg("%s: PTRACE_TRACEME doesn't work",
+ __func__);
+ show_security_policy_diagnostics();
+ die();
+ }
kill(pid, SIGSTOP);
if (fork() < 0)
perror_msg_and_die("fork");
@@ -971,10 +1000,13 @@ test_ptrace_setoptions_for_all(void)
if (pid == 0) {
pid = getpid();
- if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
+ if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
+ perror_msg("%s: PTRACE_TRACEME doesn't work",
+ __func__);
+ show_security_policy_diagnostics();
/* Note: exits with exitcode 1 */
- perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
- __func__);
+ die();
+ }
kill(pid, SIGSTOP);
_exit(0); /* parent should see entry into this syscall */
}