From: Sapan Bhatia Date: Wed, 5 Sep 2012 11:00:45 +0000 (-0400) Subject: Pid and mnt namespace support in lxcsu X-Git-Tag: lxcsu-0.2-1~1 X-Git-Url: http://git.onelab.eu/?p=lxc-kernelspace-obsolete.git;a=commitdiff_plain;h=7fc32ca36e05b7abb54df84fd5fd3664a62c7784 Pid and mnt namespace support in lxcsu --- diff --git a/mntsu.c b/mntsu.c new file mode 100644 index 0000000..34cfb56 --- /dev/null +++ b/mntsu.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mount.h" + +#define VERSION_STR "0.0.1" + +#ifndef CONFIG_X86_64 +#error "This code does not support your architecture" +#endif + +MODULE_AUTHOR("Sapan Bhatia "); +MODULE_DESCRIPTION("Hack to enable mount namespace switching via setns. Based on a patch by Eric Biederman."); +MODULE_LICENSE("GPL"); +MODULE_VERSION(VERSION_STR); + +struct proc_dir_entry *proc_entry; + +static void *mntns_get(struct task_struct *task) +{ + struct mnt_namespace *ns; + rcu_read_lock(); + ns = task->nsproxy->mnt_ns; + atomic_inc(&ns->count); + rcu_read_unlock(); + return ns; +} + +void (*put_mnt_ns2)(struct mnt_namespace *ns); + +static void mntns_put(void *ns) +{ + (*put_mnt_ns2)(ns); +} + +static int mntns_install(struct nsproxy *nsproxy, void *ns) +{ + struct fs_struct *fs = current->fs; + struct mnt_namespace *mnt_ns = ns; + struct path root; + + if (fs->users != 1) + return -EINVAL; + + atomic_inc(&mnt_ns->count); + (*put_mnt_ns2)(nsproxy->mnt_ns); + nsproxy->mnt_ns = mnt_ns; + + root.mnt = &mnt_ns->root->mnt; + root.dentry = mnt_ns->root->mnt.mnt_root; + path_get(&root); + while(d_mountpoint(root.dentry) && follow_down(&root)) + ; + + path_get(&root); + path_get(&root); + path_put(&fs->root); + path_put(&fs->pwd); + fs->root = root; + fs->pwd = root; + path_put(&root); + + return 0; +} + +const struct proc_ns_operations mntns_operations = { + .name = "mnt_ns", + .get = mntns_get, + .put = mntns_put, + .install = mntns_install, +}; + +void (*free_nsproxy2)(struct nsproxy *ns); + +struct nsproxy * (*create_new_namespaces)(unsigned long flags, + struct task_struct *tsk, struct fs_struct *new_fs); + +void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new); + +static int setns(struct task_struct *reftask) { + const struct proc_ns_operations *ops; + struct task_struct *tsk = current; + struct nsproxy *new_nsproxy; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = -EINVAL; + ops = &mntns_operations; + + 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, reftask->nsproxy->mnt_ns); + if (err) { + (*free_nsproxy2)(new_nsproxy); + goto out; + } + (*switch_task_namespaces2)(tsk, new_nsproxy); + return 0; +out: + return err; + +} + +static void __exit lxcsu_exit(void) +{ + remove_proc_entry("lxcsu",NULL); + printk("Procprotect: Stopped lxcsu.\n"); +} + +int lxcsu_write(struct file *file, const char *buffer, unsigned long count, void *data) { + char pidname[PATH_MAX]; + int pid; + struct pid *p; + char **s; + struct task_struct *task; + + if (current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) + return -EPERM; + + if (copy_from_user(pidname, buffer, count)) { + return -EFAULT; + } + if (count && (pidname[count-1]==10 || pidname[count-1]==13)) { + pidname[count-1]='\0'; + } + else + pidname[count]='\0'; + + pid = simple_strtol(pidname,s,10); + p = find_vpid(pid); + task = get_pid_task(p,PIDTYPE_PID); + if (task) { + setns(task); + } + else { + printk(KERN_CRIT "Task %d not found",pid); + } + + return count; +} + + +static int __init lxcsu_init(void) +{ + int ret=0; + printk("Mntsu: starting lxcsu version %s.\n", + VERSION_STR); + + + free_nsproxy2 = kallsyms_lookup_name("free_nsproxy"); + printk(KERN_CRIT "free_nsproxy = %x",free_nsproxy2); + + switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces"); + printk(KERN_CRIT "switch_task_namespaces = %x",switch_task_namespaces2); + + create_new_namespaces = kallsyms_lookup_name("create_new_namespaces"); + printk(KERN_CRIT "create_new_namespaces = %x",create_new_namespaces); + + put_mnt_ns2 = kallsyms_lookup_name("put_mnt_ns"); + printk(KERN_CRIT "Put mnt ns = %x",put_mnt_ns2); + + proc_entry = create_proc_entry("lxcsu", 0644, NULL); + proc_entry->write_proc = lxcsu_write; + return ret; +} + +module_init(lxcsu_init); +module_exit(lxcsu_exit); diff --git a/pidsu.c b/pidsu.c new file mode 100644 index 0000000..fa09133 --- /dev/null +++ b/pidsu.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mount.h" + +#define VERSION_STR "0.0.1" + +#ifndef CONFIG_X86_64 +#error "This code does not support your architecture" +#endif + +MODULE_AUTHOR("Sapan Bhatia "); +MODULE_DESCRIPTION("Hack to enable pid namespace switching via setns. Based on a patch by Eric Biederman."); +MODULE_LICENSE("GPL"); +MODULE_VERSION(VERSION_STR); + +struct proc_dir_entry *proc_entry; + +/* + * Pid namespaces + * + * Authors: + * (C) 2007 Pavel Emelyanov , OpenVZ, SWsoft Inc. + * (C) 2007 Sukadev Bhattiprolu , IBM + * Many thanks to Oleg Nesterov for comments and help + * + */ + +#define BITS_PER_PAGE (PAGE_SIZE*8) + +void (*free_nsproxy2)(struct nsproxy *ns); +struct nsproxy * (*create_new_namespaces)(unsigned long flags, + struct task_struct *tsk, struct fs_struct *new_fs); + +void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new); +void (*free_pid_ns2)(struct kref *kref); + + +struct pid_cache { + int nr_ids; + char name[16]; + struct kmem_cache *cachep; + struct list_head list; +}; + +static LIST_HEAD(pid_caches_lh); +static DEFINE_MUTEX(pid_caches_mutex); + +static void *pidns_get(struct task_struct *task) +{ + struct pid_namespace *ns; + + rcu_read_lock(); + ns = get_pid_ns(task_active_pid_ns(task)); + rcu_read_unlock(); + + return ns; +} + +static void pidns_put(void *ns) +{ + struct pid_namespace *pidns = ns; + if (pidns != &init_pid_ns) + kref_put(&pidns->kref, free_pid_ns2); +} + +static int pidns_install(struct nsproxy *nsproxy, void *ns) +{ + printk(KERN_CRIT "Entering pid ns"); + pidns_put(nsproxy->pid_ns); + nsproxy->pid_ns = get_pid_ns(ns); + return 0; +} + +const struct proc_ns_operations pidns_operations = { + .name = "pid", + .type = CLONE_NEWPID, + .get = pidns_get, + .put = pidns_put, + .install = pidns_install, +}; + +static int setns(struct task_struct *reftask) { + const struct proc_ns_operations *ops; + struct task_struct *tsk = current; + struct nsproxy *new_nsproxy; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = -EINVAL; + ops = &pidns_operations; + + 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, reftask->nsproxy->pid_ns); + if (err) { + (*free_nsproxy2)(new_nsproxy); + goto out; + } + (*switch_task_namespaces2)(tsk, new_nsproxy); + return 0; +out: + return err; + +} + +static void __exit pidsu_exit(void) +{ + remove_proc_entry("pidsu",NULL); + printk("Procprotect: Stopped pidsu.\n"); +} + +int pidsu_write(struct file *file, const char *buffer, unsigned long count, void *data) { + char pidname[80]; + int pid; + struct pid *p; + char **s; + struct task_struct *task; + + if (current->nsproxy->pid_ns!=init_task.nsproxy->pid_ns) + return -EPERM; + + if (copy_from_user(pidname, buffer, count)) { + return -EFAULT; + } + if (count && (pidname[count-1]==10 || pidname[count-1]==13)) { + pidname[count-1]='\0'; + } + else + pidname[count]='\0'; + + pid = simple_strtol(pidname,s,10); + p = find_vpid(pid); + task = get_pid_task(p,PIDTYPE_PID); + if (task) { + setns(task); + } + else { + printk(KERN_CRIT "Task %d not found",pid); + } + + return count; +} + +static int __init pidsu_init(void) +{ + int ret=0; + printk("Mntsu: starting pidsu version %s.\n", + VERSION_STR); + + free_pid_ns2 = kallsyms_lookup_name("free_pid_ns"); + printk(KERN_CRIT "free_pid_ns = %x",free_pid_ns2); + + free_nsproxy2 = kallsyms_lookup_name("free_nsproxy"); + printk(KERN_CRIT "free_nsproxy = %x",(unsigned int) free_nsproxy2); + + switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces"); + printk(KERN_CRIT "switch_task_namespaces = %x",(unsigned int) switch_task_namespaces2); + + create_new_namespaces = kallsyms_lookup_name("create_new_namespaces"); + printk(KERN_CRIT "create_new_namespaces = %x",(unsigned int) create_new_namespaces); + + /*put_pid_ns2 = kallsyms_lookup_name("put_pid_ns"); + printk(KERN_CRIT "Put pid ns = %x",put_pid_ns2);*/ + + proc_entry = create_proc_entry("pidsu", 0644, NULL); + proc_entry->write_proc = pidsu_write; + return ret; +} + +module_init(pidsu_init); +module_exit(pidsu_exit);