Remove SECCOMP_MODE_DEAD and store this instead in a new field in struct seccomp. This means that mode can be used to strictly store the current mode which is exposed to userspace. --- include/linux/seccomp_types.h | 4 +++- kernel/seccomp.c | 19 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/linux/seccomp_types.h b/include/linux/seccomp_types.h index cf0a0355024f..67ab25d7540a 100644 --- a/include/linux/seccomp_types.h +++ b/include/linux/seccomp_types.h @@ -12,6 +12,7 @@ struct seccomp_filter; * * @mode: indicates one of the valid values above for controlled * system calls available to a process. + * @dead: indicates that the process should be killed as a result of seccomp * @filter_count: number of seccomp filters * @filter: must always point to a valid seccomp-filter or NULL as it is * accessed without locking during system call entry. @@ -20,7 +21,8 @@ struct seccomp_filter; * is no read locking. */ struct seccomp { - int mode; + unsigned int mode : 2; + unsigned int dead : 1; atomic_t filter_count; struct seccomp_filter *filter; }; diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 25f62867a16d..8f5903f72d54 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -31,9 +31,6 @@ #include -/* Not exposed in headers: strictly internal use only. */ -#define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1) - #ifdef CONFIG_SECCOMP_FILTER #include #include @@ -1079,7 +1076,7 @@ static void __secure_computing_strict(int this_syscall) #ifdef SECCOMP_DEBUG dump_stack(); #endif - current->seccomp.mode = SECCOMP_MODE_DEAD; + current->seccomp.dead = 1; seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true); do_exit(SIGKILL); } @@ -1355,7 +1352,7 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace) case SECCOMP_RET_KILL_THREAD: case SECCOMP_RET_KILL_PROCESS: default: - current->seccomp.mode = SECCOMP_MODE_DEAD; + current->seccomp.dead = 1; seccomp_log(this_syscall, SIGSYS, action, true); /* Dump core only if this is the last remaining thread. */ if (action != SECCOMP_RET_KILL_THREAD || @@ -1396,17 +1393,19 @@ int __secure_computing(void) this_syscall = syscall_get_nr(current, current_pt_regs()); + /* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ + if (unlikely(current->seccomp.dead)) { + WARN_ON_ONCE(1); + do_exit(SIGKILL); + return -1; + } + switch (mode) { case SECCOMP_MODE_STRICT: __secure_computing_strict(this_syscall); /* may call do_exit */ return 0; case SECCOMP_MODE_FILTER: return __seccomp_filter(this_syscall, false); - /* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ - case SECCOMP_MODE_DEAD: - WARN_ON_ONCE(1); - do_exit(SIGKILL); - return -1; default: BUG(); } -- 2.54.0