seccomp: split mode setting routines

Separates the two mode setting paths to make things more readable with
fewer #ifdefs within function bodies.

Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Andy Lutomirski <luto@amacapital.net>
This commit is contained in:
Kees Cook 2014-06-25 15:55:25 -07:00
parent 1f41b45041
commit 3b23dd1284
1 changed files with 48 additions and 23 deletions

View File

@ -489,48 +489,66 @@ long prctl_get_seccomp(void)
}
/**
* seccomp_set_mode: internal function for setting seccomp mode
* @seccomp_mode: requested mode to use
* @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
*
* This function may be called repeatedly with a @seccomp_mode of
* SECCOMP_MODE_FILTER to install additional filters. Every filter
* successfully installed will be evaluated (in reverse order) for each system
* call the task makes.
* seccomp_set_mode_strict: internal function for setting strict seccomp
*
* Once current->seccomp.mode is non-zero, it may not be changed.
*
* Returns 0 on success or -EINVAL on failure.
*/
static long seccomp_set_mode(unsigned long seccomp_mode, char __user *filter)
static long seccomp_set_mode_strict(void)
{
const unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
long ret = -EINVAL;
if (!seccomp_may_assign_mode(seccomp_mode))
goto out;
switch (seccomp_mode) {
case SECCOMP_MODE_STRICT:
ret = 0;
#ifdef TIF_NOTSC
disable_TSC();
disable_TSC();
#endif
break;
seccomp_assign_mode(seccomp_mode);
ret = 0;
out:
return ret;
}
#ifdef CONFIG_SECCOMP_FILTER
case SECCOMP_MODE_FILTER:
ret = seccomp_attach_user_filter(filter);
if (ret)
goto out;
break;
#endif
default:
/**
* seccomp_set_mode_filter: internal function for setting seccomp filter
* @filter: struct sock_fprog containing filter
*
* This function may be called repeatedly to install additional filters.
* Every filter successfully installed will be evaluated (in reverse order)
* for each system call the task makes.
*
* Once current->seccomp.mode is non-zero, it may not be changed.
*
* Returns 0 on success or -EINVAL on failure.
*/
static long seccomp_set_mode_filter(char __user *filter)
{
const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
long ret = -EINVAL;
if (!seccomp_may_assign_mode(seccomp_mode))
goto out;
ret = seccomp_attach_user_filter(filter);
if (ret)
goto out;
}
seccomp_assign_mode(seccomp_mode);
out:
return ret;
}
#else
static inline long seccomp_set_mode_filter(char __user *filter)
{
return -EINVAL;
}
#endif
/**
* prctl_set_seccomp: configures current->seccomp.mode
@ -541,5 +559,12 @@ out:
*/
long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
{
return seccomp_set_mode(seccomp_mode, filter);
switch (seccomp_mode) {
case SECCOMP_MODE_STRICT:
return seccomp_set_mode_strict();
case SECCOMP_MODE_FILTER:
return seccomp_set_mode_filter(filter);
default:
return -EINVAL;
}
}