diff options
author | Kees Cook <keescook@chromium.org> | 2016-06-01 19:29:15 -0700 |
---|---|---|
committer | Amit Pundir <amit.pundir@linaro.org> | 2018-12-10 23:46:31 +0530 |
commit | 9cf8a2391acf3dc06a22db13d1e3b2de1b4a44e3 (patch) | |
tree | 009dbe2d7268b399f522dde3f00955c85080c502 /kernel | |
parent | ceb1e1cda77af6804dbe9e53eae9793c39c03253 (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.c | 21 |
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(); } |