Changes: We don't have ns_common, so instead use pointer to namespace, and where needed also pass proc_ns_operations. We don't have cgroupns_operations so skip it's hunk. Initial patch doesn't add pidns_owner to pidns_for_children_operations, as there were no such thing in ms in a time of patch, do it.
https://jira.sw.ru/browse/PSBM-57362 ms commit bcac25a58bfc ("kernel: add a helper to get an owning user namespace for a namespace") Return -EPERM if an owning user namespace is outside of a process current user namespace. v2: In a first version ns_get_owner returned ENOENT for init_user_ns. This special cases was removed from this version. There is nothing outside of init_user_ns, so we can return EPERM. v3: rename ns->get_owner() to ns->owner(). get_* usually means that it grabs a reference. Acked-by: Serge Hallyn <se...@hallyn.com> Signed-off-by: Andrei Vagin <ava...@openvz.org> Signed-off-by: Eric W. Biederman <ebied...@xmission.com> Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> --- fs/namespace.c | 7 +++++++ include/linux/proc_ns.h | 1 + include/linux/user_namespace.h | 9 +++++++++ ipc/namespace.c | 7 +++++++ kernel/pid_namespace.c | 8 ++++++++ kernel/user_namespace.c | 25 +++++++++++++++++++++++++ kernel/utsname.c | 7 +++++++ net/core/net_namespace.c | 7 +++++++ 8 files changed, 71 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index c2489dd2f520..46b521b8d16a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3537,6 +3537,12 @@ static unsigned int mntns_inum(void *ns) return mnt_ns->proc_inum; } +static struct user_namespace *mntns_owner(void *ns) +{ + struct mnt_namespace *mnt_ns = ns; + return mnt_ns->user_ns; +} + const struct proc_ns_operations mntns_operations = { .name = "mnt", .type = CLONE_NEWNS, @@ -3544,4 +3550,5 @@ const struct proc_ns_operations mntns_operations = { .put = mntns_put, .install = mntns_install, .inum = mntns_inum, + .owner = mntns_owner, }; diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h index 8deba57cbb45..3f71f8e1aa18 100644 --- a/include/linux/proc_ns.h +++ b/include/linux/proc_ns.h @@ -16,6 +16,7 @@ struct proc_ns_operations { void (*put)(void *ns); int (*install)(struct nsproxy *nsproxy, void *ns); unsigned int (*inum)(void *ns); + struct user_namespace *(*owner)(void *ns); }; struct proc_ns { diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index ba9e7ab12de4..35b0160ae4d9 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -27,6 +27,8 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ struct ucounts; +struct proc_ns_operations; + enum ucount_type { UCOUNT_USER_NAMESPACES, UCOUNT_PID_NAMESPACES, @@ -118,6 +120,8 @@ extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *); extern int proc_setgroups_show(struct seq_file *m, void *v); extern bool userns_may_setgroups(const struct user_namespace *ns); + +void *ns_get_owner(void *ns, const struct proc_ns_operations *ns_ops); #else static inline struct user_namespace *get_user_ns(struct user_namespace *ns) @@ -146,6 +150,11 @@ static inline bool userns_may_setgroups(const struct user_namespace *ns) { return true; } +static inline void *ns_get_owner(void *ns, + const struct proc_ns_operations *ns_ops) +{ + return ERR_PTR(-EPERM); +} #endif void update_mnt_policy(struct user_namespace *userns); diff --git a/ipc/namespace.c b/ipc/namespace.c index f4cc0ef2d8ac..d2eac5005be0 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -213,6 +213,12 @@ static unsigned int ipcns_inum(void *vp) return ns->proc_inum; } +static struct user_namespace *ipcns_owner(void *ns) +{ + struct ipc_namespace *ipc_ns = ns; + return ipc_ns->user_ns; +} + const struct proc_ns_operations ipcns_operations = { .name = "ipc", .type = CLONE_NEWIPC, @@ -220,4 +226,5 @@ const struct proc_ns_operations ipcns_operations = { .put = ipcns_put, .install = ipcns_install, .inum = ipcns_inum, + .owner = ipcns_owner, }; diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 3728139e7e54..1bab842a8e1e 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -420,6 +420,12 @@ static unsigned int pidns_inum(void *ns) return pid_ns->proc_inum; } +static struct user_namespace *pidns_owner(void *ns) +{ + struct pid_namespace *pid_ns = ns; + return pid_ns->user_ns; +} + const struct proc_ns_operations pidns_operations = { .name = "pid", .type = CLONE_NEWPID, @@ -427,6 +433,7 @@ const struct proc_ns_operations pidns_operations = { .put = pidns_put, .install = pidns_install, .inum = pidns_inum, + .owner = pidns_owner, }; const struct proc_ns_operations pidns_for_children_operations = { @@ -437,6 +444,7 @@ const struct proc_ns_operations pidns_for_children_operations = { .put = pidns_put, .install = pidns_install, .inum = pidns_inum, + .owner = pidns_owner, }; static __init int pid_namespaces_init(void) diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 69fb5c095966..9b145831e07c 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -1064,6 +1064,30 @@ static unsigned int userns_inum(void *ns) return user_ns->proc_inum; } +void *ns_get_owner(void *ns, const struct proc_ns_operations *ns_ops) +{ + struct user_namespace *my_user_ns = current_user_ns(); + struct user_namespace *owner, *p; + + /* See if the owner is in the current user namespace */ + owner = p = ns_ops->owner(ns); + for (;;) { + if (!p) + return ERR_PTR(-EPERM); + if (p == my_user_ns) + break; + p = p->parent; + } + + return get_user_ns(owner); +} + +static struct user_namespace *userns_owner(void *ns) +{ + struct user_namespace *user_ns = ns; + return user_ns->parent; +} + const struct proc_ns_operations userns_operations = { .name = "user", .type = CLONE_NEWUSER, @@ -1071,6 +1095,7 @@ const struct proc_ns_operations userns_operations = { .put = userns_put, .install = userns_install, .inum = userns_inum, + .owner = userns_owner, }; static __init int user_namespaces_init(void) diff --git a/kernel/utsname.c b/kernel/utsname.c index ec7adcdca386..1414b9e57822 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c @@ -184,6 +184,12 @@ static unsigned int utsns_inum(void *vp) return ns->proc_inum; } +static struct user_namespace *utsns_owner(void *ns) +{ + struct uts_namespace *uts_ns = ns; + return uts_ns->user_ns; +} + const struct proc_ns_operations utsns_operations = { .name = "uts", .type = CLONE_NEWUTS, @@ -191,4 +197,5 @@ const struct proc_ns_operations utsns_operations = { .put = utsns_put, .install = utsns_install, .inum = utsns_inum, + .owner = utsns_owner, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6602c292743d..757d7b5f2ae3 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -1060,6 +1060,12 @@ static unsigned int netns_inum(void *ns) return net->proc_inum; } +static struct user_namespace *netns_owner(void *ns) +{ + struct net *net_ns = ns; + return net_ns->user_ns; +} + const struct proc_ns_operations netns_operations = { .name = "net", .type = CLONE_NEWNET, @@ -1067,5 +1073,6 @@ const struct proc_ns_operations netns_operations = { .put = netns_put, .install = netns_install, .inum = netns_inum, + .owner = netns_owner, }; #endif -- 2.13.6 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel