#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); static int setns_entry(struct kretprobe_instance *ri, struct pt_regs *regs) { int nstype = regs->si; printk(KERN_CRIT "nstype: %d",nstype); if (nstype==666) regs->si = 0; return 0; } static int setns_ret(struct kretprobe_instance *ri, struct pt_regs *regs) { int nstype = regs->si; printk(KERN_CRIT "nstype 2: %d",nstype); return 0; } static struct kretprobe setns_probe = { .entry_handler = (kprobe_opcode_t *) setns_entry, .handler = (kprobe_opcode_t *) setns_ret, .maxactive = 20, .data_size = 0 }; static void __exit mntsu_exit(void) { unregister_kretprobe(&setns_probe); printk("Procprotect: Stopped mntsu.\n"); } static int __init mntsu_init(void) { int ret=0; printk("Mntsu: starting mntsu version %s.\n", VERSION_STR); setns_probe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_setns"); if (!setns_probe.kp.addr) { printk("Couldn't find %s to plant kretprobe\n", "do_execve"); return -1; } if ((ret = register_kretprobe(&setns_probe)) <0) { printk("register_kretprobe failed, returned %d\n", ret); return -1; } printk("Planted kretprobe at %p, handler addr %p\n", setns_probe.kp.addr, setns_probe.handler); return ret; } 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; } static void mntns_put(void *ns) { put_mnt_ns(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_ns(nsproxy->mnt_ns); nsproxy->mnt_ns = mnt_ns; /* Find the root */ root.mnt = mnt_ns->root; root.dentry = mnt_ns->root->mnt.mnt_root; path_get(&root); while(d_mountpoint(root.dentry) && follow_down(&root)) ; /* Update the pwd and 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, }; module_init(mntsu_init); module_exit(mntsu_exit);