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