From: Sapan Bhatia Date: Mon, 13 Aug 2012 09:29:42 +0000 (-0400) Subject: First commit of mntsu tool X-Git-Tag: lxcsu-0.2-1~8 X-Git-Url: http://git.onelab.eu/?p=lxc-kernelspace-obsolete.git;a=commitdiff_plain;h=84ceafa307dc65ec34ff0a20acfe90984374b8ce First commit of mntsu tool --- diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5f0bc71 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +obj-m += mntsu.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/mntsu.c b/mntsu.c new file mode 100644 index 0000000..ce35655 --- /dev/null +++ b/mntsu.c @@ -0,0 +1,150 @@ +#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); diff --git a/mount.h b/mount.h new file mode 100644 index 0000000..4ef36d9 --- /dev/null +++ b/mount.h @@ -0,0 +1,76 @@ +#include +#include +#include + +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;