aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/nsproxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/nsproxy.c')
-rw-r--r--kernel/nsproxy.c25
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
223void exit_task_namespaces(struct task_struct *p) 216void exit_task_namespaces(struct task_struct *p)
@@ -227,11 +220,10 @@ void exit_task_namespaces(struct task_struct *p)
227 220
228SYSCALL_DEFINE2(setns, int, fd, int, nstype) 221SYSCALL_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;