7c78a8547f72f6b4b59e20f34c8dd2928b795dbe
[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 #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         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;
143
144 #if defined(CONFIG_X86)
145         return 0;
146 #elif defined(CONFIG_ARM)
147         task = (struct task_struct *)regs->ARM_r0;
148 #else
149 #error this architecture is not supported
150 #endif
151
152         if (!is_us_instrumentation() || task->tgid != task->pid) {
153                 goto out;
154         }
155
156         proc = sspt_proc_get_by_task(task);
157         if (proc) {
158                 int ret = sspt_proc_uninstall(proc, task, US_UNREGS_PROBE);
159                 if (ret != 0) {
160                         printk("failed to uninstall IPs (%d)!\n", ret);
161                 }
162
163                 dbi_unregister_all_uprobes(task);
164         }
165
166 out:
167         return 0;
168 }
169
170 static struct kprobe mr_kprobe = {
171         .pre_handler = mr_pre_handler
172 };
173
174
175
176 /*
177  ******************************************************************************
178  *                                 do_munmap()                                *
179  ******************************************************************************
180  */
181
182 static int remove_unmap_probes(struct task_struct *task, struct sspt_proc *proc, unsigned long start, size_t len)
183 {
184         struct mm_struct *mm = task->mm;
185         struct vm_area_struct *vma;
186
187         if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
188                 return -EINVAL;
189         }
190
191         if ((len = PAGE_ALIGN(len)) == 0) {
192                 return -EINVAL;
193         }
194
195         vma = find_vma(mm, start);
196         if (vma && check_vma(vma)) {
197                 struct sspt_file *file;
198                 unsigned long end = start + len;
199                 struct dentry *dentry = vma->vm_file->f_dentry;
200
201                 file = sspt_proc_find_file(proc, dentry);
202                 if (file) {
203                         if (vma->vm_start == start || vma->vm_end == end) {
204                                 sspt_file_uninstall(file, task, US_UNREGS_PROBE);
205                                 file->loaded = 0;
206                         } else {
207                                 unsigned long page_addr;
208                                 struct sspt_page *page;
209
210                                 for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
211                                         page = sspt_find_page_mapped(file, page_addr);
212                                         if (page) {
213                                                 sspt_unregister_page(page, US_UNREGS_PROBE, task);
214                                         }
215                                 }
216
217                                 if (sspt_file_check_install_pages(file)) {
218                                         file->loaded = 0;
219                                 }
220                         }
221                 }
222         }
223
224         return 0;
225 }
226
227 /* Detects when target removes IPs. */
228 static int unmap_pre_handler(struct kprobe *p, struct pt_regs *regs)
229 {
230         /* for ARM */
231         struct mm_struct *mm;
232         unsigned long start;
233         size_t len;
234
235 #if defined(CONFIG_X86)
236         return 0;
237 #elif defined(CONFIG_ARM)
238         mm = (struct mm_struct *)regs->ARM_r0;
239         start = regs->ARM_r1;
240         len = (size_t)regs->ARM_r2;
241 #else
242 #error this architecture is not supported
243 #endif
244
245         struct sspt_proc *proc = NULL;
246         struct task_struct *task = current;
247
248         //if user-space instrumentation is not set
249         if (!is_us_instrumentation()) {
250                 goto out;
251         }
252
253         proc = sspt_proc_get_by_task(task);
254         if (proc) {
255                 if (remove_unmap_probes(task, proc, start, len)) {
256                         printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
257                 }
258         }
259
260 out:
261         return 0;
262 }
263
264 static struct kprobe unmap_kprobe = {
265         .pre_handler = unmap_pre_handler
266 };
267
268
269
270 int register_helper(void)
271 {
272         int ret = 0;
273
274         /* install kprobe on 'do_munmap' to detect when for remove user space probes */
275         ret = dbi_register_kprobe(&unmap_kprobe);
276         if (ret) {
277                 printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
278                 return ret;
279         }
280
281         /* install kprobe on 'mm_release' to detect when for remove user space probes */
282         ret = dbi_register_kprobe(&mr_kprobe);
283         if (ret != 0) {
284                 printk("dbi_register_kprobe(mm_release) result=%d!\n", ret);
285                 goto unregister_unmap;
286         }
287
288
289         /* install kretprobe on 'copy_process' */
290         ret = dbi_register_kretprobe(&cp_kretprobe);
291         if (ret) {
292                 printk("dbi_register_kretprobe(copy_process) result=%d!\n", ret);
293                 goto unregister_mr;
294         }
295
296         /* install kretprobe on 'do_page_fault' to detect when they will be loaded */
297         ret = dbi_register_kretprobe(&pf_kretprobe);
298         if (ret) {
299                 printk("dbi_register_kretprobe(do_page_fault) result=%d!\n", ret);
300                 goto unregister_cp;
301         }
302
303         return ret;
304
305 unregister_cp:
306         dbi_unregister_kretprobe(&cp_kretprobe);
307
308 unregister_mr:
309         dbi_unregister_kprobe(&mr_kprobe, NULL);
310
311 unregister_unmap:
312         dbi_unregister_kprobe(&unmap_kprobe, NULL);
313
314         return ret;
315 }
316
317 void unregister_helper(void)
318 {
319         /* uninstall kretprobe with 'do_page_fault' */
320         dbi_unregister_kretprobe(&pf_kretprobe);
321
322         /* uninstall kretprobe with 'copy_process' */
323         dbi_unregister_kretprobe(&cp_kretprobe);
324
325         /* uninstall kprobe with 'mm_release' */
326         dbi_unregister_kprobe(&mr_kprobe, NULL);
327
328         /* uninstall kprobe with 'do_munmap' */
329         dbi_unregister_kprobe(&unmap_kprobe, NULL);
330 }
331
332 int init_helper(void)
333 {
334         unsigned long addr;
335         addr = swap_ksyms("do_page_fault");
336         if (addr == 0) {
337                 printk("Cannot find address for page fault function!\n");
338                 return -EINVAL;
339         }
340         pf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
341
342         addr = swap_ksyms("copy_process");
343         if (addr == 0) {
344                 printk("Cannot find address for copy_process function!\n");
345                 return -EINVAL;
346         }
347         cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
348
349         addr = swap_ksyms("mm_release");
350         if (addr == 0) {
351                 printk("Cannot find address for mm_release function!\n");
352                 return -EINVAL;
353         }
354         mr_kprobe.addr = (kprobe_opcode_t *)addr;
355
356         addr = swap_ksyms("do_munmap");
357         if (addr == 0) {
358                 printk("Cannot find address for do_munmap function!\n");
359                 return -EINVAL;
360         }
361         unmap_kprobe.addr = (kprobe_opcode_t *)addr;
362
363         return 0;
364 }
365
366 void uninit_helper(void)
367 {
368 }