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