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