/* * called from clone. This now handles copy for nsproxy and all * namespaces therein. */ int copy_namespaces(unsigned long flags, struct task_struct *tsk) { struct nsproxy *old_ns = tsk->nsproxy; struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); struct nsproxy *new_ns; if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWCGROUP)))) { get_nsproxy(old_ns); return 0; } if (!ns_capable(user_ns, CAP_SYS_ADMIN)) return -EPERM; /* * CLONE_NEWIPC must detach from the undolist: after switching * to a new ipc namespace, the semaphore arrays from the old * namespace are unreachable. In clone parlance, CLONE_SYSVSEM * means share undolist with parent, so we must forbid using * it along with CLONE_NEWIPC. */ if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) == (CLONE_NEWIPC | CLONE_SYSVSEM)) return -EINVAL; new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); if (IS_ERR(new_ns)) return PTR_ERR(new_ns); tsk->nsproxy = new_ns; return 0; }
/* * Called from unshare. Unshare all the namespaces part of nsproxy. * On success, returns the new nsproxy. */ int unshare_nsproxy_namespaces(unsigned long unshare_flags, struct nsproxy **new_nsp, struct fs_struct *new_fs) { int err = 0; if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWNET))) return 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; *new_nsp = create_new_namespaces(unshare_flags, current, new_fs ? new_fs : current->fs); if (IS_ERR(*new_nsp)) { err = PTR_ERR(*new_nsp); goto out; } err = ns_cgroup_clone(current, task_pid(current)); if (err) put_nsproxy(*new_nsp); out: return err; }
/* * called from clone. This now handles copy for nsproxy and all * namespaces therein. */ int copy_namespaces(unsigned long flags, struct task_struct *tsk, int force_admin) { struct nsproxy *old_ns = tsk->nsproxy; struct nsproxy *new_ns; int err = 0; if (!old_ns) return 0; get_nsproxy(old_ns); if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET))) return 0; if (!force_admin) { if (!capable(CAP_SYS_ADMIN)) { err = -EPERM; goto out; } /* * netns-vs-sysfs is deadly broken, thus new namespace * (even in ve0) can bring the node down */ if (flags & CLONE_NEWNET) { err = -EINVAL; goto out; } } /* * CLONE_NEWIPC must detach from the undolist: after switching * to a new ipc namespace, the semaphore arrays from the old * namespace are unreachable. In clone parlance, CLONE_SYSVSEM * means share undolist with parent, so we must forbid using * it along with CLONE_NEWIPC. */ if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) { err = -EINVAL; goto out; } new_ns = create_new_namespaces(flags, tsk, tsk->fs); if (IS_ERR(new_ns)) { err = PTR_ERR(new_ns); goto out; } tsk->nsproxy = new_ns; out: put_nsproxy(old_ns); return err; }
/* * called from clone. This now handles copy for nsproxy and all * namespaces therein. */ int copy_namespaces(unsigned long flags, struct task_struct *tsk) { struct nsproxy *old_ns = tsk->nsproxy; struct nsproxy *new_ns; int err = 0; if (!old_ns) return 0; //old的命名空间递增. get_nsproxy(old_ns); //查看是不是要创建新的命令空间..查看各个标记. if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET))) return 0; if (!capable(CAP_SYS_ADMIN)) { err = -EPERM; goto out; } /* * CLONE_NEWIPC must detach from the undolist: after switching * to a new ipc namespace, the semaphore arrays from the old * namespace are unreachable. In clone parlance, CLONE_SYSVSEM * means share undolist with parent, so we must forbid using * it along with CLONE_NEWIPC. */ if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) { err = -EINVAL; goto out; } new_ns = create_new_namespaces(flags, tsk, tsk->fs); if (IS_ERR(new_ns)) { err = PTR_ERR(new_ns); goto out; } tsk->nsproxy = new_ns; //这里返回就是需要设置自己的命名空间,最后需要对old的命名空间的引用递减. out: put_nsproxy(old_ns); return err; }
struct nsproxy *lve_nsproxy_dup(struct nsproxy *ns) { struct task_struct *task; struct nsproxy *nsnew; task = kmalloc(sizeof(*task), GFP_KERNEL); if (task == NULL) { LVE_WARN("failed to allocate task_struct\n"); return NULL; } task->nsproxy = ns; nsnew = create_new_namespaces(0, task, NULL, NULL); kfree(task); if (IS_ERR(nsnew)) { LVE_WARN("failed to create new ns, err %ld\n", PTR_ERR(nsnew)); nsnew = NULL; } return nsnew; }
/* * called from clone. This now handles copy for nsproxy and all * namespaces therein. */ int copy_namespaces(unsigned long 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); if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET))) return 0; if (!capable(CAP_SYS_ADMIN)) { err = -EPERM; goto out; } new_ns = create_new_namespaces(flags, tsk, tsk->fs); if (IS_ERR(new_ns)) { err = PTR_ERR(new_ns); 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; }
/* * Called from unshare. Unshare all the namespaces part of nsproxy. * On success, returns the new nsproxy. */ int unshare_nsproxy_namespaces(unsigned long unshare_flags, struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs) { struct user_namespace *user_ns; int err = 0; if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP))) return 0; user_ns = new_cred ? new_cred->user_ns : current_user_ns(); if (!ns_capable(user_ns, CAP_SYS_ADMIN)) return -EPERM; *new_nsp = create_new_namespaces(unshare_flags, current, user_ns, new_fs ? new_fs : current->fs); if (IS_ERR(*new_nsp)) { err = PTR_ERR(*new_nsp); goto out; } out: return err; }