[PATCH RFC 22/31] net: Add network namespace clone support.
From: Eric W. Biederman <hidden>
Date: 2007-01-25 19:01:39
Subsystem:
networking [general], scheduler, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot, Linus Torvalds
From: Eric W. Biederman <redacted> - unquoted This patch allows you to create a new network namespace using sys_clone(...). Signed-off-by: Eric W. Biederman <redacted> --- include/linux/sched.h | 1 + kernel/nsproxy.c | 11 +++++++++++ net/core/net_namespace.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4463735..9e0f91a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h@@ -26,6 +26,7 @@ #define CLONE_STOPPED 0x02000000 /* Start in stopped state */ #define CLONE_NEWUTS 0x04000000 /* New utsname group? */ #define CLONE_NEWIPC 0x08000000 /* New ipcs */ +#define CLONE_NEWNET 0x20000000 /* New network namespace */ /* * Scheduling policies
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 4f3c95a..7861c4c 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c@@ -20,6 +20,7 @@ #include <linux/mnt_namespace.h> #include <linux/utsname.h> #include <linux/pid_namespace.h> +#include <net/net_namespace.h> struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); EXPORT_SYMBOL_GPL(init_nsproxy);
@@ -70,6 +71,7 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig) get_ipc_ns(ns->ipc_ns); if (ns->pid_ns) get_pid_ns(ns->pid_ns); + get_net(ns->net_ns); } return ns;
@@ -117,10 +119,18 @@ int copy_namespaces(int flags, struct task_struct *tsk) if (err) goto out_pid; + err = copy_net(flags, tsk); + if (err) + goto out_net; + out: put_nsproxy(old_ns); return err; +out_net: + if (new_ns->pid_ns) + put_pid_ns(new_ns->pid_ns); + out_pid: if (new_ns->ipc_ns) put_ipc_ns(new_ns->ipc_ns);
@@ -146,5 +156,6 @@ void free_nsproxy(struct nsproxy *ns) put_ipc_ns(ns->ipc_ns); if (ns->pid_ns) put_pid_ns(ns->pid_ns); + put_net(ns->net_ns); kfree(ns); }
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 93e3879..cc56105 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c@@ -175,6 +175,44 @@ out_undo: goto out; } +int copy_net(int flags, struct task_struct *tsk) +{ + net_t old_net = tsk->nsproxy->net_ns; + net_t new_net; + int err; + + get_net(old_net); + + if (!(flags & CLONE_NEWNET)) + return 0; + + err = -EPERM; + if (!capable(CAP_SYS_ADMIN)) + goto out; + + err = -ENOMEM; + new_net = net_alloc(); + if (null_net(new_net)) + goto out; + + mutex_lock(&net_mutex); + err = setup_net(new_net); + if (err) + goto out_unlock; + + net_lock(); + net_list_append(new_net); + net_unlock(); + + tsk->nsproxy->net_ns = new_net; + +out_unlock: + mutex_unlock(&net_mutex); +out: + put_net(old_net); + return err; +} + void pernet_modcopy(void *pnetdst, const void *src, unsigned long size) { net_t net;
--
1.4.4.1.g278f