diff options
| -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 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 | ||
| 26 | static struct kmem_cache *nsproxy_cachep; | 29 | static 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 | ||
| 239 | SYSCALL_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); | ||
| 273 | out: | ||
| 274 | fput(file); | ||
| 275 | return err; | ||
| 276 | } | ||
| 277 | |||
| 236 | static int __init nsproxy_cache_init(void) | 278 | static int __init nsproxy_cache_init(void) |
| 237 | { | 279 | { |
| 238 | nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC); | 280 | nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC); |
