Blame view

kernel/nsproxy.c 6.28 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
  struct nsproxy init_nsproxy = {
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
30
31
  	.count			= ATOMIC_INIT(1),
  	.uts_ns			= &init_uts_ns,
8467005da   Alexey Dobriyan   nsproxy: remove I...
32
  #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
33
  	.ipc_ns			= &init_ipc_ns,
8467005da   Alexey Dobriyan   nsproxy: remove I...
34
  #endif
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
35
36
  	.mnt_ns			= NULL,
  	.pid_ns_for_children	= &init_pid_ns,
8467005da   Alexey Dobriyan   nsproxy: remove I...
37
  #ifdef CONFIG_NET
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
38
  	.net_ns			= &init_net,
8467005da   Alexey Dobriyan   nsproxy: remove I...
39
40
  #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

c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
86
87
88
89
  	new_nsp->pid_ns_for_children =
  		copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
  	if (IS_ERR(new_nsp->pid_ns_for_children)) {
  		err = PTR_ERR(new_nsp->pid_ns_for_children);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
90
  		goto out_pid;
467e9f4b5   Cedric Le Goater   fix create_new_na...
91
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
92

bcf58e725   Eric W. Biederman   userns: Make crea...
93
  	new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
94
95
96
97
  	if (IS_ERR(new_nsp->net_ns)) {
  		err = PTR_ERR(new_nsp->net_ns);
  		goto out_net;
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
98
  	return new_nsp;
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
99
  out_net:
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
100
101
  	if (new_nsp->pid_ns_for_children)
  		put_pid_ns(new_nsp->pid_ns_for_children);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
102
103
104
105
106
107
108
109
110
111
  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 ...
112
  	kmem_cache_free(nsproxy_cachep, new_nsp);
467e9f4b5   Cedric Le Goater   fix create_new_na...
113
  	return ERR_PTR(err);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
114
115
116
117
118
119
  }
  
  /*
   * called from clone.  This now handles copy for nsproxy and all
   * namespaces therein.
   */
213dd266d   Eric W. Biederman   namespace: ensure...
120
  int copy_namespaces(unsigned long flags, struct task_struct *tsk)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
121
122
  {
  	struct nsproxy *old_ns = tsk->nsproxy;
b33c77ef2   Eric W. Biederman   userns: Allow unp...
123
  	struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
124
  	struct nsproxy *new_ns;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
125

dbef0c1c4   Eric W. Biederman   namespaces: Simpl...
126
127
128
  	if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
  			      CLONE_NEWPID | CLONE_NEWNET)))) {
  		get_nsproxy(old_ns);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
129
  		return 0;
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
130
  	}
dbef0c1c4   Eric W. Biederman   namespaces: Simpl...
131
132
  	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
  		return -EPERM;
02fdb36ae   Serge E. Hallyn   ipc: sysvsem: ref...
133
134
135
136
137
138
139
  	/*
  	 * 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.
  	 */
21e851943   Raphael S.Carvalho   kernel/nsproxy.c:...
140
  	if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) ==
dbef0c1c4   Eric W. Biederman   namespaces: Simpl...
141
142
  		(CLONE_NEWIPC | CLONE_SYSVSEM)) 
  		return -EINVAL;
02fdb36ae   Serge E. Hallyn   ipc: sysvsem: ref...
143

d7d48f621   Yuanhan Liu   kernel/nsproxy.c:...
144
  	new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
dbef0c1c4   Eric W. Biederman   namespaces: Simpl...
145
146
  	if (IS_ERR(new_ns))
  		return  PTR_ERR(new_ns);
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
147

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
148
  	tsk->nsproxy = new_ns;
dbef0c1c4   Eric W. Biederman   namespaces: Simpl...
149
  	return 0;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
150
151
152
153
  }
  
  void free_nsproxy(struct nsproxy *ns)
  {
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
154
155
156
157
158
159
  	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);
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
160
161
  	if (ns->pid_ns_for_children)
  		put_pid_ns(ns->pid_ns_for_children);
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
162
  	put_net(ns->net_ns);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
163
  	kmem_cache_free(nsproxy_cachep, ns);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
164
  }
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
165
166
167
  
  /*
   * Called from unshare. Unshare all the namespaces part of nsproxy.
4e71e474c   Cedric Le Goater   fix refcounting o...
168
   * On success, returns the new nsproxy.
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
169
170
   */
  int unshare_nsproxy_namespaces(unsigned long unshare_flags,
b2e0d9870   Eric W. Biederman   userns: Implement...
171
  	struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
172
  {
bcf58e725   Eric W. Biederman   userns: Make crea...
173
  	struct user_namespace *user_ns;
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
174
  	int err = 0;
77ec739d8   Serge E. Hallyn   user namespace: a...
175
  	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
50804fe37   Eric W. Biederman   pidns: Support un...
176
  			       CLONE_NEWNET | CLONE_NEWPID)))
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
177
  		return 0;
b2e0d9870   Eric W. Biederman   userns: Implement...
178
179
  	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()...
180
  		return -EPERM;
bcf58e725   Eric W. Biederman   userns: Make crea...
181
  	*new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
b2e0d9870   Eric W. Biederman   userns: Implement...
182
  					 new_fs ? new_fs : current->fs);
858d72ead   Serge E. Hallyn   cgroups: implemen...
183
  	if (IS_ERR(*new_nsp)) {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
184
  		err = PTR_ERR(*new_nsp);
858d72ead   Serge E. Hallyn   cgroups: implemen...
185
186
  		goto out;
  	}
858d72ead   Serge E. Hallyn   cgroups: implemen...
187
  out:
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
188
189
  	return err;
  }
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
190

cf7b708c8   Pavel Emelyanov   Make access to ta...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  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...
217
218
219
220
221
  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...
222
  	struct proc_ns *ei;
0663c6f8f   Eric W. Biederman   ns: Introduce the...
223
224
  	struct file *file;
  	int err;
0663c6f8f   Eric W. Biederman   ns: Introduce the...
225
226
227
228
229
  	file = proc_ns_fget(fd);
  	if (IS_ERR(file))
  		return PTR_ERR(file);
  
  	err = -EINVAL;
0bb80f240   David Howells   proc: Split the n...
230
  	ei = get_proc_ns(file_inode(file));
0663c6f8f   Eric W. Biederman   ns: Introduce the...
231
232
233
  	ops = ei->ns_ops;
  	if (nstype && (ops->type != nstype))
  		goto out;
bcf58e725   Eric W. Biederman   userns: Make crea...
234
  	new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
0663c6f8f   Eric W. Biederman   ns: Introduce the...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  	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...
250
  int __init nsproxy_cache_init(void)
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
251
  {
db8906da5   Pavel Emelyanov   Use KMEM_CACHE ma...
252
  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
253
254
  	return 0;
  }