Blame view

kernel/nsproxy.c 6.22 KB
ab516013a   Serge E. Hallyn   [PATCH] namespace...
1
2
3
4
5
6
7
8
9
  /*
   *  Copyright (C) 2006 IBM Corporation
   *
   *  Author: Serge Hallyn <serue@us.ibm.com>
   *
   *  This program is free software; you can redistribute it and/or
   *  modify it under the terms of the GNU General Public License as
   *  published by the Free Software Foundation, version 2 of the
   *  License.
25b21cb2f   Kirill Korotaev   [PATCH] IPC names...
10
11
12
13
   *
   *  Jun 2006 - namespaces support
   *             OpenVZ, SWsoft Inc.
   *             Pavel Emelianov <xemul@openvz.org>
ab516013a   Serge E. Hallyn   [PATCH] namespace...
14
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
9984de1a5   Paul Gortmaker   kernel: Map most ...
16
  #include <linux/export.h>
ab516013a   Serge E. Hallyn   [PATCH] namespace...
17
  #include <linux/nsproxy.h>
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
18
  #include <linux/init_task.h>
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
19
  #include <linux/mnt_namespace.h>
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
20
  #include <linux/utsname.h>
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
21
  #include <linux/pid_namespace.h>
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
22
  #include <net/net_namespace.h>
ae5e1b22f   Pavel Emelyanov   namespaces: move ...
23
  #include <linux/ipc_namespace.h>
0bb80f240   David Howells   proc: Split the n...
24
  #include <linux/proc_ns.h>
0663c6f8f   Eric W. Biederman   ns: Introduce the...
25
26
  #include <linux/file.h>
  #include <linux/syscalls.h>
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
27

98c0d07cb   Cedric Le Goater   add a kmem_cache ...
28
  static struct kmem_cache *nsproxy_cachep;
8467005da   Alexey Dobriyan   nsproxy: remove I...
29
30
31
32
33
34
35
36
37
38
39
40
  struct nsproxy init_nsproxy = {
  	.count	= ATOMIC_INIT(1),
  	.uts_ns	= &init_uts_ns,
  #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
  	.ipc_ns	= &init_ipc_ns,
  #endif
  	.mnt_ns	= NULL,
  	.pid_ns	= &init_pid_ns,
  #ifdef CONFIG_NET
  	.net_ns	= &init_net,
  #endif
  };
ab516013a   Serge E. Hallyn   [PATCH] namespace...
41

90af90d7d   Alexey Dobriyan   nsproxy: extract ...
42
  static inline struct nsproxy *create_nsproxy(void)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
43
  {
90af90d7d   Alexey Dobriyan   nsproxy: extract ...
44
  	struct nsproxy *nsproxy;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
45

90af90d7d   Alexey Dobriyan   nsproxy: extract ...
46
47
48
49
  	nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
  	if (nsproxy)
  		atomic_set(&nsproxy->count, 1);
  	return nsproxy;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
50
51
52
  }
  
  /*
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
53
54
55
   * Create new nsproxy and all of its the associated namespaces.
   * Return the newly created nsproxy.  Do not attach this to the task,
   * leave it to the caller to do proper locking and attach it to task.
ab516013a   Serge E. Hallyn   [PATCH] namespace...
56
   */
213dd266d   Eric W. Biederman   namespace: ensure...
57
  static struct nsproxy *create_new_namespaces(unsigned long flags,
bcf58e725   Eric W. Biederman   userns: Make crea...
58
59
  	struct task_struct *tsk, struct user_namespace *user_ns,
  	struct fs_struct *new_fs)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
