diff options
Diffstat (limited to 'kernel/nsproxy.c')
| -rw-r--r-- | kernel/nsproxy.c | 42 | 
1 files changed, 42 insertions, 0 deletions
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index a05d191ffdd..5424e37673e 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -22,6 +22,9 @@  #include <linux/pid_namespace.h>  #include <net/net_namespace.h>  #include <linux/ipc_namespace.h> +#include <linux/proc_fs.h> +#include <linux/file.h> +#include <linux/syscalls.h>  static struct kmem_cache *nsproxy_cachep; @@ -233,6 +236,45 @@ void exit_task_namespaces(struct task_struct *p)  	switch_task_namespaces(p, NULL);  } +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; +} +  static int __init nsproxy_cache_init(void)  {  	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);  |