aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/nsproxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/nsproxy.c')
-rw-r--r--kernel/nsproxy.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index a05d191ffdd9..5424e37673ed 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -22,6 +22,9 @@
22#include <linux/pid_namespace.h> 22#include <linux/pid_namespace.h>
23#include <net/net_namespace.h> 23#include <net/net_namespace.h>
24#include <linux/ipc_namespace.h> 24#include <linux/ipc_namespace.h>
25#include <linux/proc_fs.h>
26#include <linux/file.h>
27#include <linux/syscalls.h>
25 28
26static struct kmem_cache *nsproxy_cachep; 29static struct kmem_cache *nsproxy_cachep;
27 30
@@ -233,6 +236,45 @@ void exit_task_namespaces(struct task_struct *p)
233 switch_task_namespaces(p, NULL); 236 switch_task_namespaces(p, NULL);
234} 237}
235 238
239SYSCALL_DEFINE2(setns, int, fd, int, nstype)
240{
241 const struct proc_ns_operations *ops;
242 struct task_struct *tsk = current;
243 struct nsproxy *new_nsproxy;
244 struct proc_inode *ei;
245 struct file *file;
246 int err;
247
248 if (!capable(CAP_SYS_ADMIN))
249 return -EPERM;
250
251 file = proc_ns_fget(fd);
252 if (IS_ERR(file))
253 return PTR_ERR(file);
254
255 err = -EINVAL;
256 ei = PROC_I(file->f_dentry->d_inode);
257 ops = ei->ns_ops;
258 if (nstype && (ops->type != nstype))
259 goto out;
260
261 new_nsproxy = create_new_namespaces(0, tsk, tsk->fs);
262 if (IS_ERR(new_nsproxy)) {
263 err = PTR_ERR(new_nsproxy);
264 goto out;
265 }
266
267 err = ops->install(new_nsproxy, ei->ns);
268 if (err) {
269 free_nsproxy(new_nsproxy);
270 goto out;
271 }
272 switch_task_namespaces(tsk, new_nsproxy);
273out:
274 fput(file);
275 return err;
276}
277
236static int __init nsproxy_cache_init(void) 278static int __init nsproxy_cache_init(void)
237{ 279{
238 nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC); 280 nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);