194 lines
6.0 KiB
Diff
194 lines
6.0 KiB
Diff
From 25e8461cbe56a3f035df145d9d762b65aa3eedb7 Mon Sep 17 00:00:00 2001
|
|
From: Jorge Gomes <jorge@lip.pt>
|
|
Date: Mon, 13 Feb 2017 20:37:17 +0000
|
|
Subject: [PATCH] fix event.c for seccomp and ptrace
|
|
|
|
---
|
|
src/tracee/event.c | 129 ++++++++++++++++++++++++++++++++++++-----------------
|
|
1 file changed, 88 insertions(+), 41 deletions(-)
|
|
|
|
diff --git src/tracee/event.c src/tracee/event.c
|
|
index bafc3c5..64166f6 100644
|
|
--- a/src/tracee/event.c
|
|
+++ b/src/tracee/event.c
|
|
@@ -20,6 +20,7 @@
|
|
* 02110-1301 USA.
|
|
*/
|
|
|
|
+#include <stdio.h>
|
|
#include <sched.h> /* CLONE_*, */
|
|
#include <sys/types.h> /* pid_t, */
|
|
#include <sys/ptrace.h> /* ptrace(1), PTRACE_*, */
|
|
@@ -47,6 +48,7 @@
|
|
#include "attribute.h"
|
|
#include "compat.h"
|
|
|
|
+
|
|
/**
|
|
* Start @tracee->exe with the given @argv[]. This function
|
|
* returns -errno if an error occurred, otherwise 0.
|
|
@@ -205,6 +207,27 @@ static void print_talloc_hierarchy(int signum, siginfo_t *siginfo UNUSED, void *
|
|
static int last_exit_status = -1;
|
|
|
|
/**
|
|
+ * Check if kernel >= 4.8
|
|
+ */
|
|
+bool is_kernel_4_8(void) {
|
|
+ struct utsname utsname;
|
|
+ int status;
|
|
+ static bool version_48 = false;
|
|
+ static int major = 0;
|
|
+ static int minor = 0;
|
|
+ if (! major) {
|
|
+ status = uname(&utsname);
|
|
+ if (status < 0)
|
|
+ return false;
|
|
+ sscanf(utsname.release, "%d.%d", &major, &minor);
|
|
+ if (major >= 4)
|
|
+ if (minor >= 8)
|
|
+ version_48 = true;
|
|
+ }
|
|
+ return version_48;
|
|
+}
|
|
+
|
|
+/**
|
|
* Check if this instance of PRoot can *technically* handle @tracee.
|
|
*/
|
|
static void check_architecture(Tracee *tracee)
|
|
@@ -362,6 +385,7 @@ int event_loop()
|
|
int handle_tracee_event(Tracee *tracee, int tracee_status)
|
|
{
|
|
static bool seccomp_detected = false;
|
|
+ static bool seccomp_enabled = false;
|
|
pid_t pid = tracee->pid;
|
|
long status;
|
|
int signal;
|
|
@@ -432,6 +456,7 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
|
|
status = ptrace(PTRACE_SETOPTIONS, tracee->pid, NULL,
|
|
default_ptrace_options | PTRACE_O_TRACESECCOMP);
|
|
if (status < 0) {
|
|
+ seccomp_enabled = false;
|
|
/* ... otherwise use default options only. */
|
|
status = ptrace(PTRACE_SETOPTIONS, tracee->pid, NULL,
|
|
default_ptrace_options);
|
|
@@ -440,8 +465,71 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
+ else {
|
|
+ if (getenv("PROOT_NO_SECCOMP") == NULL)
|
|
+ seccomp_enabled = true;
|
|
+ }
|
|
}
|
|
/* Fall through. */
|
|
+ case SIGTRAP | PTRACE_EVENT_SECCOMP2 << 8:
|
|
+ case SIGTRAP | PTRACE_EVENT_SECCOMP << 8:
|
|
+
|
|
+ if (is_kernel_4_8()) {
|
|
+ if (seccomp_enabled) {
|
|
+ if (!seccomp_detected) {
|
|
+ VERBOSE(tracee, 1, "ptrace acceleration (seccomp mode 2) enabled");
|
|
+ tracee->seccomp = ENABLED;
|
|
+ seccomp_detected = true;
|
|
+ }
|
|
+
|
|
+ unsigned long flags = 0;
|
|
+ status = ptrace(PTRACE_GETEVENTMSG, tracee->pid, NULL, &flags);
|
|
+ if (status < 0)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (signal == (SIGTRAP | PTRACE_EVENT_SECCOMP2 << 8) ||
|
|
+ signal == (SIGTRAP | PTRACE_EVENT_SECCOMP << 8)) {
|
|
+ unsigned long flags = 0;
|
|
+
|
|
+ signal = 0;
|
|
+
|
|
+ if (!seccomp_detected) {
|
|
+ VERBOSE(tracee, 1, "ptrace acceleration (seccomp mode 2) enabled");
|
|
+ tracee->seccomp = ENABLED;
|
|
+ seccomp_detected = true;
|
|
+ }
|
|
+
|
|
+ /* Use the common ptrace flow if seccomp was
|
|
+ * explicitely disabled for this tracee. */
|
|
+ if (tracee->seccomp != ENABLED)
|
|
+ break;
|
|
+
|
|
+ status = ptrace(PTRACE_GETEVENTMSG, tracee->pid, NULL, &flags);
|
|
+ if (status < 0)
|
|
+ break;
|
|
+
|
|
+ /* Use the common ptrace flow when
|
|
+ * sysexit has to be handled. */
|
|
+ if ((flags & FILTER_SYSEXIT) != 0) {
|
|
+ tracee->restart_how = PTRACE_SYSCALL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Otherwise, handle the sysenter
|
|
+ * stage right now. */
|
|
+ tracee->restart_how = PTRACE_CONT;
|
|
+ translate_syscall(tracee);
|
|
+
|
|
+ /* This syscall has disabled seccomp, so move
|
|
+ * the ptrace flow back to the common path to
|
|
+ * ensure its sysexit will be handled. */
|
|
+ if (tracee->seccomp == DISABLING)
|
|
+ tracee->restart_how = PTRACE_SYSCALL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Fall through. */
|
|
case SIGTRAP | 0x80:
|
|
signal = 0;
|
|
|
|
@@ -490,47 +578,6 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
|
|
}
|
|
break;
|
|
|
|
- case SIGTRAP | PTRACE_EVENT_SECCOMP2 << 8:
|
|
- case SIGTRAP | PTRACE_EVENT_SECCOMP << 8: {
|
|
- unsigned long flags = 0;
|
|
-
|
|
- signal = 0;
|
|
-
|
|
- if (!seccomp_detected) {
|
|
- VERBOSE(tracee, 1, "ptrace acceleration (seccomp mode 2) enabled");
|
|
- tracee->seccomp = ENABLED;
|
|
- seccomp_detected = true;
|
|
- }
|
|
-
|
|
- /* Use the common ptrace flow if seccomp was
|
|
- * explicitely disabled for this tracee. */
|
|
- if (tracee->seccomp != ENABLED)
|
|
- break;
|
|
-
|
|
- status = ptrace(PTRACE_GETEVENTMSG, tracee->pid, NULL, &flags);
|
|
- if (status < 0)
|
|
- break;
|
|
-
|
|
- /* Use the common ptrace flow when
|
|
- * sysexit has to be handled. */
|
|
- if ((flags & FILTER_SYSEXIT) != 0) {
|
|
- tracee->restart_how = PTRACE_SYSCALL;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Otherwise, handle the sysenter
|
|
- * stage right now. */
|
|
- tracee->restart_how = PTRACE_CONT;
|
|
- translate_syscall(tracee);
|
|
-
|
|
- /* This syscall has disabled seccomp, so move
|
|
- * the ptrace flow back to the common path to
|
|
- * ensure its sysexit will be handled. */
|
|
- if (tracee->seccomp == DISABLING)
|
|
- tracee->restart_how = PTRACE_SYSCALL;
|
|
- break;
|
|
- }
|
|
-
|
|
case SIGTRAP | PTRACE_EVENT_VFORK << 8:
|
|
signal = 0;
|
|
(void) new_child(tracee, CLONE_VFORK);
|