[STYLE] Fix mr_pre_handler
[kernel/swap-modules.git] / us_manager / helper.c
1 /*
2  *  SWAP uprobe manager
3  *  modules/us_manager/helper.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Vyacheslav Cherkashin: SWAP us_manager implement
22  *
23  */
24
25
26 #include <kprobe/swap_kprobes.h>
27 #include <kprobe/swap_kprobes_deps.h>
28 #include <ksyms/ksyms.h>
29 #include <writer/kernel_operations.h>
30 #include "us_slot_manager.h"
31 #include "sspt/sspt.h"
32 #include "sspt/sspt_filter.h"
33 #include "helper.h"
34
35 struct task_struct;
36
37 struct task_struct *check_task(struct task_struct *task);
38
39 static atomic_t stop_flag = ATOMIC_INIT(0);
40
41
42 /*
43  ******************************************************************************
44  *                               do_page_fault()                              *
45  ******************************************************************************
46  */
47
48 struct pf_data {
49         unsigned long addr;
50
51 #if defined(CONFIG_ARM)
52         struct pt_regs *pf_regs;
53         unsigned long save_pc;
54 #endif /* CONFIG_ARM */
55 };
56
57 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
58 {
59         struct pf_data *data = (struct pf_data *)ri->data;
60
61 #if defined(CONFIG_ARM)
62         data->addr = swap_get_karg(regs, 0);
63         data->pf_regs = (struct pt_regs *)swap_get_karg(regs, 2);
64         data->save_pc = data->pf_regs->ARM_pc;
65 #elif defined(CONFIG_X86_32)
66         data->addr = read_cr2();
67 #else
68         #error "this architecture is not supported"
69 #endif /* CONFIG_arch */
70
71         if (data->addr) {
72                 struct sspt_proc * proc = sspt_proc_get_by_task(current);
73
74                 if (proc && (proc->r_state_addr == data->addr))
75                         /* skip ret_handler_pf() for current task */
76                         return 1;
77         }
78
79         return 0;
80 }
81
82 static unsigned long cb_pf(void *data)
83 {
84         unsigned long page_addr = *(unsigned long *)data;
85
86         call_page_fault(current, page_addr);
87
88         return 0;
89 }
90
91 /* Detects when IPs are really loaded into phy mem and installs probes. */
92 static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
93 {
94         struct task_struct *task = current;
95         struct pf_data *data = (struct pf_data *)ri->data;
96         unsigned long page_addr;
97         int ret;
98
99         if (is_kthread(task))
100                 return 0;
101
102 #if defined(CONFIG_ARM)
103         /* skip fixup page_fault */
104         if (data->save_pc != data->pf_regs->ARM_pc)
105                 return 0;
106 #endif /* CONFIG_ARM */
107
108         /* TODO: check return value */
109         page_addr = data->addr & PAGE_MASK;
110         ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_pf,
111                           &page_addr, sizeof(page_addr));
112
113         if (ret == 0)
114                 ri->ret_addr = (unsigned long *)get_jump_addr();
115
116         return 0;
117 }
118
119 static struct kretprobe mf_kretprobe = {
120         .entry_handler = entry_handler_pf,
121         .handler = ret_handler_pf,
122         .data_size = sizeof(struct pf_data)
123 };
124
125 static int register_mf(void)
126 {
127         int ret;
128
129         ret = swap_register_kretprobe(&mf_kretprobe);
130         if (ret)
131                 printk(KERN_INFO "swap_register_kretprobe(handle_mm_fault) ret=%d!\n",
132                        ret);
133
134         return ret;
135 }
136
137 static void unregister_mf(void)
138 {
139         swap_unregister_kretprobe(&mf_kretprobe);
140 }
141
142
143
144
145
146 #ifdef CONFIG_ARM
147 /*
148  ******************************************************************************
149  *                       workaround for already running                       *
150  ******************************************************************************
151  */
152 static unsigned long cb_check_and_install(void *data);
153
154 static int ctx_task_pre_handler(struct kprobe *p, struct pt_regs *regs)
155 {
156         struct sspt_proc *proc;
157         unsigned long page_addr;
158         struct task_struct *task = current;
159
160         if (is_kthread(task) || check_task_on_filters(task) == 0)
161                 return 0;
162
163         proc = sspt_proc_get_by_task(task);
164         if (proc && proc->first_install)
165                 return 0;
166
167         page_addr = 0;
168
169         return set_kjump_cb(regs, cb_check_and_install, NULL, 0);
170 }
171
172 static struct kprobe ctx_task_kprobe = {
173         .pre_handler = ctx_task_pre_handler,
174 };
175
176 static int register_ctx_task(void)
177 {
178         int ret = 0;
179
180         ret = swap_register_kprobe(&ctx_task_kprobe);
181         if (ret)
182                 printk(KERN_INFO "swap_register_kprobe(workaround) ret=%d!\n",
183                        ret);
184
185         return ret;
186 }
187
188 static void unregister_ctx_task(void)
189 {
190         swap_unregister_kprobe(&ctx_task_kprobe);
191 }
192 #endif /* CONFIG_ARM */
193
194
195
196
197
198 /*
199  ******************************************************************************
200  *                              copy_process()                                *
201  ******************************************************************************
202  */
203 static void func_uinst_creare(struct us_ip *ip, void *data)
204 {
205         struct hlist_head *head = (struct hlist_head *)data;
206         struct uprobe *up;
207
208         up = probe_info_get_uprobe(ip->info, ip);
209         if (up) {
210                 struct uinst_info *uinst;
211                 unsigned long vaddr = (unsigned long)up->kp.addr;
212
213                 uinst = uinst_info_create(vaddr, up->kp.opcode);
214                 if (uinst)
215                         hlist_add_head(&uinst->hlist, head);
216         }
217 }
218
219 static void disarm_for_task(struct task_struct *child, struct hlist_head *head)
220 {
221         struct uinst_info *uinst;
222         struct hlist_node *tmp;
223         DECLARE_NODE_PTR_FOR_HLIST(node);
224
225         swap_hlist_for_each_entry_safe(uinst, node, tmp, head, hlist) {
226                 uinst_info_disarm(uinst, child);
227                 hlist_del(&uinst->hlist);
228                 uinst_info_destroy(uinst);
229         }
230 }
231
232 struct clean_data {
233         struct task_struct *task;
234
235         struct hlist_head head;
236         struct hlist_head rhead;
237 };
238
239 static atomic_t rm_uprobes_child_cnt = ATOMIC_INIT(0);
240
241 static unsigned long cb_clean_child(void *data)
242 {
243         struct clean_data *cdata = (struct clean_data *)data;
244         struct task_struct *child = cdata->task;
245
246         /* disarm up for child */
247         disarm_for_task(child, &cdata->head);
248
249         /* disarm urp for child */
250         urinst_info_put_current_hlist(&cdata->rhead, child);
251
252         atomic_dec(&rm_uprobes_child_cnt);
253         return 0;
254 }
255
256 static void rm_uprobes_child(struct kretprobe_instance *ri,
257                              struct pt_regs *regs, struct task_struct *child)
258 {
259         struct sspt_proc *proc;
260         struct clean_data cdata = {
261                 .task = child,
262                 .head = HLIST_HEAD_INIT,
263                 .rhead = HLIST_HEAD_INIT
264         };
265
266         sspt_proc_write_lock();
267         proc = sspt_proc_get_by_task(current);
268         if (proc) {
269                 sspt_proc_on_each_ip(proc, func_uinst_creare, (void *)&cdata.head);
270                 urinst_info_get_current_hlist(&cdata.rhead, false);
271         }
272         sspt_proc_write_unlock();
273
274         if (proc) {
275                 int ret;
276
277                 /* set jumper */
278                 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
279                                   cb_clean_child, &cdata, sizeof(cdata));
280                 if (ret == 0) {
281                         atomic_inc(&rm_uprobes_child_cnt);
282                         ri->ret_addr = (unsigned long *)get_jump_addr();
283                 }
284         }
285 }
286
287
288 static atomic_t pre_handler_cp_cnt = ATOMIC_INIT(0);
289
290 static unsigned long cp_cb(void *data)
291 {
292         if (atomic_read(&stop_flag))
293                 call_mm_release(current);
294
295         atomic_dec(&pre_handler_cp_cnt);
296         return 0;
297 }
298
299 static int pre_handler_cp(struct kprobe *p, struct pt_regs *regs)
300 {
301         int ret = 0;
302
303         if (is_kthread(current))
304                 goto out;
305
306         if (!atomic_read(&stop_flag))
307                 goto out;
308
309         ret = set_kjump_cb(regs, cp_cb, NULL, 0);
310         if (ret < 0) {
311                 pr_err("set_kjump_cp, ret=%d\n", ret);
312                 ret = 0;
313         } else {
314                 atomic_inc(&pre_handler_cp_cnt);
315         }
316 out:
317         return ret;
318 }
319
320
321 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
322
323 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
324 {
325         atomic_inc(&copy_process_cnt);
326
327         return 0;
328 }
329
330 /* Delete uprobs in children at fork */
331 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
332 {
333         struct task_struct *task =
334                 (struct task_struct *)regs_return_value(regs);
335
336         if (!task || IS_ERR(task))
337                 goto out;
338
339         if (task->mm != current->mm) {  /* check flags CLONE_VM */
340                 rm_uprobes_child(ri, regs, task);
341         }
342 out:
343         atomic_dec(&copy_process_cnt);
344
345         return 0;
346 }
347
348 static struct kretprobe cp_kretprobe = {
349         .entry_handler = entry_handler_cp,
350         .handler = ret_handler_cp,
351 };
352
353 static struct kprobe cp_kprobe = {
354         .pre_handler = pre_handler_cp
355 };
356
357 static int register_cp(void)
358 {
359         int ret;
360
361
362         ret = swap_register_kprobe(&cp_kprobe);
363         if (ret)
364                 pr_err("swap_register_kprobe(copy_process) ret=%d!\n", ret);
365
366         ret = swap_register_kretprobe(&cp_kretprobe);
367         if (ret) {
368                 pr_err("swap_register_kretprobe(copy_process) ret=%d!\n", ret);
369                 swap_unregister_kprobe(&cp_kprobe);
370         }
371
372         return ret;
373 }
374
375 static void unregister_cp(void)
376 {
377         swap_unregister_kretprobe_top(&cp_kretprobe, 0);
378         do {
379                 synchronize_sched();
380         } while (atomic_read(&copy_process_cnt));
381         swap_unregister_kretprobe_bottom(&cp_kretprobe);
382         swap_unregister_kprobe(&cp_kprobe);
383
384         do {
385                 synchronize_sched();
386         } while (atomic_read(&rm_uprobes_child_cnt)
387               || atomic_read(&pre_handler_cp_cnt));
388 }
389
390
391
392
393
394 /*
395  ******************************************************************************
396  *                                mm_release()                                *
397  ******************************************************************************
398  */
399
400 static atomic_t mm_release_cnt = ATOMIC_INIT(0);
401
402 static unsigned long mr_cb(void *data)
403 {
404         struct task_struct *task = *(struct task_struct **)data;
405         struct mm_struct *mm = task->mm;
406
407         if (mm == NULL) {
408                 pr_err("mm is NULL\n");
409                 return 0;
410         }
411
412         /* TODO: this lock for synchronizing to disarm urp */
413         down_write(&mm->mmap_sem);
414         if (task->tgid != task->pid) {
415                 struct sspt_proc *proc;
416                 struct hlist_head head = HLIST_HEAD_INIT;
417
418                 if (task != current) {
419                         pr_err("call mm_release in isn't current context\n");
420                         return 0;
421                 }
422
423                 /* if the thread is killed we need to discard pending
424                  * uretprobe instances which have not triggered yet */
425                 sspt_proc_write_lock();
426                 proc = sspt_proc_get_by_task(task);
427                 if (proc) {
428                         urinst_info_get_current_hlist(&head, true);
429                 }
430                 sspt_proc_write_unlock();
431
432                 if (proc) {
433                         /* disarm urp for task */
434                         urinst_info_put_current_hlist(&head, task);
435                 }
436         } else {
437                 call_mm_release(task);
438         }
439         up_write(&mm->mmap_sem);
440
441         atomic_dec(&mm_release_cnt);
442
443         return 0;
444 }
445
446 /* Detects when target process removes IPs. */
447 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
448 {
449         int ret = 0;
450         struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
451
452         if (is_kthread(task))
453                 goto out;
454
455         ret = set_kjump_cb(regs, mr_cb, (void *)&task, sizeof(task));
456         if (ret < 0) {
457                 printk("##### ERROR: mr_pre_handler, ret=%d\n", ret);
458         } else {
459                 atomic_inc(&mm_release_cnt);
460         }
461
462 out:
463         return 0;
464 }
465
466 static struct kprobe mr_kprobe = {
467         .pre_handler = mr_pre_handler
468 };
469
470 static int register_mr(void)
471 {
472         int ret;
473
474         ret = swap_register_kprobe(&mr_kprobe);
475         if (ret)
476                 printk(KERN_INFO
477                        "swap_register_kprobe(mm_release) ret=%d!\n", ret);
478
479         return ret;
480 }
481
482 static void unregister_mr(void)
483 {
484         swap_unregister_kprobe(&mr_kprobe);
485         do {
486                 synchronize_sched();
487         } while (atomic_read(&mm_release_cnt));
488 }
489
490
491
492
493
494 /*
495  ******************************************************************************
496  *                                 do_munmap()                                *
497  ******************************************************************************
498  */
499 struct unmap_data {
500         unsigned long start;
501         size_t len;
502 };
503
504 static atomic_t unmap_cnt = ATOMIC_INIT(0);
505
506 struct msg_unmap_data {
507         unsigned long start;
508         unsigned long end;
509 };
510
511 static void msg_unmap(struct sspt_filter *f, void *data)
512 {
513         if (f->pfg_is_inst) {
514                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
515
516                 if (cb && cb->msg_unmap) {
517                         struct msg_unmap_data *msg_data;
518
519                         msg_data = (struct msg_unmap_data *)data;
520                         cb->msg_unmap(msg_data->start, msg_data->end);
521                 }
522         }
523 }
524
525 static void __remove_unmap_probes(struct sspt_proc *proc,
526                                   struct unmap_data *umd)
527 {
528         struct task_struct *task = proc->task;
529         unsigned long start = umd->start;
530         size_t len = PAGE_ALIGN(umd->len);
531         LIST_HEAD(head);
532
533         if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
534                 struct sspt_file *file, *n;
535                 unsigned long end = start + len;
536                 struct msg_unmap_data msg_data = {
537                         .start = start,
538                         .end = end
539                 };
540
541                 list_for_each_entry_safe(file, n, &head, list) {
542                         if (file->vm_start >= end)
543                                 continue;
544
545                         if (file->vm_start >= start)
546                                 sspt_file_uninstall(file, task, US_UNINSTALL);
547                         /* TODO: else: uninstall pages: * start..file->vm_end */
548                 }
549
550                 sspt_proc_insert_files(proc, &head);
551
552                 sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data);
553         }
554 }
555
556 static void remove_unmap_probes(struct task_struct *task,
557                                 struct unmap_data *umd)
558 {
559         struct sspt_proc *proc;
560
561         sspt_proc_write_lock();
562
563         proc = sspt_proc_get_by_task(task);
564         if (proc)
565                 __remove_unmap_probes(proc, umd);
566
567         sspt_proc_write_unlock();
568 }
569
570 static int entry_handler_unmap(struct kretprobe_instance *ri,
571                                struct pt_regs *regs)
572 {
573         struct unmap_data *data = (struct unmap_data *)ri->data;
574         struct task_struct *task = current->group_leader;
575
576         atomic_inc(&unmap_cnt);
577
578         data->start = swap_get_karg(regs, 1);
579         data->len = (size_t)swap_get_karg(regs, 2);
580
581         if (!is_kthread(task) && atomic_read(&stop_flag))
582                 remove_unmap_probes(task, data);
583
584         return 0;
585 }
586
587 static int ret_handler_unmap(struct kretprobe_instance *ri,
588                              struct pt_regs *regs)
589 {
590         struct task_struct *task;
591
592         task = current->group_leader;
593         if (is_kthread(task) || regs_return_value(regs))
594                 goto out;
595
596         remove_unmap_probes(task, (struct unmap_data *)ri->data);
597
598 out:
599         atomic_dec(&unmap_cnt);
600
601         return 0;
602 }
603
604 static struct kretprobe unmap_kretprobe = {
605         .entry_handler = entry_handler_unmap,
606         .handler = ret_handler_unmap,
607         .data_size = sizeof(struct unmap_data)
608 };
609
610 static int register_unmap(void)
611 {
612         int ret;
613
614         ret = swap_register_kretprobe(&unmap_kretprobe);
615         if (ret)
616                 printk(KERN_INFO "swap_register_kprobe(do_munmap) ret=%d!\n",
617                        ret);
618
619         return ret;
620 }
621
622 static void unregister_unmap(void)
623 {
624         swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
625         do {
626                 synchronize_sched();
627         } while (atomic_read(&unmap_cnt));
628         swap_unregister_kretprobe_bottom(&unmap_kretprobe);
629 }
630
631
632
633
634
635 /*
636  ******************************************************************************
637  *                               do_mmap_pgoff()                              *
638  ******************************************************************************
639  */
640 static void msg_map(struct sspt_filter *f, void *data)
641 {
642         if (f->pfg_is_inst) {
643                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
644
645                 if (cb && cb->msg_map)
646                         cb->msg_map((struct vm_area_struct *)data);
647         }
648 }
649
650 static int ret_handler_mmap(struct kretprobe_instance *ri,
651                             struct pt_regs *regs)
652 {
653         struct sspt_proc *proc;
654         struct task_struct *task;
655         unsigned long start_addr;
656         struct vm_area_struct *vma;
657
658         task = current->group_leader;
659         if (is_kthread(task))
660                 return 0;
661
662         start_addr = regs_return_value(regs);
663         if (IS_ERR_VALUE(start_addr))
664                 return 0;
665
666         proc = sspt_proc_get_by_task(task);
667         if (proc == NULL)
668                 return 0;
669
670         vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
671         if (vma && check_vma(vma))
672                 sspt_proc_on_each_filter(proc, msg_map, (void *)vma);
673
674         return 0;
675 }
676
677 static struct kretprobe mmap_kretprobe = {
678         .handler = ret_handler_mmap
679 };
680
681 static int register_mmap(void)
682 {
683         int ret;
684
685         ret = swap_register_kretprobe(&mmap_kretprobe);
686         if (ret)
687                 printk(KERN_INFO "swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n",
688                        ret);
689
690         return ret;
691 }
692
693 static void unregister_mmap(void)
694 {
695         swap_unregister_kretprobe(&mmap_kretprobe);
696 }
697
698
699
700
701
702 /*
703  ******************************************************************************
704  *                               set_task_comm()                              *
705  ******************************************************************************
706  */
707 struct comm_data {
708         struct task_struct *task;
709 };
710
711 static unsigned long cb_check_and_install(void *data)
712 {
713         check_task_and_install(current);
714
715         return 0;
716 }
717
718 static int entry_handler_comm(struct kretprobe_instance *ri,
719                               struct pt_regs *regs)
720 {
721         struct comm_data *data = (struct comm_data *)ri->data;
722
723         data->task = (struct task_struct *)swap_get_karg(regs, 0);
724
725         return 0;
726 }
727
728 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
729 {
730         struct task_struct *task;
731         int ret;
732
733         if (is_kthread(current))
734                 return 0;
735
736         task = ((struct comm_data *)ri->data)->task;
737         if (task != current)
738                 return 0;
739
740         ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
741                           cb_check_and_install, NULL, 0);
742         if (ret == 0)
743                 ri->ret_addr = (unsigned long *)get_jump_addr();
744
745         return 0;
746 }
747
748 static struct kretprobe comm_kretprobe = {
749         .entry_handler = entry_handler_comm,
750         .handler = ret_handler_comm,
751         .data_size = sizeof(struct comm_data)
752 };
753
754 static int register_comm(void)
755 {
756         int ret;
757
758         ret = swap_register_kretprobe(&comm_kretprobe);
759         if (ret)
760                 printk(KERN_INFO "swap_register_kretprobe(set_task_comm) ret=%d!\n",
761                        ret);
762
763         return ret;
764 }
765
766 static void unregister_comm(void)
767 {
768         swap_unregister_kretprobe(&comm_kretprobe);
769 }
770
771
772
773
774
775 /**
776  * @brief Registration of helper
777  *
778  * @return Error code
779  */
780 int register_helper(void)
781 {
782         int ret = 0;
783
784         atomic_set(&stop_flag, 0);
785
786         /*
787          * install probe on 'set_task_comm' to detect when field comm struct
788          * task_struct changes
789          */
790         ret = register_comm();
791         if (ret)
792                 return ret;
793
794         /* install probe on 'do_munmap' to detect when for remove US probes */
795         ret = register_unmap();
796         if (ret)
797                 goto unreg_comm;
798
799         /* install probe on 'mm_release' to detect when for remove US probes */
800         ret = register_mr();
801         if (ret)
802                 goto unreg_unmap;
803
804         /* install probe on 'copy_process' to disarm children process */
805         ret = register_cp();
806         if (ret)
807                 goto unreg_mr;
808
809         /* install probe on 'do_mmap_pgoff' to detect when mapping file */
810         ret = register_mmap();
811         if (ret)
812                 goto unreg_cp;
813
814         /*
815          * install probe on 'handle_mm_fault' to detect when US pages will be
816          * loaded
817          */
818         ret = register_mf();
819         if (ret)
820                 goto unreg_mmap;
821
822 #ifdef CONFIG_ARM
823         /* install probe to detect already running process */
824         ret = register_ctx_task();
825         if (ret)
826                 goto unreg_mf;
827 #endif /* CONFIG_ARM */
828
829         return ret;
830
831 #ifdef CONFIG_ARM
832 unreg_mf:
833         unregister_mf();
834 #endif /* CONFIG_ARM */
835
836 unreg_mmap:
837         unregister_mmap();
838
839 unreg_cp:
840         unregister_cp();
841
842 unreg_mr:
843         unregister_mr();
844
845 unreg_unmap:
846         unregister_unmap();
847
848 unreg_comm:
849         unregister_comm();
850
851         return ret;
852 }
853
854 /**
855  * @brief Unegistration of helper bottom
856  *
857  * @return Void
858  */
859 void unregister_helper_top(void)
860 {
861 #ifdef CONFIG_ARM
862         unregister_ctx_task();
863 #endif /* CONFIG_ARM */
864         unregister_mf();
865         atomic_set(&stop_flag, 1);
866 }
867
868 /**
869  * @brief Unegistration of helper top
870  *
871  * @return Void
872  */
873 void unregister_helper_bottom(void)
874 {
875         unregister_mmap();
876         unregister_cp();
877         unregister_mr();
878         unregister_unmap();
879         unregister_comm();
880 }
881
882 /**
883  * @brief Initialization of helper
884  *
885  * @return Error code
886  */
887 int once_helper(void)
888 {
889         const char *sym;
890
891         sym = "do_page_fault";
892         mf_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
893         if (mf_kretprobe.kp.addr == NULL)
894                 goto not_found;
895
896         sym = "copy_process";
897         cp_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms_substr(sym);
898         if (cp_kretprobe.kp.addr == NULL)
899                 goto not_found;
900         cp_kprobe.addr = cp_kretprobe.kp.addr;
901
902         sym = "mm_release";
903         mr_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
904         if (mr_kprobe.addr == NULL)
905                 goto not_found;
906
907         sym = "do_munmap";
908         unmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
909         if (unmap_kretprobe.kp.addr == NULL)
910                 goto not_found;
911
912         sym = "do_mmap_pgoff";
913         mmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
914         if (mmap_kretprobe.kp.addr == NULL)
915                 goto not_found;
916
917         sym = "set_task_comm";
918         comm_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
919         if (comm_kretprobe.kp.addr == NULL)
920                 goto not_found;
921
922 #ifdef CONFIG_ARM
923         sym = "ret_to_user";
924         ctx_task_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
925         if (ctx_task_kprobe.addr == NULL)
926                 goto not_found;
927 #endif /* CONFIG_ARM */
928
929         return 0;
930
931 not_found:
932         printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
933         return -ESRCH;
934 }