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_set_mode_strict: internal function for setting strict seccomp
* @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.
* *
* Once current->seccomp.mode is non-zero, it may not be changed. * Once current->seccomp.mode is non-zero, it may not be changed.
* *
* Returns 0 on success or -EINVAL on failure. * 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; long ret = -EINVAL;
if (!seccomp_may_assign_mode(seccomp_mode)) if (!seccomp_may_assign_mode(seccomp_mode))
goto out; goto out;
switch (seccomp_mode) {
case SECCOMP_MODE_STRICT:
ret = 0;
#ifdef TIF_NOTSC #ifdef TIF_NOTSC
disable_TSC(); disable_TSC();
#endif #endif
break; seccomp_assign_mode(seccomp_mode);
ret = 0;
out:
return ret;
}
#ifdef CONFIG_SECCOMP_FILTER #ifdef CONFIG_SECCOMP_FILTER
case SECCOMP_MODE_FILTER: /**
ret = seccomp_attach_user_filter(filter); * seccomp_set_mode_filter: internal function for setting seccomp filter
if (ret) * @filter: struct sock_fprog containing filter
goto out; *
break; * This function may be called repeatedly to install additional filters.
#endif * Every filter successfully installed will be evaluated (in reverse order)
default: * 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; goto out;
}
seccomp_assign_mode(seccomp_mode); seccomp_assign_mode(seccomp_mode);
out: out:
return ret; return ret;
} }
#else
static inline long seccomp_set_mode_filter(char __user *filter)
{
return -EINVAL;
}
#endif
/** /**
* prctl_set_seccomp: configures current->seccomp.mode * prctl_set_seccomp: configures current->seccomp.mode
@ -541,5 +559,12 @@ out:
*/ */
long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter) 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;
}
} }