X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=kernel%2Fnsproxy.c;h=f5b9ee6f6bbb02733cef1e64fabe4dc521efc767;hb=4fc00cb4d520124e82fdaa5882077075b1f007cc;hp=ad950886547357ee4c38acb2fe872dae5a1f6739;hpb=ab516013ad9ca47f1d3a936fa81303bfbf734d52;p=powerpc.git diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index ad95088654..f5b9ee6f6b 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -7,11 +7,21 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. + * + * Jun 2006 - namespaces support + * OpenVZ, SWsoft Inc. + * Pavel Emelianov */ #include #include #include +#include +#include +#include +#include + +struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); static inline void get_nsproxy(struct nsproxy *ns) { @@ -35,11 +45,9 @@ static inline struct nsproxy *clone_namespaces(struct nsproxy *orig) { struct nsproxy *ns; - ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL); - if (ns) { - memcpy(ns, orig, sizeof(struct nsproxy)); + ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL); + if (ns) atomic_set(&ns->count, 1); - } return ns; } @@ -52,6 +60,17 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig) { struct nsproxy *ns = clone_namespaces(orig); + if (ns) { + if (ns->mnt_ns) + get_mnt_ns(ns->mnt_ns); + if (ns->uts_ns) + get_uts_ns(ns->uts_ns); + if (ns->ipc_ns) + get_ipc_ns(ns->ipc_ns); + if (ns->pid_ns) + get_pid_ns(ns->pid_ns); + } + return ns; } @@ -62,16 +81,69 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig) int copy_namespaces(int flags, struct task_struct *tsk) { struct nsproxy *old_ns = tsk->nsproxy; + struct nsproxy *new_ns; + int err = 0; if (!old_ns) return 0; get_nsproxy(old_ns); - return 0; + if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC))) + return 0; + + new_ns = clone_namespaces(old_ns); + if (!new_ns) { + err = -ENOMEM; + goto out; + } + + tsk->nsproxy = new_ns; + + err = copy_mnt_ns(flags, tsk); + if (err) + goto out_ns; + + err = copy_utsname(flags, tsk); + if (err) + goto out_uts; + + err = copy_ipcs(flags, tsk); + if (err) + goto out_ipc; + + err = copy_pid_ns(flags, tsk); + if (err) + goto out_pid; + +out: + put_nsproxy(old_ns); + return err; + +out_pid: + if (new_ns->ipc_ns) + put_ipc_ns(new_ns->ipc_ns); +out_ipc: + if (new_ns->uts_ns) + put_uts_ns(new_ns->uts_ns); +out_uts: + if (new_ns->mnt_ns) + put_mnt_ns(new_ns->mnt_ns); +out_ns: + tsk->nsproxy = old_ns; + kfree(new_ns); + goto out; } void free_nsproxy(struct nsproxy *ns) { - kfree(ns); + if (ns->mnt_ns) + put_mnt_ns(ns->mnt_ns); + if (ns->uts_ns) + put_uts_ns(ns->uts_ns); + if (ns->ipc_ns) + put_ipc_ns(ns->ipc_ns); + if (ns->pid_ns) + put_pid_ns(ns->pid_ns); + kfree(ns); }