diff options
Diffstat (limited to 'kernel/nsproxy.c')
| -rw-r--r-- | kernel/nsproxy.c | 36 |
1 files changed, 12 insertions, 24 deletions
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 997cbb951a3b..8e7811086b82 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
| @@ -126,22 +126,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) | |||
| 126 | struct nsproxy *old_ns = tsk->nsproxy; | 126 | struct nsproxy *old_ns = tsk->nsproxy; |
| 127 | struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); | 127 | struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); |
| 128 | struct nsproxy *new_ns; | 128 | struct nsproxy *new_ns; |
| 129 | int err = 0; | ||
| 130 | 129 | ||
| 131 | if (!old_ns) | 130 | if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | |
| 131 | CLONE_NEWPID | CLONE_NEWNET)))) { | ||
| 132 | get_nsproxy(old_ns); | ||
| 132 | return 0; | 133 | return 0; |
| 133 | |||
| 134 | get_nsproxy(old_ns); | ||
| 135 | |||
| 136 | if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | | ||
| 137 | CLONE_NEWPID | CLONE_NEWNET))) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) { | ||
| 141 | err = -EPERM; | ||
| 142 | goto out; | ||
| 143 | } | 134 | } |
| 144 | 135 | ||
| 136 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) | ||
| 137 | return -EPERM; | ||
| 138 | |||
| 145 | /* | 139 | /* |
| 146 | * CLONE_NEWIPC must detach from the undolist: after switching | 140 | * CLONE_NEWIPC must detach from the undolist: after switching |
| 147 | * to a new ipc namespace, the semaphore arrays from the old | 141 | * to a new ipc namespace, the semaphore arrays from the old |
| @@ -149,22 +143,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) | |||
| 149 | * means share undolist with parent, so we must forbid using | 143 | * means share undolist with parent, so we must forbid using |
| 150 | * it along with CLONE_NEWIPC. | 144 | * it along with CLONE_NEWIPC. |
| 151 | */ | 145 | */ |
| 152 | if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) { | 146 | if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) == |
| 153 | err = -EINVAL; | 147 | (CLONE_NEWIPC | CLONE_SYSVSEM)) |
| 154 | goto out; | 148 | return -EINVAL; |
| 155 | } | ||
| 156 | 149 | ||
| 157 | new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); | 150 | new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs); |
| 158 | if (IS_ERR(new_ns)) { | 151 | if (IS_ERR(new_ns)) |
| 159 | err = PTR_ERR(new_ns); | 152 | return PTR_ERR(new_ns); |
| 160 | goto out; | ||
| 161 | } | ||
| 162 | 153 | ||
| 163 | tsk->nsproxy = new_ns; | 154 | tsk->nsproxy = new_ns; |
| 164 | 155 | return 0; | |
| 165 | out: | ||
| 166 | put_nsproxy(old_ns); | ||
| 167 | return err; | ||
| 168 | } | 156 | } |
| 169 | 157 | ||
| 170 | void free_nsproxy(struct nsproxy *ns) | 158 | void free_nsproxy(struct nsproxy *ns) |
