diff options
Diffstat (limited to 'kernel/nsproxy.c')
-rw-r--r-- | kernel/nsproxy.c | 25 |
1 files changed, 8 insertions, 17 deletions
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 8e7811086b82..49746c81ad8d 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
@@ -204,20 +204,13 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) | |||
204 | 204 | ||
205 | might_sleep(); | 205 | might_sleep(); |
206 | 206 | ||
207 | task_lock(p); | ||
207 | ns = p->nsproxy; | 208 | ns = p->nsproxy; |
209 | p->nsproxy = new; | ||
210 | task_unlock(p); | ||
208 | 211 | ||
209 | rcu_assign_pointer(p->nsproxy, new); | 212 | if (ns && atomic_dec_and_test(&ns->count)) |
210 | |||
211 | if (ns && atomic_dec_and_test(&ns->count)) { | ||
212 | /* | ||
213 | * wait for others to get what they want from this nsproxy. | ||
214 | * | ||
215 | * cannot release this nsproxy via the call_rcu() since | ||
216 | * put_mnt_ns() will want to sleep | ||
217 | */ | ||
218 | synchronize_rcu(); | ||
219 | free_nsproxy(ns); | 213 | free_nsproxy(ns); |
220 | } | ||
221 | } | 214 | } |
222 | 215 | ||
223 | void exit_task_namespaces(struct task_struct *p) | 216 | void exit_task_namespaces(struct task_struct *p) |
@@ -227,11 +220,10 @@ void exit_task_namespaces(struct task_struct *p) | |||
227 | 220 | ||
228 | SYSCALL_DEFINE2(setns, int, fd, int, nstype) | 221 | SYSCALL_DEFINE2(setns, int, fd, int, nstype) |
229 | { | 222 | { |
230 | const struct proc_ns_operations *ops; | ||
231 | struct task_struct *tsk = current; | 223 | struct task_struct *tsk = current; |
232 | struct nsproxy *new_nsproxy; | 224 | struct nsproxy *new_nsproxy; |
233 | struct proc_ns *ei; | ||
234 | struct file *file; | 225 | struct file *file; |
226 | struct ns_common *ns; | ||
235 | int err; | 227 | int err; |
236 | 228 | ||
237 | file = proc_ns_fget(fd); | 229 | file = proc_ns_fget(fd); |
@@ -239,9 +231,8 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype) | |||
239 | return PTR_ERR(file); | 231 | return PTR_ERR(file); |
240 | 232 | ||
241 | err = -EINVAL; | 233 | err = -EINVAL; |
242 | ei = get_proc_ns(file_inode(file)); | 234 | ns = get_proc_ns(file_inode(file)); |
243 | ops = ei->ns_ops; | 235 | if (nstype && (ns->ops->type != nstype)) |
244 | if (nstype && (ops->type != nstype)) | ||
245 | goto out; | 236 | goto out; |
246 | 237 | ||
247 | new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); | 238 | new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); |
@@ -250,7 +241,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype) | |||
250 | goto out; | 241 | goto out; |
251 | } | 242 | } |
252 | 243 | ||
253 | err = ops->install(new_nsproxy, ei->ns); | 244 | err = ns->ops->install(new_nsproxy, ns); |
254 | if (err) { | 245 | if (err) { |
255 | free_nsproxy(new_nsproxy); | 246 | free_nsproxy(new_nsproxy); |
256 | goto out; | 247 | goto out; |