Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.24 /kernel/nsproxy.c

Filename:/kernel/nsproxy.c
Lines Added:59
Lines Deleted:19
Also changed in: (Previous) 2.6.24-rc8  2.6.24-rc7  2.6.24-rc6  2.6.24-rc5  2.6.24-rc4  2.6.24-rc3 
(Following) 2.6.24-git19  2.6.24-git20  2.6.24-git21  2.6.24-git22  2.6.25-rc1  2.6.25-rc2 

Location
[  2.6.24
  [  kernel
     o  nsproxy.c

Patch

diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index a4fb7d4..79f871b 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -20,24 +20,12 @@
 #include <linux/mnt_namespace.h>
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
+#include <net/net_namespace.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
-static inline void get_nsproxy(struct nsproxy *ns)
-{
-   atomic_inc(&ns->count);
-}
-
-void get_task_namespaces(struct task_struct *tsk)
-{
-   struct nsproxy *ns = tsk->nsproxy;
-   if (ns) {
-      get_nsproxy(ns);
-   }
-}
-
 /*
  * creates a copy of "orig" with refcount 1.
  */
@@ -86,7 +74,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
       goto out_ipc;
    }
 
-   new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
+   new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
    if (IS_ERR(new_nsp->pid_ns)) {
       err = PTR_ERR(new_nsp->pid_ns);
       goto out_pid;
@@ -98,8 +86,17 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
       goto out_user;
    }
 
+   new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns);
+   if (IS_ERR(new_nsp->net_ns)) {
+      err = PTR_ERR(new_nsp->net_ns);
+      goto out_net;
+   }
+
    return new_nsp;
 
+out_net:
+   if (new_nsp->user_ns)
+      put_user_ns(new_nsp->user_ns);
 out_user:
    if (new_nsp->pid_ns)
       put_pid_ns(new_nsp->pid_ns);
@@ -132,7 +129,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 
    get_nsproxy(old_ns);
 
-   if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)))
+   if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+            CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET)))
       return 0;
 
    if (!capable(CAP_SYS_ADMIN)) {
@@ -146,7 +144,14 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
       goto out;
    }
 
+   err = ns_cgroup_clone(tsk);
+   if (err) {
+      put_nsproxy(new_ns);
+      goto out;
+   }
+
    tsk->nsproxy = new_ns;
+
 out:
    put_nsproxy(old_ns);
    return err;
@@ -164,6 +169,7 @@ void free_nsproxy(struct nsproxy *ns)
       put_pid_ns(ns->pid_ns);
    if (ns->user_ns)
       put_user_ns(ns->user_ns);
+   put_net(ns->net_ns);
    kmem_cache_free(nsproxy_cachep, ns);
 }
 
@@ -177,7 +183,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
    int err = 0;
 
    if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-                CLONE_NEWUSER)))
+                CLONE_NEWUSER | CLONE_NEWNET)))
       return 0;
 
    if (!capable(CAP_SYS_ADMIN))
@@ -185,15 +191,49 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
 
    *new_nsp = create_new_namespaces(unshare_flags, current,
             new_fs ? new_fs : current->fs);
-   if (IS_ERR(*new_nsp))
+   if (IS_ERR(*new_nsp)) {
       err = PTR_ERR(*new_nsp);
+      goto out;
+   }
+
+   err = ns_cgroup_clone(current);
+   if (err)
+      put_nsproxy(*new_nsp);
+
+out:
    return err;
 }
 
+void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
+{
+   struct nsproxy *ns;
+
+   might_sleep();
+
+   ns = p->nsproxy;
+
+   rcu_assign_pointer(p->nsproxy, new);
+
+   if (ns && atomic_dec_and_test(&ns->count)) {
+      /*
+       * wait for others to get what they want from this nsproxy.
+       *
+       * cannot release this nsproxy via the call_rcu() since
+       * put_mnt_ns() will want to sleep
+       */
+      synchronize_rcu();
+      free_nsproxy(ns);
+   }
+}
+
+void exit_task_namespaces(struct task_struct *p)
+{
+   switch_task_namespaces(p, NULL);
+}
+
 static int __init nsproxy_cache_init(void)
 {
-   nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
-                  0, SLAB_PANIC, NULL);
+   nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
    return 0;
 }
 


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.