d16ad80b16da431cd3a939629d7b644811c5f792
[lxc-kernelspace-obsolete.git] / mntsu.c
1 #include <linux/module.h>
2 #include <linux/moduleparam.h>
3 #include <linux/types.h>
4 #include <linux/kernel.h>
5 #include <linux/fs_struct.h>
6 #include <linux/fs.h>
7 #include <linux/mm.h>
8 #include <linux/reboot.h>
9 #include <linux/delay.h>
10 #include <linux/proc_fs.h>
11 #include <asm/uaccess.h>
12 #include <linux/sysrq.h>
13 #include <linux/timer.h>
14 #include <linux/time.h>
15 #include <linux/lglock.h>
16 #include <linux/init.h>
17 #include <linux/idr.h>
18 #include <linux/namei.h>
19 #include <linux/bitops.h>
20 #include <linux/mnt_namespace.h>
21 #include <linux/path.h>
22 #include <linux/dcache.h>
23 #include <linux/spinlock.h>
24 #include <linux/completion.h>
25 #include <linux/sched.h>
26 #include <linux/seq_file.h>
27 #include <linux/file.h>
28 #include <linux/kprobes.h>
29 #include <linux/kallsyms.h>
30 #include <linux/nsproxy.h>
31 #include "mount.h"
32
33 #define VERSION_STR "0.0.1"
34
35 #ifndef CONFIG_X86_64
36 #error "This code does not support your architecture"
37 #endif
38
39 MODULE_AUTHOR("Sapan Bhatia <sapanb@cs.princeton.edu>");
40 MODULE_DESCRIPTION("Hack to enable mount namespace switching via setns. Based on a patch by Eric Biederman.");
41 MODULE_LICENSE("GPL");
42 MODULE_VERSION(VERSION_STR);
43
44
45 static void *mntns_get(struct task_struct *task)
46 {
47        struct mnt_namespace *ns;
48        rcu_read_lock();
49        ns = task->nsproxy->mnt_ns;
50        atomic_inc(&ns->count);
51        rcu_read_unlock();
52        return ns;
53 }
54
55 void (*put_mnt_ns2)(struct mnt_namespace *ns);
56
57 static void mntns_put(void *ns)
58 {
59        (*put_mnt_ns2)(ns);
60 }
61
62 static int mntns_install(struct nsproxy *nsproxy, void *ns)
63 {
64        struct fs_struct *fs = current->fs;
65        struct mnt_namespace *mnt_ns = ns;
66        struct path root;
67
68        if (fs->users != 1)
69                return -EINVAL;
70
71        atomic_inc(&mnt_ns->count);
72        (*put_mnt_ns2)(nsproxy->mnt_ns);
73        nsproxy->mnt_ns = mnt_ns;
74
75        /* Find the root */
76        root.mnt    = mnt_ns->root;
77        root.dentry = mnt_ns->root->mnt.mnt_root;
78        path_get(&root);
79        while(d_mountpoint(root.dentry) && follow_down(&root))
80                ;
81
82        /* Update the pwd and root */
83        path_get(&root);
84        path_get(&root);
85        path_put(&fs->root);
86        path_put(&fs->pwd);
87        fs->root = root;
88        fs->pwd  = root;
89        path_put(&root);
90
91        return 0;
92 }
93
94 const struct proc_ns_operations mntns_operations = {
95        .name           = "mnt_ns",
96        .get            = mntns_get,
97        .put            = mntns_put,
98        .install        = mntns_install,
99 };
100
101 void (*free_nsproxy2)(struct nsproxy *ns);
102 struct file *(*proc_ns_fget2)(int fd);
103
104 struct nsproxy * (*create_new_namespaces)(unsigned long flags,
105                         struct task_struct *tsk, struct fs_struct *new_fs);
106
107 void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new);
108
109 static int setns_entry(int fd, int nstype) {
110     if (nstype==666) {
111         const struct proc_ns_operations *ops;
112         struct task_struct *tsk = current;
113         struct nsproxy *new_nsproxy;
114         struct proc_inode *ei;
115         struct file *file;
116         int err;
117
118         if (!capable(CAP_SYS_ADMIN))
119             return -EPERM;
120
121         file = (*proc_ns_fget2)(fd);
122         if (IS_ERR(file))
123             return PTR_ERR(file);
124
125         err = -EINVAL;
126         ei = PROC_I(file->f_dentry->d_inode);
127         ops = &mntns_operations;
128
129         new_nsproxy = (*create_new_namespaces)(0, tsk, tsk->fs);
130         if (IS_ERR(new_nsproxy)) {
131             err = PTR_ERR(new_nsproxy);
132             goto out;
133         }
134
135         err = ops->install(new_nsproxy, ei->ns);
136         if (err) {
137             (*free_nsproxy2)(new_nsproxy);
138             goto out;
139         }
140         (*switch_task_namespaces2)(tsk, new_nsproxy);
141 out:
142         fput(file);
143     }
144
145     jprobe_return();
146     return 0;
147 }
148
149 static struct jprobe setns_jprobe = {
150         .entry = (kprobe_opcode_t *) setns_entry
151 };
152
153 static void __exit mntsu_exit(void)
154 {
155         unregister_jprobe(&setns_jprobe);
156         printk("Procprotect: Stopped mntsu.\n");
157 }
158
159 static int __init mntsu_init(void)
160 {
161                 int ret=0;
162         printk("Mntsu: starting mntsu version %s.\n",
163                VERSION_STR);
164         proc_ns_fget2 = kallsyms_lookup_name("proc_ns_fget");
165         printk(KERN_CRIT "proc_ns_fget = %x",proc_ns_fget2);
166
167
168         free_nsproxy2 = kallsyms_lookup_name("free_nsproxy");
169         printk(KERN_CRIT "free_nsproxy = %x",free_nsproxy2);
170
171         switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces");
172         printk(KERN_CRIT "switch_task_namespaces = %x",switch_task_namespaces2);
173
174         create_new_namespaces = kallsyms_lookup_name("create_new_namespaces");
175         printk(KERN_CRIT "create_new_namespaces = %x",create_new_namespaces);
176
177         put_mnt_ns2 = kallsyms_lookup_name("put_mnt_ns");
178         printk(KERN_CRIT "Put mnt ns = %x",put_mnt_ns2);
179
180           setns_jprobe.kp.addr = 
181                   (kprobe_opcode_t *) kallsyms_lookup_name("sys_setns");
182           if (!setns_jprobe.kp.addr) {
183                   printk("Couldn't find %s to plant jprobe\n", "do_execve");
184                   return -1;
185           }
186   
187           if ((ret = register_jprobe(&setns_jprobe)) <0) {
188                   printk("register_jprobe failed, returned %d\n", ret);
189                   return -1;
190           }
191
192         return ret;
193 }
194
195 module_init(mntsu_init);
196 module_exit(mntsu_exit);