Removed debug message
[lxc-kernelspace-obsolete.git] / lxcsu.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 struct proc_dir_entry *proc_entry;
45
46 static void *mntns_get(struct task_struct *task)
47 {
48        struct mnt_namespace *ns;
49        rcu_read_lock();
50        ns = task->nsproxy->mnt_ns;
51        atomic_inc(&ns->count);
52        rcu_read_unlock();
53        return ns;
54 }
55
56 void (*put_mnt_ns2)(struct mnt_namespace *ns);
57
58 static void mntns_put(void *ns)
59 {
60        (*put_mnt_ns2)(ns);
61 }
62
63 static int mntns_install(struct nsproxy *nsproxy, void *ns)
64 {
65        struct fs_struct *fs = current->fs;
66        struct mnt_namespace *mnt_ns = ns;
67        struct path root;
68
69        if (fs->users != 1)
70                return -EINVAL;
71
72        atomic_inc(&mnt_ns->count);
73        (*put_mnt_ns2)(nsproxy->mnt_ns);
74        nsproxy->mnt_ns = mnt_ns;
75
76        root.mnt    = &mnt_ns->root->mnt;
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        path_get(&root);
83        path_get(&root);
84        path_put(&fs->root);
85        path_put(&fs->pwd);
86        fs->root = root;
87        fs->pwd  = root;
88        path_put(&root);
89
90        return 0;
91 }
92
93 const struct proc_ns_operations mntns_operations = {
94        .name           = "mnt_ns",
95        .get            = mntns_get,
96        .put            = mntns_put,
97        .install        = mntns_install,
98 };
99
100 void (*free_nsproxy2)(struct nsproxy *ns);
101
102 struct nsproxy * (*create_new_namespaces)(unsigned long flags,
103                         struct task_struct *tsk, struct fs_struct *new_fs);
104
105 void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new);
106
107 static int setns(struct task_struct *reftask) {
108         const struct proc_ns_operations *ops;
109         struct task_struct *tsk = current;
110         struct nsproxy *new_nsproxy;
111         int err;
112
113         if (!capable(CAP_SYS_ADMIN))
114             return -EPERM;
115
116         err = -EINVAL;
117         ops = &mntns_operations;
118
119         new_nsproxy = (*create_new_namespaces)(0, tsk, tsk->fs);
120         if (IS_ERR(new_nsproxy)) {
121             err = PTR_ERR(new_nsproxy);
122             goto out;
123         }
124
125         err = ops->install(new_nsproxy, reftask->nsproxy->mnt_ns);
126         if (err) {
127             (*free_nsproxy2)(new_nsproxy);
128             goto out;
129         }
130         (*switch_task_namespaces2)(tsk, new_nsproxy);
131         return 0;
132 out:
133         return err;
134
135 }
136
137 static void __exit lxcsu_exit(void)
138 {
139         remove_proc_entry("lxcsu",NULL);
140         printk("Procprotect: Stopped lxcsu.\n");
141 }
142
143 int lxcsu_write(struct file *file, const char *buffer, unsigned long count, void *data) {
144         char pidname[PATH_MAX];
145     int pid;
146     struct pid *p;
147     char **s;
148     struct task_struct *task;
149
150         if (current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns)
151                 return -EPERM;
152
153         if (copy_from_user(pidname, buffer, count)) {
154                 return -EFAULT;
155         }
156         if (count && (pidname[count-1]==10 || pidname[count-1]==13)) {
157                 pidname[count-1]='\0';
158         }
159         else
160                 pidname[count]='\0';
161
162     pid = simple_strtol(pidname,s,10);
163     p = find_vpid(pid);
164     task = get_pid_task(p,PIDTYPE_PID);
165     if (task) {
166         setns(task);
167     }
168     else {
169         printk(KERN_CRIT "Task %d not found",pid);
170     }
171
172         return count;
173 }
174
175
176 static int __init lxcsu_init(void)
177 {
178                 int ret=0;
179         printk("Mntsu: starting lxcsu version %s.\n",
180                VERSION_STR);
181
182         free_nsproxy2 = kallsyms_lookup_name("free_nsproxy");
183         printk(KERN_CRIT "free_nsproxy = %x",free_nsproxy2);
184
185         switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces");
186         printk(KERN_CRIT "switch_task_namespaces = %x",switch_task_namespaces2);
187
188         create_new_namespaces = kallsyms_lookup_name("create_new_namespaces");
189         printk(KERN_CRIT "create_new_namespaces = %x",create_new_namespaces);
190
191         put_mnt_ns2 = kallsyms_lookup_name("put_mnt_ns");
192         printk(KERN_CRIT "Put mnt ns = %x",put_mnt_ns2);
193
194         proc_entry = create_proc_entry("lxcsu", 0644, NULL);
195             proc_entry->write_proc = lxcsu_write;
196         return ret;
197 }
198
199 module_init(lxcsu_init);
200 module_exit(lxcsu_exit);