60
  {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
61
  	struct nsproxy *new_nsp;
467e9f4b5   Cedric Le Goater   fix create_new_na...
62
  	int err;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
63

90af90d7d   Alexey Dobriyan   nsproxy: extract ...
64
  	new_nsp = create_nsproxy();
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
65
66
  	if (!new_nsp)
  		return ERR_PTR(-ENOMEM);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
67

bcf58e725   Eric W. Biederman   userns: Make crea...
68
  	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
467e9f4b5   Cedric Le Goater   fix create_new_na...
69
70
  	if (IS_ERR(new_nsp->mnt_ns)) {
  		err = PTR_ERR(new_nsp->mnt_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
71
  		goto out_ns;
467e9f4b5   Cedric Le Goater   fix create_new_na...
72
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
73

bcf58e725   Eric W. Biederman   userns: Make crea...
74
  	new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
75
76
  	if (IS_ERR(new_nsp->uts_ns)) {
  		err = PTR_ERR(new_nsp->uts_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
77
  		goto out_uts;
467e9f4b5   Cedric Le Goater   fix create_new_na...
78
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
79

bcf58e725   Eric W. Biederman   userns: Make crea...
80
  	new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
81
82
  	if (IS_ERR(new_nsp->ipc_ns)) {
  		err = PTR_ERR(new_nsp->ipc_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
83
  		goto out_ipc;
467e9f4b5   Cedric Le Goater   fix create_new_na...
84
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
85

bcf58e725   Eric W. Biederman   userns: Make crea...
86
  	new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
87
88
  	if (IS_ERR(new_nsp->pid_ns)) {
  		err = PTR_ERR(new_nsp->pid_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
89
  		goto out_pid;
467e9f4b5   Cedric Le Goater   fix create_new_na...
90
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
91

bcf58e725   Eric W. Biederman   userns: Make crea...
92
  	new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
93
94
95
96
  	if (IS_ERR(new_nsp->net_ns)) {
  		err = PTR_ERR(new_nsp->net_ns);
  		goto out_net;
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
97
  	return new_nsp;
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
98
  out_net:
acce292c8   Cedric Le Goater   user namespace: a...
99
100
  	if (new_nsp->pid_ns)
  		put_pid_ns(new_nsp->pid_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
101
102
103
104
105
106
107
108
109
110
  out_pid:
  	if (new_nsp->ipc_ns)
  		put_ipc_ns(new_nsp->ipc_ns);
  out_ipc:
  	if (new_nsp->uts_ns)
  		put_uts_ns(new_nsp->uts_ns);
  out_uts:
  	if (new_nsp->mnt_ns)
  		put_mnt_ns(new_nsp->mnt_ns);
  out_ns:
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
111
  	kmem_cache_free(nsproxy_cachep, new_nsp);
467e9f4b5   Cedric Le Goater   fix create_new_na...
112
  	return ERR_PTR(err);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
113
114
115
116
117
118
  }
  
  /*
   * called from clone.  This now handles copy for nsproxy and all
   * namespaces therein.
   */
213dd266d   Eric W. Biederman   namespace: ensure...
119
  int copy_namespaces(unsigned long flags, struct task_struct *tsk)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
120
121
  {
  	struct nsproxy *old_ns = tsk->nsproxy;
b33c77ef2   Eric W. Biederman   userns: Allow unp...
122
  	struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
123
124
  	struct nsproxy *new_ns;
  	int err = 0;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
125
126
127
128
129
  
  	if (!old_ns)
  		return 0;
  
  	get_nsproxy(old_ns);
30e49c263   Pavel Emelyanov   pid namespaces: a...
130
  	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
18b6e0414   Serge Hallyn   User namespaces: ...
131
  				CLONE_NEWPID | CLONE_NEWNET)))
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
132
  		return 0;
b33c77ef2   Eric W. Biederman   userns: Allow unp...
133
  	if (!ns_capable(user_ns, CAP_SYS_ADMIN)) {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
134
  		err = -EPERM;
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
135
136
  		goto out;
  	}
02fdb36ae   Serge E. Hallyn   ipc: sysvsem: ref...
137
138
139
140
141
142
143
144
145
146
147
  	/*
  	 * 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;
  	}
d7d48f621   Yuanhan Liu   kernel/nsproxy.c:...
148
  	new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
149
150
151
152
  	if (IS_ERR(new_ns)) {
  		err = PTR_ERR(new_ns);
  		goto out;
  	}
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
153

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
154
  	tsk->nsproxy = new_ns;
858d72ead   Serge E. Hallyn   cgroups: implemen...
155

1651e14e2   Serge E. Hallyn   [PATCH] namespace...
156
  out:
444f378b2   Linus Torvalds   Revert "[PATCH] n...
157
  	put_nsproxy(old_ns);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
158
  	return err;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
159
160
161
162
  }
  
  void free_nsproxy(struct nsproxy *ns)
  {
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
163
164
165
166
167
168
169
170
  	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);
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
171
  	put_net(ns->net_ns);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
172
  	kmem_cache_free(nsproxy_cachep, ns);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
173
  }
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
174
175
176
  
  /*
   * Called from unshare. Unshare all the namespaces part of nsproxy.
4e71e474c   Cedric Le Goater   fix refcounting o...
177
   * On success, returns the new nsproxy.
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
178
179
   */
  int unshare_nsproxy_namespaces(unsigned long unshare_flags,
b2e0d9870   Eric W. Biederman   userns: Implement...
180
  	struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
181
  {
bcf58e725   Eric W. Biederman   userns: Make crea...
182
  	struct user_namespace *user_ns;
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
183
  	int err = 0;
77ec739d8   Serge E. Hallyn   user namespace: a...
184
  	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
50804fe37   Eric W. Biederman   pidns: Support un...
185
  			       CLONE_NEWNET | CLONE_NEWPID)))
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
186
  		return 0;
b2e0d9870   Eric W. Biederman   userns: Implement...
187
188
  	user_ns = new_cred ? new_cred->user_ns : current_user_ns();
  	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
189
  		return -EPERM;
bcf58e725   Eric W. Biederman   userns: Make crea...
190
  	*new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
b2e0d9870   Eric W. Biederman   userns: Implement...
191
  					 new_fs ? new_fs : current->fs);
858d72ead   Serge E. Hallyn   cgroups: implemen...
192
  	if (IS_ERR(*new_nsp)) {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
193
  		err = PTR_ERR(*new_nsp);
858d72ead   Serge E. Hallyn   cgroups: implemen...
194
195
  		goto out;
  	}
858d72ead   Serge E. Hallyn   cgroups: implemen...
196
  out:
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
197
198
  	return err;
  }
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
199

cf7b708c8   Pavel Emelyanov   Make access to ta...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
  {
  	struct nsproxy *ns;
  
  	might_sleep();
  
  	ns = p->nsproxy;
  
  	rcu_assign_pointer(p->nsproxy, new);
  
  	if (ns && atomic_dec_and_test(&ns->count)) {
  		/*
  		 * wait for others to get what they want from this nsproxy.
  		 *
  		 * cannot release this nsproxy via the call_rcu() since
  		 * put_mnt_ns() will want to sleep
  		 */
  		synchronize_rcu();
  		free_nsproxy(ns);
  	}
  }
  
  void exit_task_namespaces(struct task_struct *p)
  {
  	switch_task_namespaces(p, NULL);
  }
0663c6f8f   Eric W. Biederman   ns: Introduce the...
226
227
228
229
230
  SYSCALL_DEFINE2(setns, int, fd, int, nstype)
  {
  	const struct proc_ns_operations *ops;
  	struct task_struct *tsk = current;
  	struct nsproxy *new_nsproxy;
0bb80f240   David Howells   proc: Split the n...
231
  	struct proc_ns *ei;
0663c6f8f   Eric W. Biederman   ns: Introduce the...
232
233
  	struct file *file;
  	int err;
0663c6f8f   Eric W. Biederman   ns: Introduce the...
234
235
236
237
238
  	file = proc_ns_fget(fd);
  	if (IS_ERR(file))
  		return PTR_ERR(file);
  
  	err = -EINVAL;
0bb80f240   David Howells   proc: Split the n...
239
  	ei = get_proc_ns(file_inode(file));
0663c6f8f   Eric W. Biederman   ns: Introduce the...
240
241
242
  	ops = ei->ns_ops;
  	if (nstype && (ops->type != nstype))
  		goto out;
bcf58e725   Eric W. Biederman   userns: Make crea...
243
  	new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
0663c6f8f   Eric W. Biederman   ns: Introduce the...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  	if (IS_ERR(new_nsproxy)) {
  		err = PTR_ERR(new_nsproxy);
  		goto out;
  	}
  
  	err = ops->install(new_nsproxy, ei->ns);
  	if (err) {
  		free_nsproxy(new_nsproxy);
  		goto out;
  	}
  	switch_task_namespaces(tsk, new_nsproxy);
  out:
  	fput(file);
  	return err;
  }
665771939   Al Viro   make sure that ns...
259
  int __init nsproxy_cache_init(void)
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
260
  {
db8906da5   Pavel Emelyanov   Use KMEM_CACHE ma...
261
  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
262
263
  	return 0;
  }