Blame view

kernel/nsproxy.c 5.26 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>
ab516013a   Serge E. Hallyn   [PATCH] namespace...
16
  #include <linux/module.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>
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
24

98c0d07cb   Cedric Le Goater   add a kmem_cache ...
25
  static struct kmem_cache *nsproxy_cachep;
8467005da   Alexey Dobriyan   nsproxy: remove I...
26
27
28
29
30
31
32
33
34
35
36
37
  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...
38

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

90af90d7d   Alexey Dobriyan   nsproxy: extract ...
43
44
45
46
  	nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
  	if (nsproxy)
  		atomic_set(&nsproxy->count, 1);
  	return nsproxy;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
47
48
49
  }
  
  /*
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
50
51
52
   * 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...
53
   */
213dd266d   Eric W. Biederman   namespace: ensure...
54
55
  static struct nsproxy *create_new_namespaces(unsigned long flags,
  			struct task_struct *tsk, struct fs_struct *new_fs)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
56
  {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
57
  	struct nsproxy *new_nsp;
467e9f4b5   Cedric Le Goater   fix create_new_na...
58
  	int err;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
59

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

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
64
  	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
467e9f4b5   Cedric Le Goater   fix create_new_na...
65
66
  	if (IS_ERR(new_nsp->mnt_ns)) {
  		err = PTR_ERR(new_nsp->mnt_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
67
  		goto out_ns;
467e9f4b5   Cedric Le Goater   fix create_new_na...
68
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
69
70
  
  	new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
71
72
  	if (IS_ERR(new_nsp->uts_ns)) {
  		err = PTR_ERR(new_nsp->uts_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
73
  		goto out_uts;
467e9f4b5   Cedric Le Goater   fix create_new_na...
74
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
75
76
  
  	new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
77
78
  	if (IS_ERR(new_nsp->ipc_ns)) {
  		err = PTR_ERR(new_nsp->ipc_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
79
  		goto out_ipc;
467e9f4b5   Cedric Le Goater   fix create_new_na...
80
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
81

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

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

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

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

cf7b708c8   Pavel Emelyanov   Make access to ta...
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
222
  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);
  }
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
223
224
  static int __init nsproxy_cache_init(void)
  {
db8906da5   Pavel Emelyanov   Use KMEM_CACHE ma...
225
  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
226
227
228
229
  	return 0;
  }
  
  module_init(nsproxy_cache_init);