First commit of mntsu tool
[lxc-kernelspace-obsolete.git] / mntsu.c
diff --git a/mntsu.c b/mntsu.c
new file mode 100644 (file)
index 0000000..ce35655
--- /dev/null
+++ b/mntsu.c
@@ -0,0 +1,150 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs_struct.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/reboot.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/sysrq.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/lglock.h>
+#include <linux/init.h>
+#include <linux/idr.h>
+#include <linux/namei.h>
+#include <linux/bitops.h>
+#include <linux/mnt_namespace.h>
+#include <linux/path.h>
+#include <linux/dcache.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include <linux/nsproxy.h>
+#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 <sapanb@cs.princeton.edu>");
+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);