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

Reply via email to