summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-06-01 19:29:15 -0700
committerAmit Pundir <amit.pundir@linaro.org>2018-12-10 23:46:31 +0530
commit9cf8a2391acf3dc06a22db13d1e3b2de1b4a44e3 (patch)
tree009dbe2d7268b399f522dde3f00955c85080c502 /kernel
parentceb1e1cda77af6804dbe9e53eae9793c39c03253 (diff)
UPSTREAM: seccomp: recheck the syscall after RET_TRACE
When RET_TRACE triggers, a tracer may change a syscall into something that should be filtered by seccomp. This re-runs seccomp after a trace event to make sure things continue to pass. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andy Lutomirski <luto@kernel.org> (cherry picked from commit ce6526e8afa4b6ad0ab134a4cc50c9c863319637) Bug: 119769499 Change-Id: Ib67732df3c2ac8c6b1de87e75f96aaed02f4627d Signed-off-by: Greg Hackmann <ghackmann@google.com> Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/seccomp.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 44af84e3bc75..49eafa463853 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -581,7 +581,8 @@ void secure_computing_strict(int this_syscall)
#else
#ifdef CONFIG_SECCOMP_FILTER
-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
+static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
+ const bool recheck_after_trace)
{
u32 filter_ret, action;
int data;
@@ -613,6 +614,10 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
goto skip;
case SECCOMP_RET_TRACE:
+ /* We've been put in this state by the ptracer already. */
+ if (recheck_after_trace)
+ return 0;
+
/* ENOSYS these calls if there is no tracer attached. */
if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
syscall_set_return_value(current,
@@ -636,6 +641,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
if (this_syscall < 0)
goto skip;
+ /*
+ * Recheck the syscall, since it may have changed. This
+ * intentionally uses a NULL struct seccomp_data to force
+ * a reload of all registers. This does not goto skip since
+ * a skip would have already been reported.
+ */
+ if (__seccomp_filter(this_syscall, NULL, true))
+ return -1;
+
return 0;
case SECCOMP_RET_ALLOW:
@@ -654,7 +668,8 @@ skip:
return -1;
}
#else
-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
+static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
+ const bool recheck_after_trace)
{
BUG();
}
@@ -677,7 +692,7 @@ int __secure_computing(const struct seccomp_data *sd)
__secure_computing_strict(this_syscall); /* may call do_exit */
return 0;
case SECCOMP_MODE_FILTER:
- return __seccomp_filter(this_syscall, sd);
+ return __seccomp_filter(this_syscall, sd, false);
default:
BUG();
}