[FEATURE] add instrumentation US for x86
[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         task = (struct task_struct *)regs->EREG(ax);
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         mm = (struct mm_struct *)regs->EREG(ax);
237         start = regs->EREG(dx);
238         len = (size_t)regs->EREG(cx);
239 #elif defined(CONFIG_ARM)
240         mm = (struct mm_struct *)regs->ARM_r0;
241         start = regs->ARM_r1;
242         len = (size_t)regs->ARM_r2;
243 #else
244 #error this architecture is not supported
245 #endif
246
247         struct sspt_proc *proc = NULL;
248         struct task_struct *task = current;
249
250         //if user-space instrumentation is not set
251         if (!is_us_instrumentation()) {
252                 goto out;
253         }
254
255         proc = sspt_proc_get_by_task(task);
256         if (proc) {
257                 if (remove_unmap_probes(task, proc, start, len)) {
258                         printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
259                 }
260         }
261
262 out:
263         return 0;
264 }
265
266 static struct kprobe unmap_kprobe = {
267         .pre_handler = unmap_pre_handler
268 };
269
270
271
272 int register_helper(void)
273 {
274         int ret = 0;
275
276         /* install kprobe on 'do_munmap' to detect when for remove user space probes */
277         ret = dbi_register_kprobe(&unmap_kprobe);
278         if (ret) {
279                 printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
280                 return ret;
281         }
282
283         /* install kprobe on 'mm_release' to detect when for remove user space probes */
284         ret = dbi_register_kprobe(&mr_kprobe);
285         if (ret != 0) {
286                 printk("dbi_register_kprobe(mm_release) result=%d!\n", ret);
287                 goto unregister_unmap;
288         }
289
290
291         /* install kretprobe on 'copy_process' */
292         ret = dbi_register_kretprobe(&cp_kretprobe);
293         if (ret) {
294                 printk("dbi_register_kretprobe(copy_process) result=%d!\n", ret);
295                 goto unregister_mr;
296         }
297
298         /* install kretprobe on 'do_page_fault' to detect when they will be loaded */
299         ret = dbi_register_kretprobe(&pf_kretprobe);
300         if (ret) {
301                 printk("dbi_register_kretprobe(do_page_fault) result=%d!\n", ret);
302                 goto unregister_cp;
303         }
304
305         return ret;
306
307 unregister_cp:
308         dbi_unregister_kretprobe(&cp_kretprobe);
309
310 unregister_mr:
311         dbi_unregister_kprobe(&mr_kprobe, NULL);
312
313 unregister_unmap:
314         dbi_unregister_kprobe(&unmap_kprobe, NULL);
315
316         return ret;
317 }
318
319 void unregister_helper(void)
320 {
321         /* uninstall kretprobe with 'do_page_fault' */
322         dbi_unregister_kretprobe(&pf_kretprobe);
323
324         /* uninstall kretprobe with 'copy_process' */
325         dbi_unregister_kretprobe(&cp_kretprobe);
326
327         /* uninstall kprobe with 'mm_release' */
328         dbi_unregister_kprobe(&mr_kprobe, NULL);
329
330         /* uninstall kprobe with 'do_munmap' */
331         dbi_unregister_kprobe(&unmap_kprobe, NULL);
332 }
333
334 int init_helper(void)
335 {
336         unsigned long addr;
337         addr = swap_ksyms("do_page_fault");
338         if (addr == 0) {
339                 printk("Cannot find address for page fault function!\n");
340                 return -EINVAL;
341         }
342         pf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
343
344         addr = swap_ksyms("copy_process");
345         if (addr == 0) {
346                 printk("Cannot find address for copy_process function!\n");
347                 return -EINVAL;
348         }
349         cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
350
351         addr = swap_ksyms("mm_release");
352         if (addr == 0) {
353                 printk("Cannot find address for mm_release function!\n");
354                 return -EINVAL;
355         }
356         mr_kprobe.addr = (kprobe_opcode_t *)addr;
357
358         addr = swap_ksyms("do_munmap");
359         if (addr == 0) {
360                 printk("Cannot find address for do_munmap function!\n");
361                 return -EINVAL;
362         }
363         unmap_kprobe.addr = (kprobe_opcode_t *)addr;
364
365         return 0;
366 }
367
368 void uninit_helper(void)
369 {
370 }