From: YiFei Zhu <yifeifz2@xxxxxxxxxxxx> This is to make way for eBPF, so that this part of the code can be shared by both cBPF and eBPF code paths. Doing the privilege check after prepare_filter means that any filter issues the caller would get -EINVAL, even when it does not set no_new_privs or CAP_SYS_ADMIN. Signed-off-by: YiFei Zhu <yifeifz2@xxxxxxxxxxxx> --- kernel/seccomp.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 1e63db4dbd9a..6e5ac0d686a1 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -642,16 +642,6 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog) BUG_ON(INT_MAX / fprog->len < sizeof(struct sock_filter)); - /* - * Installing a seccomp filter requires that the task has - * CAP_SYS_ADMIN in its namespace or be running with no_new_privs. - * This avoids scenarios where unprivileged tasks can affect the - * behavior of privileged children. - */ - if (!task_no_new_privs(current) && - !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) - return ERR_PTR(-EACCES); - /* Allocate a new seccomp_filter */ sfilter = kzalloc(sizeof(*sfilter), GFP_KERNEL | __GFP_NOWARN); if (!sfilter) @@ -1805,6 +1795,22 @@ static long seccomp_set_mode_filter(unsigned int flags, if (IS_ERR(prepared)) return PTR_ERR(prepared); + /* + * Installing a seccomp filter requires that the task has + * CAP_SYS_ADMIN in its namespace or be running with no_new_privs. + * This avoids scenarios where unprivileged tasks can affect the + * behavior of privileged children. + * + * This is checked after filter preparation because the user + * will get an EINVAL if their filter is invalid prior to the + * EACCES. + */ + if (!task_no_new_privs(current) && + !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) { + ret = -EACCES; + goto out_free; + } + if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) { listener = get_unused_fd_flags(O_CLOEXEC); if (listener < 0) { -- 2.31.1