3 * modules/us_manager/helper.c
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.
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.
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.
19 * Copyright (C) Samsung Electronics, 2013
21 * 2013 Vyacheslav Cherkashin: SWAP us_manager implement
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"
37 struct task_struct *check_task(struct task_struct *task);
39 static atomic_t stop_flag = ATOMIC_INIT(0);
43 ******************************************************************************
45 ******************************************************************************
51 #if defined(CONFIG_ARM)
52 struct pt_regs *pf_regs;
53 unsigned long save_pc;
54 #endif /* CONFIG_ARM */
57 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
59 struct pf_data *data = (struct pf_data *)ri->data;
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();
68 #error "this architecture is not supported"
69 #endif /* CONFIG_arch */
73 struct sspt_proc *proc;
75 proc = sspt_proc_get_by_task(current);
77 if (proc->r_state_addr == data->addr) {
78 /* skip ret_handler_pf() for current task */
91 static unsigned long cb_pf(void *data)
93 unsigned long page_addr = *(unsigned long *)data;
95 call_page_fault(current, page_addr);
100 /* Detects when IPs are really loaded into phy mem and installs probes. */
101 static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
103 struct task_struct *task = current;
104 struct pf_data *data = (struct pf_data *)ri->data;
105 unsigned long page_addr;
108 if (is_kthread(task))
111 #if defined(CONFIG_ARM)
112 /* skip fixup page_fault */
113 if (data->save_pc != data->pf_regs->ARM_pc)
115 #endif /* CONFIG_ARM */
117 /* TODO: check return value */
118 page_addr = data->addr & PAGE_MASK;
119 ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_pf,
120 &page_addr, sizeof(page_addr));
123 ri->ret_addr = (unsigned long *)get_jump_addr();
128 static struct kretprobe mf_kretprobe = {
129 .entry_handler = entry_handler_pf,
130 .handler = ret_handler_pf,
131 .data_size = sizeof(struct pf_data)
134 static int register_mf(void)
138 ret = swap_register_kretprobe(&mf_kretprobe);
140 printk(KERN_INFO "swap_register_kretprobe(handle_mm_fault) ret=%d!\n",
146 static void unregister_mf(void)
148 swap_unregister_kretprobe(&mf_kretprobe);
156 ******************************************************************************
158 ******************************************************************************
160 static void disarm_ip(struct sspt_ip *ip, void *data)
162 struct task_struct *child = (struct task_struct *)data;
165 up = probe_info_get_uprobe(ip->desc->type, ip);
167 disarm_uprobe(up, child);
170 static atomic_t rm_uprobes_child_cnt = ATOMIC_INIT(0);
172 static unsigned long cb_clean_child(void *data)
174 struct task_struct *parent = current;
175 struct sspt_proc *proc;
177 proc = sspt_proc_get_by_task(parent);
179 struct task_struct *child = *(struct task_struct **)data;
181 /* disarm up for child */
182 sspt_proc_on_each_ip(proc, disarm_ip, (void *)child);
184 /* disarm urp for child */
185 swap_uretprobe_free_task(parent, child, false);
190 atomic_dec(&rm_uprobes_child_cnt);
193 static void rm_uprobes_child(struct kretprobe_instance *ri,
194 struct pt_regs *regs, struct task_struct *child)
198 if (!sspt_proc_by_task(current))
202 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
203 cb_clean_child, &child, sizeof(child));
205 atomic_inc(&rm_uprobes_child_cnt);
206 ri->ret_addr = (unsigned long *)get_jump_addr();
213 static atomic_t pre_handler_cp_cnt = ATOMIC_INIT(0);
215 static unsigned long cp_cb(void *data)
217 if (atomic_read(&stop_flag))
218 call_mm_release(current);
220 atomic_dec(&pre_handler_cp_cnt);
224 static int pre_handler_cp(struct kprobe *p, struct pt_regs *regs)
228 if (is_kthread(current))
231 if (!atomic_read(&stop_flag))
234 ret = set_kjump_cb(regs, cp_cb, NULL, 0);
236 pr_err("set_kjump_cp, ret=%d\n", ret);
239 atomic_inc(&pre_handler_cp_cnt);
246 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
248 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
250 atomic_inc(©_process_cnt);
255 /* Delete uprobs in children at fork */
256 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
258 struct task_struct *task =
259 (struct task_struct *)regs_return_value(regs);
261 if (!task || IS_ERR(task))
264 if (task->mm != current->mm) { /* check flags CLONE_VM */
265 rm_uprobes_child(ri, regs, task);
268 atomic_dec(©_process_cnt);
273 static struct kretprobe cp_kretprobe = {
274 .entry_handler = entry_handler_cp,
275 .handler = ret_handler_cp,
278 static struct kprobe cp_kprobe = {
279 .pre_handler = pre_handler_cp
282 static int register_cp(void)
287 ret = swap_register_kprobe(&cp_kprobe);
289 pr_err("swap_register_kprobe(copy_process) ret=%d!\n", ret);
291 ret = swap_register_kretprobe(&cp_kretprobe);
293 pr_err("swap_register_kretprobe(copy_process) ret=%d!\n", ret);
294 swap_unregister_kprobe(&cp_kprobe);
300 static void unregister_cp(void)
302 swap_unregister_kretprobe_top(&cp_kretprobe, 0);
305 } while (atomic_read(©_process_cnt));
306 swap_unregister_kretprobe_bottom(&cp_kretprobe);
307 swap_unregister_kprobe(&cp_kprobe);
311 } while (atomic_read(&rm_uprobes_child_cnt)
312 || atomic_read(&pre_handler_cp_cnt));
320 ******************************************************************************
322 ******************************************************************************
325 static atomic_t mm_release_cnt = ATOMIC_INIT(0);
327 static unsigned long mr_cb(void *data)
329 struct task_struct *task = *(struct task_struct **)data;
330 struct mm_struct *mm = task->mm;
333 pr_err("mm is NULL\n");
337 /* TODO: this lock for synchronizing to disarm urp */
338 down_write(&mm->mmap_sem);
339 if (task != task->group_leader) {
340 struct sspt_proc *proc;
342 if (task != current) {
343 pr_err("call mm_release in isn't current context\n");
347 /* if the thread is killed we need to discard pending
348 * uretprobe instances which have not triggered yet */
349 proc = sspt_proc_by_task(task);
351 swap_uretprobe_free_task(task, task, true);
353 call_mm_release(task);
355 up_write(&mm->mmap_sem);
357 atomic_dec(&mm_release_cnt);
362 /* Detects when target process removes IPs. */
363 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
366 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
368 if (is_kthread(task))
371 ret = set_kjump_cb(regs, mr_cb, (void *)&task, sizeof(task));
373 printk("##### ERROR: mr_pre_handler, ret=%d\n", ret);
376 atomic_inc(&mm_release_cnt);
383 static struct kprobe mr_kprobe = {
384 .pre_handler = mr_pre_handler
387 static int register_mr(void)
391 ret = swap_register_kprobe(&mr_kprobe);
394 "swap_register_kprobe(mm_release) ret=%d!\n", ret);
399 static void unregister_mr(void)
401 swap_unregister_kprobe(&mr_kprobe);
404 } while (atomic_read(&mm_release_cnt));
412 ******************************************************************************
414 ******************************************************************************
421 static atomic_t unmap_cnt = ATOMIC_INIT(0);
423 struct msg_unmap_data {
428 static void msg_unmap(struct sspt_filter *f, void *data)
430 if (f->pfg_is_inst) {
431 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
433 if (cb && cb->msg_unmap) {
434 struct msg_unmap_data *msg_data;
436 msg_data = (struct msg_unmap_data *)data;
437 cb->msg_unmap(msg_data->start, msg_data->end);
442 static void __remove_unmap_probes(struct sspt_proc *proc,
443 struct unmap_data *umd)
445 unsigned long start = umd->start;
446 size_t len = umd->len;
449 if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
450 struct sspt_file *file, *n;
451 unsigned long end = start + len;
452 struct task_struct *task = proc->leader;
454 list_for_each_entry_safe(file, n, &head, list) {
455 if (file->vm_start >= end)
458 if (file->vm_start >= start)
459 sspt_file_uninstall(file, task, US_UNINSTALL);
460 /* TODO: else: uninstall pages: * start..file->vm_end */
463 sspt_proc_insert_files(proc, &head);
467 static unsigned long cb_munmap(void *data)
469 struct sspt_proc *proc;
470 struct unmap_data *umd = (struct unmap_data *)data;
472 proc = sspt_proc_get_by_task(current);
474 struct msg_unmap_data msg_data = {
476 .end = umd->start + umd->len,
479 __remove_unmap_probes(proc, umd);
481 /* send unmap region */
482 sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data);
487 atomic_dec(&unmap_cnt);
491 static int entry_handler_unmap(struct kretprobe_instance *ri,
492 struct pt_regs *regs)
494 struct unmap_data *data = (struct unmap_data *)ri->data;
496 data->start = swap_get_karg(regs, 1);
497 data->len = (size_t)PAGE_ALIGN(swap_get_karg(regs, 2));
499 atomic_inc(&unmap_cnt);
503 static int ret_handler_unmap(struct kretprobe_instance *ri,
504 struct pt_regs *regs)
508 if (regs_return_value(regs)) {
509 atomic_dec(&unmap_cnt);
513 ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_munmap,
514 (struct unmap_data *)ri->data,
515 sizeof(struct unmap_data));
517 ri->ret_addr = (unsigned long *)get_jump_addr();
520 atomic_dec(&unmap_cnt);
526 static struct kretprobe unmap_kretprobe = {
527 .entry_handler = entry_handler_unmap,
528 .handler = ret_handler_unmap,
529 .data_size = sizeof(struct unmap_data)
532 static int register_unmap(void)
536 ret = swap_register_kretprobe(&unmap_kretprobe);
538 printk(KERN_INFO "swap_register_kprobe(do_munmap) ret=%d!\n",
544 static void unregister_unmap(void)
546 swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
549 } while (atomic_read(&unmap_cnt));
550 swap_unregister_kretprobe_bottom(&unmap_kretprobe);
558 ******************************************************************************
560 ******************************************************************************
562 static void msg_map(struct sspt_filter *f, void *data)
564 if (f->pfg_is_inst) {
565 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
567 if (cb && cb->msg_map)
568 cb->msg_map((struct vm_area_struct *)data);
572 static int ret_handler_mmap(struct kretprobe_instance *ri,
573 struct pt_regs *regs)
575 struct sspt_proc *proc;
576 struct task_struct *task;
577 unsigned long start_addr;
578 struct vm_area_struct *vma;
580 task = current->group_leader;
581 if (is_kthread(task))
584 start_addr = regs_return_value(regs);
585 if (IS_ERR_VALUE(start_addr))
588 proc = sspt_proc_get_by_task(task);
592 vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
593 if (vma && check_vma(vma))
594 sspt_proc_on_each_filter(proc, msg_map, (void *)vma);
600 static struct kretprobe mmap_kretprobe = {
601 .handler = ret_handler_mmap
604 static int register_mmap(void)
608 ret = swap_register_kretprobe(&mmap_kretprobe);
610 printk(KERN_INFO "swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n",
616 static void unregister_mmap(void)
618 swap_unregister_kretprobe(&mmap_kretprobe);
626 ******************************************************************************
628 ******************************************************************************
631 struct task_struct *task;
634 static unsigned long cb_check_and_install(void *data)
636 check_task_and_install(current);
641 static int entry_handler_comm(struct kretprobe_instance *ri,
642 struct pt_regs *regs)
644 struct comm_data *data = (struct comm_data *)ri->data;
646 data->task = (struct task_struct *)swap_get_karg(regs, 0);
651 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
653 struct task_struct *task;
656 if (is_kthread(current))
659 task = ((struct comm_data *)ri->data)->task;
663 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
664 cb_check_and_install, NULL, 0);
666 ri->ret_addr = (unsigned long *)get_jump_addr();
671 static struct kretprobe comm_kretprobe = {
672 .entry_handler = entry_handler_comm,
673 .handler = ret_handler_comm,
674 .data_size = sizeof(struct comm_data)
677 static int register_comm(void)
681 ret = swap_register_kretprobe(&comm_kretprobe);
683 printk(KERN_INFO "swap_register_kretprobe(set_task_comm) ret=%d!\n",
689 static void unregister_comm(void)
691 swap_unregister_kretprobe(&comm_kretprobe);
698 ******************************************************************************
700 ******************************************************************************
702 static int release_task_h(struct kprobe *p, struct pt_regs *regs)
704 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
705 struct task_struct *cur = current;
707 if (cur->flags & PF_KTHREAD)
710 /* EXEC: change group leader */
711 if (cur != task && task->pid == cur->pid)
712 sspt_change_leader(task, cur);
717 struct kprobe release_task_kp = {
718 .pre_handler = release_task_h,
721 static int reg_release_task(void)
723 return swap_register_kprobe(&release_task_kp);
726 static void unreg_release_task(void)
728 swap_unregister_kprobe(&release_task_kp);
736 * @brief Registration of helper
740 int register_helper(void)
744 atomic_set(&stop_flag, 0);
746 /* tracking group leader changing */
747 ret = reg_release_task();
752 * install probe on 'set_task_comm' to detect when field comm struct
753 * task_struct changes
755 ret = register_comm();
759 /* install probe on 'do_munmap' to detect when for remove US probes */
760 ret = register_unmap();
764 /* install probe on 'mm_release' to detect when for remove US probes */
769 /* install probe on 'copy_process' to disarm children process */
774 /* install probe on 'do_mmap_pgoff' to detect when mapping file */
775 ret = register_mmap();
780 * install probe on 'handle_mm_fault' to detect when US pages will be
805 unreg_release_task();
811 * @brief Unegistration of helper bottom
815 void unregister_helper_top(void)
818 atomic_set(&stop_flag, 1);
822 * @brief Unegistration of helper top
826 void unregister_helper_bottom(void)
833 unreg_release_task();
837 * @brief Initialization of helper
841 int once_helper(void)
845 sym = "do_page_fault";
846 mf_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
847 if (mf_kretprobe.kp.addr == NULL)
850 sym = "copy_process";
851 cp_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms_substr(sym);
852 if (cp_kretprobe.kp.addr == NULL)
854 cp_kprobe.addr = cp_kretprobe.kp.addr;
857 mr_kprobe.addr = (kprobe_opcode_t *)swap_ksyms(sym);
858 if (mr_kprobe.addr == NULL)
862 unmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
863 if (unmap_kretprobe.kp.addr == NULL)
866 sym = "do_mmap_pgoff";
867 mmap_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
868 if (mmap_kretprobe.kp.addr == NULL)
871 sym = "set_task_comm";
872 comm_kretprobe.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
873 if (comm_kretprobe.kp.addr == NULL)
876 sym = "release_task";
877 release_task_kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
878 if (release_task_kp.addr == NULL)
884 printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);