--- /dev/null
+#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);
--- /dev/null
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+
+struct mnt_namespace {
+ atomic_t count;
+ struct mount * root;
+ struct list_head list;
+ wait_queue_head_t poll;
+ int event;
+};
+
+struct mnt_pcp {
+ int mnt_count;
+ int mnt_writers;
+};
+
+struct mount {
+ struct list_head mnt_hash;
+ struct mount *mnt_parent;
+ struct dentry *mnt_mountpoint;
+ struct vfsmount mnt;
+#ifdef CONFIG_SMP
+ struct mnt_pcp __percpu *mnt_pcp;
+ atomic_t mnt_longterm; /* how many of the refs are longterm */
+#else
+ int mnt_count;
+ int mnt_writers;
+#endif
+ struct list_head mnt_mounts; /* list of children, anchored here */
+ struct list_head mnt_child; /* and going through their mnt_child */
+ struct list_head mnt_instance; /* mount instance on sb->s_mounts */
+ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
+ struct list_head mnt_list;
+ struct list_head mnt_expire; /* link in fs-specific expiry list */
+ struct list_head mnt_share; /* circular list of shared mounts */
+ struct list_head mnt_slave_list;/* list of slave mounts */
+ struct list_head mnt_slave; /* slave list entry */
+ struct mount *mnt_master; /* slave is on master->mnt_slave_list */
+ struct mnt_namespace *mnt_ns; /* containing namespace */
+#ifdef CONFIG_FSNOTIFY
+ struct hlist_head mnt_fsnotify_marks;
+ __u32 mnt_fsnotify_mask;
+#endif
+ int mnt_id; /* mount identifier */
+ int mnt_group_id; /* peer group identifier */
+ int mnt_expiry_mark; /* true if marked for expiry */
+ int mnt_pinned;
+ int mnt_ghosts;
+};
+
+static inline struct mount *real_mount(struct vfsmount *mnt)
+{
+ return container_of(mnt, struct mount, mnt);
+}
+
+static inline int mnt_has_parent(struct mount *mnt)
+{
+ return mnt != mnt->mnt_parent;
+}
+
+extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+
+static inline void get_mnt_ns(struct mnt_namespace *ns)
+{
+ atomic_inc(&ns->count);
+}
+
+struct proc_mounts {
+ struct seq_file m; /* must be the first element */
+ struct mnt_namespace *ns;
+ struct path root;
+ int (*show)(struct seq_file *, struct vfsmount *);
+};
+
+extern const struct seq_operations mounts_op;