Merge branch 'tizen_2.4' into tizen_2.4_dev
[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         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->desc->type, ip);
211         if (up) {
212                 struct uinst_info *uinst;
213                 unsigned long vaddr = (unsigned long)up->addr;
214
215                 uinst = uinst_info_create(vaddr, up->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                 ret = 0;
461         } else {
462                 atomic_inc(&mm_release_cnt);
463         }
464
465 out:
466         return ret;
467 }
468
469 static struct kprobe mr_kprobe = {
470         .pre_handler = mr_pre_handler
471 };
472
473 static int register_mr(void)
474 {
475         int ret;
476
477         ret = swap_register_kprobe(&mr_kprobe);
478         if (ret)
479                 printk(KERN_INFO
480                        "swap_register_kprobe(mm_release) ret=%d!\n", ret);
481
482         return ret;
483 }
484
485 static void unregister_mr(void)
486 {
487         swap_unregister_kprobe(&mr_kprobe);
488         do {
489                 synchronize_sched();
490         } while (atomic_read(&mm_release_cnt));
491 }
492
493
494
495
496
497 /*
498  ******************************************************************************
499  *                                 do_munmap()                                *
500  ******************************************************************************
501  */
502 struct unmap_data {
503         unsigned long start;
504         size_t len;
505 };
506
507 static atomic_t unmap_cnt = ATOMIC_INIT(0);
508
509 struct msg_unmap_data {
510         unsigned long start;
511         unsigned long end;
512 };
513
514 static void msg_unmap(struct sspt_filter *f, void *data)
515 {
516         if (f->pfg_is_inst) {
517                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
518
519                 if (cb && cb->msg_unmap) {
520                         struct msg_unmap_data *msg_data;
521
522                         msg_data = (struct msg_unmap_data *)data;
523                         cb->msg_unmap(msg_data->start, msg_data->end);
524                 }
525         }
526 }
527
528 static void __remove_unmap_probes(struct sspt_proc *proc,
529                                   struct unmap_data *umd)
530 {
531         struct task_struct *task = proc->task;
532         unsigned long start = umd->start;
533         size_t len = PAGE_ALIGN(umd->len);
534         LIST_HEAD(head);
535
536         if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
537                 struct sspt_file *file, *n;
538                 unsigned long end = start + len;
539                 struct msg_unmap_data msg_data = {
540                         .start = start,
541                         .end = end
542                 };
543
544                 list_for_each_entry_safe(file, n, &head, list) {
545                         if (file->vm_start >= end)
546                                 continue;
547
548                         if (file->vm_start >= start)
549                                 sspt_file_uninstall(file, task, US_UNINSTALL);
550                         /* TODO: else: uninstall pages: * start..file->vm_end */
551                 }
552
553                 sspt_proc_insert_files(proc, &head);
554
555                 sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data);
556         }
557 }
558
559 static void remove_unmap_probes(struct task_struct *task,
560                                 struct unmap_data *umd)
561 {
562         struct sspt_proc *proc;
563
564         sspt_proc_write_lock();
565
566         proc = sspt_proc_get_by_task_no_lock(task);
567         if (proc)
568                 __remove_unmap_probes(proc, umd);
569
570         sspt_proc_write_unlock();
571 }
572
573 static int entry_handler_unmap(struct kretprobe_instance *ri,
574                                struct pt_regs *regs)
575 {
576         struct unmap_data *data = (struct unmap_data *)ri->data;
577         struct task_struct *task = current->group_leader;
578
579         atomic_inc(&unmap_cnt);
580
581         data->start = swap_get_karg(regs, 1);
582         data->len = (size_t)swap_get_karg(regs, 2);
583
584         if (!is_kthread(task) && atomic_read(&stop_flag))
585                 remove_unmap_probes(task, data);
586
587         return 0;
588 }
589
590 static int ret_handler_unmap(struct kretprobe_instance *ri,
591                              struct pt_regs *regs)
592 {
593         struct task_struct *task;
594
595         task = current->group_leader;
596         if (is_kthread(task) || regs_return_value(regs))
597                 goto out;
598
599         remove_unmap_probes(task, (struct unmap_data *)ri->data);
600
601 out:
602         atomic_dec(&unmap_cnt);
603
604         return 0;
605 }
606
607 static struct kretprobe unmap_kretprobe = {
608         .entry_handler = entry_handler_unmap,
609         .handler = ret_handler_unmap,
610         .data_size = sizeof(struct unmap_data)
611 };
612
613 static int register_unmap(void)
614 {
615         int ret;
616
617         ret = swap_register_kretprobe(&unmap_kretprobe);
618         if (ret)
619                 printk(KERN_INFO "swap_register_kprobe(do_munmap) ret=%d!\n",
620                        ret);
621
622         return ret;
623 }
624
625 static void unregister_unmap(void)
626 {
627         swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
628         do {
629                 synchronize_sched();
630         } while (atomic_read(&unmap_cnt));
631         swap_unregister_kretprobe_bottom(&unmap_kretprobe);
632 }
633
634
635
636
637
638 /*
639  ******************************************************************************
640  *                               do_mmap_pgoff()                              *
641  ******************************************************************************
642  */
643 static void msg_map(struct sspt_filter *f, void *data)
644 {
645         if (f->pfg_is_inst) {
646                 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
647
648                 if (cb && cb->msg_map)
649                         cb->msg_map((struct vm_area_struct *)data);
650         }
651 }
652
653 static int ret_handler_mmap(struct kretprobe_instance *ri,
654                             struct pt_regs *regs)
655 {
656         struct sspt_proc *proc;
657         struct task_struct *task;
658         unsigned long start_addr;
659         struct vm_area_struct *vma;
660
661         task = current->group_leader;
662         if (is_kthread(task))
663                 return 0;
664
665         start_addr = regs_return_value(regs);
666         if (IS_ERR_VALUE(start_addr))
667                 return 0;
668
669         proc = sspt_proc_get_by_task(task);
670         if (proc == NULL)
671                 return 0;
672
673         vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
674         if (vma && check_vma(vma))
675                 sspt_proc_on_each_filter(proc, msg_map, (void *)vma);
676
677         return 0;
678 }
679
680 static struct kretprobe mmap_kretprobe = {
681         .handler = ret_handler_mmap
682 };
683
684 static int register_mmap(void)
685 {
686         int ret;
687
688         ret = swap_register_kretprobe(&mmap_kretprobe);
689         if (ret)
690                 printk(KERN_INFO "swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n",
691                        ret);
692
693         return ret;
694 }
695
696 static void unregister_mmap(void)
697 {
698         swap_unregister_kretprobe(&mmap_kretprobe);
699 }
700
701
702
703
704
705 /*
706  ******************************************************************************
707  *                               set_task_comm()                              *
708  ******************************************************************************
709  */
710 struct comm_data {
711         struct task_struct *task;
712 };
713
714 static unsigned long cb_check_and_install(void *data)
715 {
716         check_task_and_install(current);
717
718         return 0;
719 }
720
721 static int entry_handler_comm(struct kretprobe_instance *ri,
722                               struct pt_regs *regs)
723 {
724         struct comm_data *data = (struct comm_data *)ri->data;
725
726         data->task = (struct task_struct *)swap_get_karg(regs, 0);
727
728         return 0;
729 }
730
731 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
732 {
733         struct task_struct *task;
734         int ret;
735
736         if (is_kthread(current))
737                 return 0;
738
739         task = ((struct comm_data *)ri->data)->task;
740         if (task != current)
741                 return 0;
742
743         ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
744                           cb_check_and_install, NULL, 0);
745         if (ret == 0)
746                 ri->ret_addr = (unsigned long *)get_jump_addr();
747
748         return 0;
749 }
750
751 static struct kretprobe comm_kretprobe = {
752         .entry_handler = entry_handler_comm,
753         .handler = ret_handler_comm,
754         .data_size = sizeof(struct comm_data)
755 };
756
757 static int register_comm(void)
758 {
759         int ret;
760
761         ret = swap_register_kretprobe(&comm_kretprobe);
762         if (ret)
763                 printk(KERN_INFO "swap_register_kretprobe(set_task_comm) ret=%d!\n",
764                        ret);
765
766         return ret;
767 }
768
769 static void unregister_comm(void)
770 {
771         swap_unregister_kretprobe(&comm_kretprobe);
772 }
773
774
775
776
777
778 /**
779  * @brief Registration of helper
780  *
781  * @return Error code
782  */
783 int register_helper(void)
784 {
785         int ret = 0;
786
787         atomic_set(&stop_flag, 0);
788
789         /*
790          * install probe on 'set_task_comm' to detect when field comm struct
791          * task_struct changes
792          */
793         ret = register_comm();
794         if (ret)
795                 return ret;
796
797         /* install probe on 'do_munmap' to detect when for remove US probes */
798         ret = register_unmap();
799         if (ret)
800                 goto unreg_comm;
801
802         /* install probe on 'mm_release' to detect when for remove US probes */
803         ret = register_mr();
804         if (ret)
805                 goto unreg_unmap;
806
807         /* install probe on 'copy_process' to disarm children process */
808         ret = register_cp();
809         if (ret)
810                 goto unreg_mr;
811
812         /* install probe on 'do_mmap_pgoff' to detect when mapping file */
813         ret = register_mmap();
814         if (ret)
815                 goto unreg_cp;
816
817         /*
818          * install probe on 'handle_mm_fault' to detect when US pages will be
819          * loaded
820          */
821         ret = register_mf();
822         if (ret)
823                 goto unreg_mmap;
824
825 #ifdef CONFIG_ARM
826         /* install probe to detect already running process */
827         ret = register_ctx_task();
828         if (ret)
829                 goto unreg_mf;
830 #endif /* CONFIG_ARM */
831
832         return ret;
833
834 #ifdef CONFIG_ARM
835 unreg_mf:
836         unregister_mf();
837 #endif /* CONFIG_ARM */
838
839 unreg_mmap:
840         unregister_mmap();
841
842 unreg_cp:
843         unregister_cp();
844
845 unreg_mr:
846         unregister_mr();
847
848 unreg_unmap:
849         unregister_unmap();
850
851 unreg_comm:
852         unregister_comm();
853
854         return ret;
855 }
856
857 /**
858  * @brief Unegistration of helper bottom
859  *
860  * @return Void
861  */
862 void unregister_helper_top(void)
863 {
864 #ifdef CONFIG_ARM
865         unregister_ctx_task();
866 #endif /* CONFIG_ARM */
867         unregister_mf();
868         atomic_set(&stop_flag, 1);
869 }
870
871 /**
872  * @brief Unegistration of helper top
873  *
874  * @return Void
875  */
876 void unregister_helper_bottom(void)
877 {
878         unregister_mmap();
879         unregister_cp();
880         unregister_mr();
881         unregister_unmap();
882         unregister_comm();
883 }
884
885 /**
886  * @brief Initialization of helper
887  *
888  * @return Error code
889  */
890 int once_helper(void)
891 {
892         const char *sym;
893
894         sym = "do_page_fault";
895         mf_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
896         if (mf_kretprobe.kp.addr == NULL)
897                 goto not_found;
898
899         sym = "copy_process";
900         cp_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms_substr(sym);
901         if (cp_kretprobe.kp.addr == NULL)
902                 goto not_found;
903         cp_kprobe.addr = cp_kretprobe.kp.addr;
904
905         sym = "mm_release";
906         mr_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
907         if (mr_kprobe.addr == NULL)
908                 goto not_found;
909
910         sym = "do_munmap";
911         unmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
912         if (unmap_kretprobe.kp.addr == NULL)
913                 goto not_found;
914
915         sym = "do_mmap_pgoff";
916         mmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
917         if (mmap_kretprobe.kp.addr == NULL)
918                 goto not_found;
919
920         sym = "set_task_comm";
921         comm_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
922         if (comm_kretprobe.kp.addr == NULL)
923                 goto not_found;
924
925 #ifdef CONFIG_ARM
926         sym = "ret_to_user";
927         ctx_task_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
928         if (ctx_task_kprobe.addr == NULL)
929                 goto not_found;
930 #endif /* CONFIG_ARM */
931
932         return 0;
933
934 not_found:
935         printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
936         return -ESRCH;
937 }