userns: add a user namespace owner of ipc ns
authorSerge E. Hallyn <serge@hallyn.com>
Wed, 23 Mar 2011 23:43:23 +0000 (16:43 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Mar 2011 02:47:07 +0000 (19:47 -0700)
Changelog:
Feb 15: Don't set new ipc->user_ns if we didn't create a new
ipc_ns.
Feb 23: Move extern declaration to ipc_namespace.h, and group
fwd declarations at top.

Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Acked-by: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/ipc_namespace.h
ipc/msgutil.c
ipc/namespace.c
kernel/nsproxy.c

index 51952989ad426dd19deef978f68ea4f7b123ec5c..d3c32dcec62399055100ea3e8c3f54ee07329030 100644 (file)
@@ -15,6 +15,7 @@
 
 #define IPCNS_CALLBACK_PRI 0
 
+struct user_namespace;
 
 struct ipc_ids {
        int in_use;
@@ -56,6 +57,8 @@ struct ipc_namespace {
        unsigned int    mq_msg_max;      /* initialized to DFLT_MSGMAX */
        unsigned int    mq_msgsize_max;  /* initialized to DFLT_MSGSIZEMAX */
 
+       /* user_ns which owns the ipc ns */
+       struct user_namespace *user_ns;
 };
 
 extern struct ipc_namespace init_ipc_ns;
index f095ee26883333fcc69d7c32e907a8f1949e2f3f..8b5ce5d3f3ef3e4f468d5afc4175cd22518fc029 100644 (file)
@@ -32,6 +32,7 @@ struct ipc_namespace init_ipc_ns = {
        .mq_msg_max      = DFLT_MSGMAX,
        .mq_msgsize_max  = DFLT_MSGSIZEMAX,
 #endif
+       .user_ns = &init_user_ns,
 };
 
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
index a1094ff0befa2775c5e9023c44c1520ff813ad04..aa1889962693d72820fd337a76c60f3493a6dc74 100644 (file)
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/user_namespace.h>
 
 #include "util.h"
 
-static struct ipc_namespace *create_ipc_ns(void)
+static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns)
 {
        struct ipc_namespace *ns;
        int err;
@@ -43,6 +44,9 @@ static struct ipc_namespace *create_ipc_ns(void)
        ipcns_notify(IPCNS_CREATED);
        register_ipcns_notifier(ns);
 
+       ns->user_ns = old_ns->user_ns;
+       get_user_ns(ns->user_ns);
+
        return ns;
 }
 
@@ -50,7 +54,7 @@ struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
 {
        if (!(flags & CLONE_NEWIPC))
                return get_ipc_ns(ns);
-       return create_ipc_ns();
+       return create_ipc_ns(ns);
 }
 
 /*
@@ -105,6 +109,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
         * order to have a correct value when recomputing msgmni.
         */
        ipcns_notify(IPCNS_REMOVED);
+       put_user_ns(ns->user_ns);
 }
 
 /*
index b97fc9d04ddfe0994898941c8d7020c0558daeff..ac8a56e90bf811d3e72c18bec09a3584501f7769 100644 (file)
@@ -80,6 +80,11 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
                err = PTR_ERR(new_nsp->ipc_ns);
                goto out_ipc;
        }
+       if (new_nsp->ipc_ns != tsk->nsproxy->ipc_ns) {
+               put_user_ns(new_nsp->ipc_ns->user_ns);
+               new_nsp->ipc_ns->user_ns = task_cred_xxx(tsk, user)->user_ns;
+               get_user_ns(new_nsp->ipc_ns->user_ns);
+       }
 
        new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
        if (IS_ERR(new_nsp->pid_ns)) {