tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / 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         int ret;
157         struct sspt_proc *proc;
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         ret = set_kjump_cb(regs, cb_check_and_install, NULL, 0);
168         if (ret < 0)
169                 pr_err("ctx_task_pre_handler: ret=%d\n", ret);
170
171         return 0;
172 }
173
174 static struct kprobe ctx_task_kprobe = {
175         .pre_handler = ctx_task_pre_handler,
176 };
177
178 static int register_ctx_task(void)
179 {
180         int ret = 0;
181
182         ret = swap_register_kprobe(&ctx_task_kprobe);
183         if (ret)
184                 printk(KERN_INFO "swap_register_kprobe(workaround) ret=%d!\n",
185                        ret);
186
187         return ret;
188 }
189
190 static void unregister_ctx_task(void)
191 {
192         swap_unregister_kprobe(&ctx_task_kprobe);
193 }
194 #endif /* CONFIG_ARM */
195
196
197
198
199
200 /*
201  ******************************************************************************
202  *                              copy_process()                                *
203  ******************************************************************************
204  */
205 static void func_uinst_creare(struct us_ip *ip, void *data)
206 {
207         struct hlist_head *head = (struct hlist_head *)data;
208         struct uprobe *up;
209
210         up = probe_info_get_uprobe(ip->info, ip);
211         if (up) {
212                 struct uinst_info *uinst;
213                 unsigned long vaddr = (unsigned long)up->kp.addr;
214
215                 uinst = uinst_info_create(vaddr, up->kp.opcode);
216                 if (uinst)
217                         hlist_add_head(&uinst->hlist, head);
218         }
219 }
220
221 static void disarm_for_task(struct task_struct *child, struct hlist_head *head)
222 {
223         struct uinst_info *uinst;
224         struct hlist_node *tmp;
225         DECLARE_NODE_PTR_FOR_HLIST(node);
226
227         swap_hlist_for_each_entry_safe(uinst, node, tmp, head, hlist) {
228                 uinst_info_disarm(uinst, child);
229                 hlist_del(&uinst->hlist);
230                 uinst_info_destroy(uinst);
231         }
232 }
233
234 struct clean_data {
235         struct task_struct *task;
236
237         struct hlist_head head;
238         struct hlist_head rhead;
239 };
240
241 static atomic_t rm_uprobes_child_cnt = ATOMIC_INIT(0);
242
243 static unsigned long cb_clean_child(void *data)
244 {
245         struct clean_data *cdata = (struct clean_data *)data;
246         struct task_struct *child = cdata->task;
247
248         /* disarm up for child */
249         disarm_for_task(child, &cdata->head);
250
251         /* disarm urp for child */
252         urinst_info_put_current_hlist(&cdata->rhead, child);
253
254         atomic_dec(&rm_uprobes_child_cnt);
255         return 0;
256 }
257
258 static void rm_uprobes_child(struct kretprobe_instance *ri,
259                              struct pt_regs *regs, struct task_struct *child)
260 {
261         struct sspt_proc *proc;
262         struct clean_data cdata = {
263                 .task = child,
264                 .head = HLIST_HEAD_INIT,
265                 .rhead = HLIST_HEAD_INIT
266         };
267
268         sspt_proc_write_lock();
269         proc = sspt_proc_get_by_task_no_lock(current);
270         if (proc) {
271                 sspt_proc_on_each_ip(proc, func_uinst_creare, (void *)&cdata.head);
272                 urinst_info_get_current_hlist(&cdata.rhead, false);
273         }
274         sspt_proc_write_unlock();
275
276         if (proc) {
277                 int ret;
278
279                 /* set jumper */
280                 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
281                                   cb_clean_child, &cdata, sizeof(cdata));
282                 if (ret == 0) {
283                         atomic_inc(&rm_uprobes_child_cnt);
284                         ri->ret_addr = (unsigned long *)get_jump_addr();
285                 }
286         }
287 }
288
289
290 static atomic_t pre_handler_cp_cnt = ATOMIC_INIT(0);
291
292 static unsigned long cp_cb(void *data)
293 {
294         if (atomic_read(&stop_flag))
295                 call_mm_release(current);
296
297         atomic_dec(&pre_handler_cp_cnt);
298         return 0;
299 }
300
301 static int pre_handler_cp(struct kprobe *p, struct pt_regs *regs)
302 {
303         int ret = 0;
304
305         if (is_kthread(current))
306                 goto out;
307
308         if (!atomic_read(&stop_flag))
309                 goto out;
310
311         ret = set_kjump_cb(regs, cp_cb, NULL, 0);
312         if (ret < 0) {
313                 pr_err("set_kjump_cp, ret=%d\n", ret);
314                 ret = 0;
315         } else {
316                 atomic_inc(&pre_handler_cp_cnt);
317         }
318 out:
319         return ret;
320 }
321
322
323 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
324
325 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
326 {
327         atomic_inc(&copy_process_cnt);
328
329         return 0;
330 }
331
332 /* Delete uprobs in children at fork */
333 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
334 {
335         struct task_struct *task =
336                 (struct task_struct *)regs_return_value(regs);
337
338         if (!task || IS_ERR(task))
339                 goto out;
340
341         if (task->mm != current->mm) {  /* check flags CLONE_VM */
342                 rm_uprobes_child(ri, regs, task);
343         }
344 out:
345         atomic_dec(&copy_process_cnt);
346
347         return 0;
348 }
349
350 static struct kretprobe cp_kretprobe = {
351         .entry_handler = entry_handler_cp,
352         .handler = ret_handler_cp,
353 };
354
355 static struct kprobe cp_kprobe = {
356         .pre_handler = pre_handler_cp
357 };
358
359 static int register_cp(void)
360 {
361         int ret;
362
363
364         ret = swap_register_kprobe(&cp_kprobe);
365         if (ret)
366                 pr_err("swap_register_kprobe(copy_process) ret=%d!\n", ret);
367
368         ret = swap_register_kretprobe(&cp_kretprobe);
369         if (ret) {
370                 pr_err("swap_register_kretprobe(copy_process) ret=%d!\n", ret);
371                 swap_unregister_kprobe(&cp_kprobe);
372         }
373
374         return ret;
375 }
376
377 static void unregister_cp(void)
378 {
379         swap_unregister_kretprobe_top(&cp_kretprobe, 0);
380         do {
381                 synchronize_sched();
382         } while (atomic_read(&copy_process_cnt));
383         swap_unregister_kretprobe_bottom(&cp_kretprobe);
384         swap_unregister_kprobe(&cp_kprobe);
385
386         do {
387                 synchronize_sched();
388         } while (atomic_read(&rm_uprobes_child_cnt)
389               || atomic_read(&pre_handler_cp_cnt));
390 }
391
392
393
394
395
396 /*
397  ******************************************************************************
398  *                                mm_release()                                *
399  ******************************************************************************
400  */
401
402 static atomic_t mm_release_cnt = ATOMIC_INIT(0);
403
404 static unsigned long mr_cb(void *data)
405 {
406         struct task_struct *task = *(struct task_struct **)data;
407         struct mm_struct *mm = task->mm;
408
409         if (mm == NULL) {
410                 pr_err("mm is NULL\n");
411                 return 0;
412         }
413
414         /* TODO: this lock for synchronizing to disarm urp */
415         down_write(&mm->mmap_sem);
416         if (task->tgid != task->pid) {
417                 struct sspt_proc *proc;
418                 struct hlist_head head = HLIST_HEAD_INIT;
419
420                 if (task != current) {
421                         pr_err("call mm_release in isn't current context\n");
422                         return 0;
423                 }
424
425                 /* if the thread is killed we need to discard pending
426                  * uretprobe instances which have not triggered yet */
427                 sspt_proc_write_lock();
428                 proc = sspt_proc_get_by_task_no_lock(task);
429                 if (proc) {
430                         urinst_info_get_current_hlist(&head, true);
431                 }
432                 sspt_proc_write_unlock();
433
434                 if (proc) {
435                         /* disarm urp for task */
436                         urinst_info_put_current_hlist(&head, task);
437                 }
438         } else {
439                 call_mm_release(task);
440         }
441         up_write(&mm->mmap_sem);
442
443         atomic_dec(&mm_release_cnt);
444
445         return 0;
446 }
447
448 /* Detects when target process removes IPs. */
449 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
450 {
451         int ret = 0;
452         struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
453
454         if (is_kthread(task))
455                 goto out;
456
457         ret = set_kjump_cb(regs, mr_cb, (void *)&task, sizeof(task));
458         if (ret < 0) {
459                 printk("##### ERROR: mr_pre_handler, ret=%d\n", ret);
460         } else {
461                 atomic_inc(&mm_release_cnt);
462         }
463
464 out:
465         return 0;
466 }
467
468 static struct kprobe mr_kprobe = {
469         .pre_handler = mr_pre_handler
470 };
471
472 static int register_mr(void)
473 {
474         int ret;
475
476         ret = swap_register_kprobe(&mr_kprobe);
477         if (ret)
478                 printk(KERN_INFO
479                        "swap_register_kprobe(mm_release) ret=%d!\n", ret);
480
481         return ret;
482 }
483
484 static void unregister_mr(void)
485 {
486         swap_unregister_kprobe(&mr_kprobe);
487         do {
488                 synchronize_sched();
489         } while (atomic_read(&mm_release_cnt));
490 }
491
492
493
494
495
496 /*
497  ******************************************************************************
498  *                                 do_munmap()                                *
499  ******************************************************************************
500  */
501 struct unmap_data {
502         unsigned long start;
503         size_t len;
504 };
505
506 static atomic_t unmap_cnt = ATOMIC_INIT(0);
507
508 struct msg_unmap_data {
509         unsigned long start;
510         unsigned long end;
511 };
512
513 static void msg_unmap(struct sspt_filter *f, void *data)
514 {
515         if (f->pfg_is_inst) {
516                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
517
518                 if (cb && cb->msg_unmap) {
519                         struct msg_unmap_data *msg_data;
520
521                         msg_data = (struct msg_unmap_data *)data;
522                         cb->msg_unmap(msg_data->start, msg_data->end);
523                 }
524         }
525 }
526
527 static void __remove_unmap_probes(struct sspt_proc *proc,
528                                   struct unmap_data *umd)
529 {
530         struct task_struct *task = proc->task;
531         unsigned long start = umd->start;
532         size_t len = PAGE_ALIGN(umd->len);
533         LIST_HEAD(head);
534
535         if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
536                 struct sspt_file *file, *n;
537                 unsigned long end = start + len;
538                 struct msg_unmap_data msg_data = {
539                         .start = start,
540                         .end = end
541                 };
542
543                 list_for_each_entry_safe(file, n, &head, list) {
544                         if (file->vm_start >= end)
545                                 continue;
546
547                         if (file->vm_start >= start)
548                                 sspt_file_uninstall(file, task, US_UNINSTALL);
549                         /* TODO: else: uninstall pages: * start..file->vm_end */
550                 }
551
552                 sspt_proc_insert_files(proc, &head);
553
554                 sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data);
555         }
556 }
557
558 static void remove_unmap_probes(struct task_struct *task,
559                                 struct unmap_data *umd)
560 {
561         struct sspt_proc *proc;
562
563         sspt_proc_write_lock();
564
565         proc = sspt_proc_get_by_task_no_lock(task);
566         if (proc)
567                 __remove_unmap_probes(proc, umd);
568
569         sspt_proc_write_unlock();
570 }
571
572 static int entry_handler_unmap(struct kretprobe_instance *ri,
573                                struct pt_regs *regs)
574 {
575         struct unmap_data *data = (struct unmap_data *)ri->data;
576         struct task_struct *task = current->group_leader;
577
578         atomic_inc(&unmap_cnt);
579
580         data->start = swap_get_karg(regs, 1);
581         data->len = (size_t)swap_get_karg(regs, 2);
582
583         if (!is_kthread(task) && atomic_read(&stop_flag))
584                 remove_unmap_probes(task, data);
585
586         return 0;
587 }
588
589 static int ret_handler_unmap(struct kretprobe_instance *ri,
590                              struct pt_regs *regs)
591 {
592         struct task_struct *task;
593
594         task = current->group_leader;
595         if (is_kthread(task) || regs_return_value(regs))
596                 goto out;
597
598         remove_unmap_probes(task, (struct unmap_data *)ri->data);
599
600 out:
601         atomic_dec(&unmap_cnt);
602
603         return 0;
604 }
605
606 static struct kretprobe unmap_kretprobe = {
607         .entry_handler = entry_handler_unmap,
608         .handler = ret_handler_unmap,
609         .data_size = sizeof(struct unmap_data)
610 };
611
612 static int register_unmap(void)
613 {
614         int ret;
615
616         ret = swap_register_kretprobe(&unmap_kretprobe);
617         if (ret)
618                 printk(KERN_INFO "swap_register_kprobe(do_munmap) ret=%d!\n",
619                        ret);
620
621         return ret;
622 }
623
624 static void unregister_unmap(void)
625 {
626         swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
627         do {
628                 synchronize_sched();
629         } while (atomic_read(&unmap_cnt));
630         swap_unregister_kretprobe_bottom(&unmap_kretprobe);
631 }
632
633
634
635
636
637 /*
638  ******************************************************************************
639  *                               do_mmap_pgoff()                              *
640  ******************************************************************************
641  */
642 static void msg_map(struct sspt_filter *f, void *data)
643 {
644         if (f->pfg_is_inst) {
645                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
646
647                 if (cb && cb->msg_map)
648                         cb->msg_map((struct vm_area_struct *)data);
649         }
650 }
651
652 static int ret_handler_mmap(struct kretprobe_instance *ri,
653                             struct pt_regs *regs)
654 {
655         struct sspt_proc *proc;
656         struct task_struct *task;
657         unsigned long start_addr;
658         struct vm_area_struct *vma;
659
660         task = current->group_leader;
661         if (is_kthread(task))
662                 return 0;
663
664         start_addr = regs_return_value(regs);
665         if (IS_ERR_VALUE(start_addr))
666                 return 0;
667
668         proc = sspt_proc_get_by_task(task);
669         if (proc == NULL)
670                 return 0;
671
672         vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
673         if (vma && check_vma(vma))
674                 sspt_proc_on_each_filter(proc, msg_map, (void *)vma);
675
676         return 0;
677 }
678
679 static struct kretprobe mmap_kretprobe = {
680         .handler = ret_handler_mmap
681 };
682
683 static int register_mmap(void)
684 {
685         int ret;
686
687         ret = swap_register_kretprobe(&mmap_kretprobe);
688         if (ret)
689                 printk(KERN_INFO "swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n",
690                        ret);
691
692         return ret;
693 }
694
695 static void unregister_mmap(void)
696 {
697         swap_unregister_kretprobe(&mmap_kretprobe);
698 }
699
700
701
702
703
704 /*
705  ******************************************************************************
706  *                               set_task_comm()                              *
707  ******************************************************************************
708  */
709 struct comm_data {
710         struct task_struct *task;
711 };
712
713 static unsigned long cb_check_and_install(void *data)
714 {
715         check_task_and_install(current);
716
717         return 0;
718 }
719
720 static int entry_handler_comm(struct kretprobe_instance *ri,
721                               struct pt_regs *regs)
722 {
723         struct comm_data *data = (struct comm_data *)ri->data;
724
725         data->task = (struct task_struct *)swap_get_karg(regs, 0);
726
727         return 0;
728 }
729
730 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
731 {
732         struct task_struct *task;
733         int ret;
734
735         if (is_kthread(current))
736                 return 0;
737
738         task = ((struct comm_data *)ri->data)->task;
739         if (task != current)
740                 return 0;
741
742         ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
743                           cb_check_and_install, NULL, 0);
744         if (ret == 0)
745                 ri->ret_addr = (unsigned long *)get_jump_addr();
746
747         return 0;
748 }
749
750 static struct kretprobe comm_kretprobe = {
751         .entry_handler = entry_handler_comm,
752         .handler = ret_handler_comm,
753         .data_size = sizeof(struct comm_data)
754 };
755
756 static int register_comm(void)
757 {
758         int ret;
759
760         ret = swap_register_kretprobe(&comm_kretprobe);
761         if (ret)
762                 printk(KERN_INFO "swap_register_kretprobe(set_task_comm) ret=%d!\n",
763                        ret);
764
765         return ret;
766 }
767
768 static void unregister_comm(void)
769 {
770         swap_unregister_kretprobe(&comm_kretprobe);
771 }
772
773
774
775
776
777 /**
778  * @brief Registration of helper
779  *
780  * @return Error code
781  */
782 int register_helper(void)
783 {
784         int ret = 0;
785
786         atomic_set(&stop_flag, 0);
787
788         /*
789          * install probe on 'set_task_comm' to detect when field comm struct
790          * task_struct changes
791          */
792         ret = register_comm();
793         if (ret)
794                 return ret;
795
796         /* install probe on 'do_munmap' to detect when for remove US probes */
797         ret = register_unmap();
798         if (ret)
799                 goto unreg_comm;
800
801         /* install probe on 'mm_release' to detect when for remove US probes */
802         ret = register_mr();
803         if (ret)
804                 goto unreg_unmap;
805
806         /* install probe on 'copy_process' to disarm children process */
807         ret = register_cp();
808         if (ret)
809                 goto unreg_mr;
810
811         /* install probe on 'do_mmap_pgoff' to detect when mapping file */
812         ret = register_mmap();
813         if (ret)
814                 goto unreg_cp;
815
816         /*
817          * install probe on 'handle_mm_fault' to detect when US pages will be
818          * loaded
819          */
820         ret = register_mf();
821         if (ret)
822                 goto unreg_mmap;
823
824 #ifdef CONFIG_ARM
825         /* install probe to detect already running process */
826         ret = register_ctx_task();
827         if (ret)
828                 goto unreg_mf;
829 #endif /* CONFIG_ARM */
830
831         return ret;
832
833 #ifdef CONFIG_ARM
834 unreg_mf:
835         unregister_mf();
836 #endif /* CONFIG_ARM */
837
838 unreg_mmap:
839         unregister_mmap();
840
841 unreg_cp:
842         unregister_cp();
843
844 unreg_mr:
845         unregister_mr();
846
847 unreg_unmap:
848         unregister_unmap();
849
850 unreg_comm:
851         unregister_comm();
852
853         return ret;
854 }
855
856 /**
857  * @brief Unegistration of helper bottom
858  *
859  * @return Void
860  */
861 void unregister_helper_top(void)
862 {
863 #ifdef CONFIG_ARM
864         unregister_ctx_task();
865 #endif /* CONFIG_ARM */
866         unregister_mf();
867         atomic_set(&stop_flag, 1);
868 }
869
870 /**
871  * @brief Unegistration of helper top
872  *
873  * @return Void
874  */
875 void unregister_helper_bottom(void)
876 {
877         unregister_mmap();
878         unregister_cp();
879         unregister_mr();
880         unregister_unmap();
881         unregister_comm();
882 }
883
884 /**
885  * @brief Initialization of helper
886  *
887  * @return Error code
888  */
889 int once_helper(void)
890 {
891         const char *sym;
892
893         sym = "do_page_fault";
894         mf_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
895         if (mf_kretprobe.kp.addr == NULL)
896                 goto not_found;
897
898         sym = "copy_process";
899         cp_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms_substr(sym);
900         if (cp_kretprobe.kp.addr == NULL)
901                 goto not_found;
902         cp_kprobe.addr = cp_kretprobe.kp.addr;
903
904         sym = "mm_release";
905         mr_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
906         if (mr_kprobe.addr == NULL)
907                 goto not_found;
908
909         sym = "do_munmap";
910         unmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
911         if (unmap_kretprobe.kp.addr == NULL)
912                 goto not_found;
913
914         sym = "do_mmap_pgoff";
915         mmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
916         if (mmap_kretprobe.kp.addr == NULL)
917                 goto not_found;
918
919         sym = "set_task_comm";
920         comm_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
921         if (comm_kretprobe.kp.addr == NULL)
922                 goto not_found;
923
924 #ifdef CONFIG_ARM
925         sym = "ret_to_user";
926         ctx_task_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
927         if (ctx_task_kprobe.addr == NULL)
928                 goto not_found;
929 #endif /* CONFIG_ARM */
930
931         return 0;
932
933 not_found:
934         printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
935         return -ESRCH;
936 }