Blame view

kernel/nsproxy.c 5.1 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
15
16
17
18
   */
  
  #include <linux/module.h>
  #include <linux/version.h>
  #include <linux/nsproxy.h>
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
19
  #include <linux/init_task.h>
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
20
  #include <linux/mnt_namespace.h>
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
21
  #include <linux/utsname.h>
9a575a92d   Cedric Le Goater   [PATCH] to nsproxy
22
  #include <linux/pid_namespace.h>
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
23
  #include <net/net_namespace.h>
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
24

98c0d07cb   Cedric Le Goater   add a kmem_cache ...
25
  static struct kmem_cache *nsproxy_cachep;
0437eb594   Serge E. Hallyn   [PATCH] nsproxy: ...
26
  struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
27

ab516013a   Serge E. Hallyn   [PATCH] namespace...
28
29
  /*
   * creates a copy of "orig" with refcount 1.
ab516013a   Serge E. Hallyn   [PATCH] namespace...
30
   */
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
31
  static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
32
33
  {
  	struct nsproxy *ns;
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
34
35
36
  	ns = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
  	if (ns) {
  		memcpy(ns, orig, sizeof(struct nsproxy));
ab516013a   Serge E. Hallyn   [PATCH] namespace...
37
  		atomic_set(&ns->count, 1);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
38
  	}
ab516013a   Serge E. Hallyn   [PATCH] namespace...
39
40
41
42
  	return ns;
  }
  
  /*
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
43
44
45
   * 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...
46
   */
213dd266d   Eric W. Biederman   namespace: ensure...
47
48
  static struct nsproxy *create_new_namespaces(unsigned long flags,
  			struct task_struct *tsk, struct fs_struct *new_fs)
ab516013a   Serge E. Hallyn   [PATCH] namespace...
49
  {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
50
  	struct nsproxy *new_nsp;
467e9f4b5   Cedric Le Goater   fix create_new_na...
51
  	int err;
ab516013a   Serge E. Hallyn   [PATCH] namespace...
52

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
53
54
55
  	new_nsp = clone_nsproxy(tsk->nsproxy);
  	if (!new_nsp)
  		return ERR_PTR(-ENOMEM);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
56

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
57
  	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
467e9f4b5   Cedric Le Goater   fix create_new_na...
58
59
  	if (IS_ERR(new_nsp->mnt_ns)) {
  		err = PTR_ERR(new_nsp->mnt_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
60
  		goto out_ns;
467e9f4b5   Cedric Le Goater   fix create_new_na...
61
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
62
63
  
  	new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
64
65
  	if (IS_ERR(new_nsp->uts_ns)) {
  		err = PTR_ERR(new_nsp->uts_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
66
  		goto out_uts;
467e9f4b5   Cedric Le Goater   fix create_new_na...
67
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
68
69
  
  	new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
70
71
  	if (IS_ERR(new_nsp->ipc_ns)) {
  		err = PTR_ERR(new_nsp->ipc_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
72
  		goto out_ipc;
467e9f4b5   Cedric Le Goater   fix create_new_na...
73
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
74

2894d650c   Sukadev Bhattiprolu   pid namespaces: d...
75
  	new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
467e9f4b5   Cedric Le Goater   fix create_new_na...
76
77
  	if (IS_ERR(new_nsp->pid_ns)) {
  		err = PTR_ERR(new_nsp->pid_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
78
  		goto out_pid;
467e9f4b5   Cedric Le Goater   fix create_new_na...
79
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
80

acce292c8   Cedric Le Goater   user namespace: a...
81
  	new_nsp->user_ns = copy_user_ns(flags, tsk->nsproxy->user_ns);
467e9f4b5   Cedric Le Goater   fix create_new_na...
82
83
  	if (IS_ERR(new_nsp->user_ns)) {
  		err = PTR_ERR(new_nsp->user_ns);
acce292c8   Cedric Le Goater   user namespace: a...
84
  		goto out_user;
467e9f4b5   Cedric Le Goater   fix create_new_na...
85
  	}
acce292c8   Cedric Le Goater   user namespace: a...
86

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

858d72ead   Serge E. Hallyn   cgroups: implemen...
140
141
142
143
144
  	err = ns_cgroup_clone(tsk);
  	if (err) {
  		put_nsproxy(new_ns);
  		goto out;
  	}
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
145
  	tsk->nsproxy = new_ns;
858d72ead   Serge E. Hallyn   cgroups: implemen...
146

1651e14e2   Serge E. Hallyn   [PATCH] namespace...
147
  out:
444f378b2   Linus Torvalds   Revert "[PATCH] n...
148
  	put_nsproxy(old_ns);
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
149
  	return err;
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
160
161
  	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);
acce292c8   Cedric Le Goater   user namespace: a...
162
163
  	if (ns->user_ns)
  		put_user_ns(ns->user_ns);
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
164
  	put_net(ns->net_ns);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
165
  	kmem_cache_free(nsproxy_cachep, ns);
ab516013a   Serge E. Hallyn   [PATCH] namespace...
166
  }
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
167
168
169
  
  /*
   * Called from unshare. Unshare all the namespaces part of nsproxy.
4e71e474c   Cedric Le Goater   fix refcounting o...
170
   * On success, returns the new nsproxy.
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
171
172
173
174
   */
  int unshare_nsproxy_namespaces(unsigned long unshare_flags,
  		struct nsproxy **new_nsp, struct fs_struct *new_fs)
  {
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
175
  	int err = 0;
77ec739d8   Serge E. Hallyn   user namespace: a...
176
  	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
9dd776b6d   Eric W. Biederman   [NET]: Add networ...
177
  			       CLONE_NEWUSER | CLONE_NEWNET)))
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
178
  		return 0;
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
179
180
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
181
182
  	*new_nsp = create_new_namespaces(unshare_flags, current,
  				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
187
188
189
190
191
192
  		goto out;
  	}
  
  	err = ns_cgroup_clone(current);
  	if (err)
  		put_nsproxy(*new_nsp);
  
  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);
  }
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
222
223
  static int __init nsproxy_cache_init(void)
  {
db8906da5   Pavel Emelyanov   Use KMEM_CACHE ma...
224
  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
98c0d07cb   Cedric Le Goater   add a kmem_cache ...
225
226
227
228
  	return 0;
  }
  
  module_init(nsproxy_cache_init);