Blame view

kernel/nsproxy.c 5.92 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>
0663c6f8f   Eric W. Biederman   ns: Introduce the...
24
25
26
  #include <linux/proc_fs.h>
  #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
58
  static struct nsproxy *create_new_namespaces(unsigned long flags,
  			struct task_struct *tsk, struct fs_struct *new_fs)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
59
  {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
60
  	struct nsproxy *new_nsp;
467e9f4b5   Cedric Le Goater   fix create_new_na...
61
  	int err;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
62

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

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
67
  	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
467e9f4b5   Cedric Le Goater   fix create_new_na...
68
69
  	if (IS_ERR(new_nsp->mnt_ns)) {
  		err = PTR_ERR(new_nsp->mnt_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
70
  		goto out_ns;
467e9f4b5   Cedric Le Goater   fix create_new_na...
71
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
72

bb96a6f50   Serge E. Hallyn   userns: allow set...
73
  	new_nsp->uts_ns = copy_utsname(flags, tsk);
467e9f4b5   Cedric Le Goater   fix create_new_na...
74
75
  	if (IS_ERR(new_nsp->uts_ns)) {
  		err = PTR_ERR(new_nsp->uts_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
76
  		goto out_uts;
467e9f4b5   Cedric Le Goater   fix create_new_na...
77
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
78

b0e77598f   Serge E. Hallyn   userns: user name...
79
  	new_nsp->ipc_ns = copy_ipcs(flags, tsk);
467e9f4b5   Cedric Le Goater   fix create_new_na...
80
81
  	if (IS_ERR(new_nsp->ipc_ns)) {
  		err = PTR_ERR(new_nsp->ipc_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
82
  		goto out_ipc;
467e9f4b5   Cedric Le Goater   fix create_new_na...
83
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
84

2894d650c   Sukadev Bhattiprolu   pid namespaces: d...
85
  	new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
467e9f4b5   Cedric Le Goater   fix create_new_na...
86
87
  	if (IS_ERR(new_nsp->pid_ns)) {
  		err = PTR_ERR(new_nsp->pid_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
88
  		goto out_pid;
467e9f4b5   Cedric Le Goater   fix create_new_na...
89
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
90

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

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

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

cf7b708c8   Pavel Emelyanov   Make access to ta...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  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...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  SYSCALL_DEFINE2(setns, int, fd, int, nstype)
  {
  	const struct proc_ns_operations *ops;
  	struct task_struct *tsk = current;
  	struct nsproxy *new_nsproxy;
  	struct proc_inode *ei;
  	struct file *file;
  	int err;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	file = proc_ns_fget(fd);
  	if (IS_ERR(file))
  		return PTR_ERR(file);
  
  	err = -EINVAL;
  	ei = PROC_I(file->f_dentry->d_inode);
  	ops = ei->ns_ops;
  	if (nstype && (ops->type != nstype))
  		goto out;
  
  	new_nsproxy = create_new_namespaces(0, tsk, tsk->fs);
  	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...
260
  int __init nsproxy_cache_init(void)
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
261
  {
db8906da5   Pavel Emelyanov   Use KMEM_CACHE ma...
262
  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
263
264
  	return 0;
  }