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>
This commit is contained in:
parent
c1e7c222ce
commit
0aa0a57dc4
1 changed files with 18 additions and 3 deletions
|
@ -581,7 +581,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;
|
||||||
|
@ -613,6 +614,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,
|
||||||
|
@ -636,6 +641,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:
|
||||||
|
@ -654,7 +668,8 @@ skip:
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
@ -677,7 +692,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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue