Merge branch 'kernel' of 106.109.8.71:/srv/git/dbi into kernel
[kernel/swap-modules.git] / us_manager / helper.c
1 #include <dbi_kprobes.h>
2 #include <dbi_kprobes_deps.h>
3 #include <ksyms.h>
4 #include "us_proc_inst.h"
5 #include "us_slot_manager.h"
6 #include "storage.h"
7 #include "sspt/sspt.h"
8 #include "filters/filters_core.h"
9
10 /*
11  ******************************************************************************
12  *                               do_page_fault()                              *
13  ******************************************************************************
14  */
15
16 struct pf_data {
17         unsigned long addr;
18 };
19
20 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
21 {
22         struct pf_data *data = (struct pf_data *)ri->data;
23
24 #if defined(CONFIG_X86)
25         data->addr = read_cr2();
26 #elif defined(CONFIG_ARM)
27         data->addr = regs->ARM_r0;
28 #else
29 #error this architecture is not supported
30 #endif
31
32         return 0;
33 }
34
35 /* Detects when IPs are really loaded into phy mem and installs probes. */
36 static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
37 {
38         struct task_struct *task;
39         struct sspt_proc *proc;
40
41         /*
42          * Because process threads have same address space
43          * we instrument only group_leader of all this threads
44          */
45         task = current->group_leader;
46         if (task->flags & PF_KTHREAD)
47                 return 0;
48
49         proc = sspt_proc_get_by_task(task);
50         if (proc)
51                 goto install_proc;
52
53         task = check_task(task);
54         if (task) {
55                 proc = sspt_proc_get_new(task);
56                 goto install_proc;
57         }
58
59         return 0;
60
61 install_proc:
62         if (proc->first_install) {
63                 unsigned long page;
64                 page = ((struct pf_data *)ri->data)->addr & PAGE_MASK;
65                 sspt_proc_install_page(proc, page);
66         } else {
67                 sspt_proc_install(proc);
68         }
69
70         return 0;
71 }
72
73 static struct kretprobe pf_kretprobe = {
74         .entry_handler = entry_handler_pf,
75         .handler = ret_handler_pf,
76         .data_size = sizeof(struct pf_data)
77 };
78
79
80
81 /*
82  ******************************************************************************
83  *                              copy_process()                                *
84  ******************************************************************************
85  */
86
87 static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
88 {
89         sspt_proc_uninstall(proc, child_task, US_DISARM);
90         dbi_disarm_urp_inst_for_task(current, child_task);
91 }
92
93 static void rm_uprobes_child(struct task_struct *task)
94 {
95         struct sspt_proc *proc = sspt_proc_get_by_task(current);
96         if(proc) {
97                 recover_child(task, proc);
98         }
99 }
100
101 /* Delete uprobs in children at fork */
102 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
103 {
104         struct task_struct *task = (struct task_struct *)regs_return_value(regs);
105
106         if(!task || IS_ERR(task))
107                 goto out;
108
109         if(task->mm != current->mm) {   /* check flags CLONE_VM */
110                 rm_uprobes_child(task);
111
112                 if (check_task(current)) {
113                         struct sspt_proc *proc;
114
115                         proc = sspt_proc_get_new(task);
116                         sspt_proc_install(proc);
117                 }
118         }
119 out:
120         return 0;
121 }
122
123 static struct kretprobe cp_kretprobe = {
124         .handler = ret_handler_cp,
125 };
126
127
128
129 /*
130  ******************************************************************************
131  *                                mm_release()                                *
132  ******************************************************************************
133  */
134
135 /* Detects when target process removes IPs. */
136 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
137 {
138         struct sspt_proc *proc = NULL;
139         struct task_struct *task;
140
141 #if defined(CONFIG_X86)
142         task = (struct task_struct *)regs->EREG(ax);
143 #elif defined(CONFIG_ARM)
144         task = (struct task_struct *)regs->ARM_r0;
145 #else
146 #error this architecture is not supported
147 #endif
148
149         if (task->tgid != task->pid) {
150                 goto out;
151         }
152
153         proc = sspt_proc_get_by_task(task);
154         if (proc) {
155                 int ret = sspt_proc_uninstall(proc, task, US_UNREGS_PROBE);
156                 if (ret != 0) {
157                         printk("failed to uninstall IPs (%d)!\n", ret);
158                 }
159
160                 dbi_unregister_all_uprobes(task);
161         }
162
163 out:
164         return 0;
165 }
166
167 static struct kprobe mr_kprobe = {
168         .pre_handler = mr_pre_handler
169 };
170
171
172
173 /*
174  ******************************************************************************
175  *                                 do_munmap()                                *
176  ******************************************************************************
177  */
178
179 static int remove_unmap_probes(struct task_struct *task, struct sspt_proc *proc, unsigned long start, size_t len)
180 {
181         struct mm_struct *mm = task->mm;
182         struct vm_area_struct *vma;
183
184         if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
185                 return -EINVAL;
186         }
187
188         if ((len = PAGE_ALIGN(len)) == 0) {
189                 return -EINVAL;
190         }
191
192         vma = find_vma(mm, start);
193         if (vma && check_vma(vma)) {
194                 struct sspt_file *file;
195                 unsigned long end = start + len;
196                 struct dentry *dentry = vma->vm_file->f_dentry;
197
198                 file = sspt_proc_find_file(proc, dentry);
199                 if (file) {
200                         if (vma->vm_start == start || vma->vm_end == end) {
201                                 sspt_file_uninstall(file, task, US_UNREGS_PROBE);
202                                 file->loaded = 0;
203                         } else {
204                                 unsigned long page_addr;
205                                 struct sspt_page *page;
206
207                                 for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
208                                         page = sspt_find_page_mapped(file, page_addr);
209                                         if (page) {
210                                                 sspt_unregister_page(page, US_UNREGS_PROBE, task);
211                                         }
212                                 }
213
214                                 if (sspt_file_check_install_pages(file)) {
215                                         file->loaded = 0;
216                                 }
217                         }
218                 }
219         }
220
221         return 0;
222 }
223
224 /* Detects when target removes IPs. */
225 static int unmap_pre_handler(struct kprobe *p, struct pt_regs *regs)
226 {
227         /* for ARM */
228         struct mm_struct *mm;
229         unsigned long start;
230         size_t len;
231
232 #if defined(CONFIG_X86)
233         mm = (struct mm_struct *)regs->EREG(ax);
234         start = regs->EREG(dx);
235         len = (size_t)regs->EREG(cx);
236 #elif defined(CONFIG_ARM)
237         mm = (struct mm_struct *)regs->ARM_r0;
238         start = regs->ARM_r1;
239         len = (size_t)regs->ARM_r2;
240 #else
241 #error this architecture is not supported
242 #endif
243
244         struct sspt_proc *proc = NULL;
245         struct task_struct *task = current;
246
247         proc = sspt_proc_get_by_task(task);
248         if (proc) {
249                 if (remove_unmap_probes(task, proc, start, len)) {
250                         printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
251                 }
252         }
253
254 out:
255         return 0;
256 }
257
258 static struct kprobe unmap_kprobe = {
259         .pre_handler = unmap_pre_handler
260 };
261
262
263
264 int register_helper(void)
265 {
266         int ret = 0;
267
268         /* install kprobe on 'do_munmap' to detect when for remove user space probes */
269         ret = dbi_register_kprobe(&unmap_kprobe);
270         if (ret) {
271                 printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
272                 return ret;
273         }
274
275         /* install kprobe on 'mm_release' to detect when for remove user space probes */
276         ret = dbi_register_kprobe(&mr_kprobe);
277         if (ret != 0) {
278                 printk("dbi_register_kprobe(mm_release) result=%d!\n", ret);
279                 goto unregister_unmap;
280         }
281
282
283         /* install kretprobe on 'copy_process' */
284         ret = dbi_register_kretprobe(&cp_kretprobe);
285         if (ret) {
286                 printk("dbi_register_kretprobe(copy_process) result=%d!\n", ret);
287                 goto unregister_mr;
288         }
289
290         /* install kretprobe on 'do_page_fault' to detect when they will be loaded */
291         ret = dbi_register_kretprobe(&pf_kretprobe);
292         if (ret) {
293                 printk("dbi_register_kretprobe(do_page_fault) result=%d!\n", ret);
294                 goto unregister_cp;
295         }
296
297         return ret;
298
299 unregister_cp:
300         dbi_unregister_kretprobe(&cp_kretprobe);
301
302 unregister_mr:
303         dbi_unregister_kprobe(&mr_kprobe, NULL);
304
305 unregister_unmap:
306         dbi_unregister_kprobe(&unmap_kprobe, NULL);
307
308         return ret;
309 }
310
311 void unregister_helper(void)
312 {
313         /* uninstall kretprobe with 'do_page_fault' */
314         dbi_unregister_kretprobe(&pf_kretprobe);
315
316         /* uninstall kretprobe with 'copy_process' */
317         dbi_unregister_kretprobe(&cp_kretprobe);
318
319         /* uninstall kprobe with 'mm_release' */
320         dbi_unregister_kprobe(&mr_kprobe, NULL);
321
322         /* uninstall kprobe with 'do_munmap' */
323         dbi_unregister_kprobe(&unmap_kprobe, NULL);
324 }
325
326 int init_helper(void)
327 {
328         unsigned long addr;
329         addr = swap_ksyms("do_page_fault");
330         if (addr == 0) {
331                 printk("Cannot find address for page fault function!\n");
332                 return -EINVAL;
333         }
334         pf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
335
336         addr = swap_ksyms("copy_process");
337         if (addr == 0) {
338                 printk("Cannot find address for copy_process function!\n");
339                 return -EINVAL;
340         }
341         cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
342
343         addr = swap_ksyms("mm_release");
344         if (addr == 0) {
345                 printk("Cannot find address for mm_release function!\n");
346                 return -EINVAL;
347         }
348         mr_kprobe.addr = (kprobe_opcode_t *)addr;
349
350         addr = swap_ksyms("do_munmap");
351         if (addr == 0) {
352                 printk("Cannot find address for do_munmap function!\n");
353                 return -EINVAL;
354         }
355         unmap_kprobe.addr = (kprobe_opcode_t *)addr;
356
357         return 0;
358 }
359
360 void uninit_helper(void)
361 {
362 }