Andrey Vagin <avagin@xxxxxxxxxx> 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 -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html