Commit ce6526e8 authored by Kees Cook's avatar Kees Cook

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: default avatarKees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@kernel.org>
parent 8112c4f1
...@@ -556,7 +556,8 @@ void secure_computing_strict(int this_syscall) ...@@ -556,7 +556,8 @@ void secure_computing_strict(int this_syscall)
#else #else
#ifdef CONFIG_SECCOMP_FILTER #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; u32 filter_ret, action;
int data; int data;
...@@ -588,6 +589,10 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ...@@ -588,6 +589,10 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
goto skip; goto skip;
case SECCOMP_RET_TRACE: 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. */ /* ENOSYS these calls if there is no tracer attached. */
if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
syscall_set_return_value(current, syscall_set_return_value(current,
...@@ -611,6 +616,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ...@@ -611,6 +616,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
if (this_syscall < 0) if (this_syscall < 0)
goto skip; 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; return 0;
case SECCOMP_RET_ALLOW: case SECCOMP_RET_ALLOW:
...@@ -629,7 +643,8 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ...@@ -629,7 +643,8 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
return -1; return -1;
} }
#else #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(); BUG();
} }
...@@ -652,7 +667,7 @@ int __secure_computing(const struct seccomp_data *sd) ...@@ -652,7 +667,7 @@ int __secure_computing(const struct seccomp_data *sd)
__secure_computing_strict(this_syscall); /* may call do_exit */ __secure_computing_strict(this_syscall); /* may call do_exit */
return 0; return 0;
case SECCOMP_MODE_FILTER: case SECCOMP_MODE_FILTER:
return __seccomp_filter(this_syscall, sd); return __seccomp_filter(this_syscall, sd, false);
default: default:
BUG(); BUG();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment