Andrey Vagin <[email protected]> writes:

> Return -EPERM if an owning user namespace is outside of a process
> current user namespace.
>
> diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
> index a5bc78c..6382e5e 100644
> --- a/kernel/user_namespace.c
> +++ b/kernel/user_namespace.c
> @@ -994,6 +994,30 @@ static int userns_install(struct nsproxy *nsproxy, 
> struct ns_common *ns)
>       return commit_creds(cred);
>  }
>  
> +struct ns_common *ns_get_owner(struct ns_common *ns)
> +{
> +     const struct cred *cred = current_cred();
> +     struct user_namespace *user_ns, *p;
> +
> +     user_ns = p = ns->user_ns;
> +     if (user_ns == NULL) { /* ns is init_user_ns */
> +             /* Unprivileged user should not know that it's init_user_ns. */
> +             if (capable(CAP_SYS_ADMIN))
> +                     return ERR_PTR(-ENOENT);
> +             return ERR_PTR(-EPERM);
> +     }

This permission check is not what I meant to request.  This does not
handle nested user namespaces.

> +     for (;;) {
> +             if (p == cred->user_ns)
> +                     break;
> +             if (p == &init_user_ns)
> +                     return ERR_PTR(-EPERM);
> +             p = p->parent;
> +     }
> +

The permission check really needs to be down here. And be:

        if (!ns_capable(user_ns, CAP_SYS_ADMIN))
                return ERR_PTR(-EPERM).

That cleanly and easily handles more than a depth of a single user
namespace.

> +     return &get_user_ns(user_ns)->ns;
> +}
> +
>  const struct proc_ns_operations userns_operations = {
>       .name           = "user",
>       .type           = CLONE_NEWUSER,


Eric

Reply via email to