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 struct pt_regs *pf_regs;
52 unsigned long save_pc;
55 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
57 struct pf_data *data = (struct pf_data *)ri->data;
59 #if defined(CONFIG_ARM)
60 data->addr = swap_get_karg(regs, 0);
61 data->pf_regs = (struct pt_regs *)swap_get_karg(regs, 2);
62 data->save_pc = data->pf_regs->ARM_pc;
63 #elif defined(CONFIG_X86_32)
64 data->addr = read_cr2();
65 data->pf_regs = (struct pt_regs *)swap_get_karg(regs, 0);
66 data->save_pc = data->pf_regs->ip;
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 /* skip fixup page_fault */
112 #if defined(CONFIG_ARM)
113 if (data->save_pc != data->pf_regs->ARM_pc)
115 #elif defined(CONFIG_X86_32)
116 if (data->save_pc != data->pf_regs->ip)
118 #endif /* CONFIG_arch */
120 /* TODO: check return value */
121 page_addr = data->addr & PAGE_MASK;
122 ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_pf,
123 &page_addr, sizeof(page_addr));
126 ri->ret_addr = (unsigned long *)get_jump_addr();
131 static struct kretprobe mf_kretprobe = {
132 .entry_handler = entry_handler_pf,
133 .handler = ret_handler_pf,
134 .data_size = sizeof(struct pf_data)
137 static int register_mf(void)
141 ret = swap_register_kretprobe(&mf_kretprobe);
143 printk(KERN_INFO "swap_register_kretprobe(handle_mm_fault) ret=%d!\n",
149 static void unregister_mf(void)
151 swap_unregister_kretprobe(&mf_kretprobe);
159 ******************************************************************************
161 ******************************************************************************
163 static void disarm_ip(struct sspt_ip *ip, void *data)
165 struct task_struct *child = (struct task_struct *)data;
168 up = probe_info_get_uprobe(ip->desc->type, ip);
170 disarm_uprobe(up, child);
173 static atomic_t rm_uprobes_child_cnt = ATOMIC_INIT(0);
175 static unsigned long cb_clean_child(void *data)
177 struct task_struct *parent = current;
178 struct sspt_proc *proc;
180 proc = sspt_proc_get_by_task(parent);
182 struct task_struct *child = *(struct task_struct **)data;
184 /* disarm up for child */
185 sspt_proc_on_each_ip(proc, disarm_ip, (void *)child);
187 /* disarm urp for child */
188 swap_uretprobe_free_task(parent, child, false);
193 atomic_dec(&rm_uprobes_child_cnt);
196 static void rm_uprobes_child(struct kretprobe_instance *ri,
197 struct pt_regs *regs, struct task_struct *child)
201 if (!sspt_proc_by_task(current))
205 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
206 cb_clean_child, &child, sizeof(child));
208 atomic_inc(&rm_uprobes_child_cnt);
209 ri->ret_addr = (unsigned long *)get_jump_addr();
216 static int pre_handler_cp(struct kprobe *p, struct pt_regs *regs)
218 if (is_kthread(current))
221 if (atomic_read(&stop_flag))
222 call_mm_release(current);
229 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
231 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
233 atomic_inc(©_process_cnt);
238 /* Delete uprobs in children at fork */
239 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
241 struct task_struct *task =
242 (struct task_struct *)regs_return_value(regs);
244 if (!task || IS_ERR(task))
247 if (task->mm != current->mm) { /* check flags CLONE_VM */
248 rm_uprobes_child(ri, regs, task);
251 atomic_dec(©_process_cnt);
256 static struct kretprobe cp_kretprobe = {
257 .entry_handler = entry_handler_cp,
258 .handler = ret_handler_cp,
261 static struct kprobe cp_kprobe = {
262 .pre_handler = pre_handler_cp
265 static int register_cp(void)
270 ret = swap_register_kprobe(&cp_kprobe);
272 pr_err("swap_register_kprobe(copy_process) ret=%d!\n", ret);
274 ret = swap_register_kretprobe(&cp_kretprobe);
276 pr_err("swap_register_kretprobe(copy_process) ret=%d!\n", ret);
277 swap_unregister_kprobe(&cp_kprobe);
283 static void unregister_cp(void)
285 swap_unregister_kretprobe_top(&cp_kretprobe, 0);
288 } while (atomic_read(©_process_cnt));
289 swap_unregister_kretprobe_bottom(&cp_kretprobe);
290 swap_unregister_kprobe(&cp_kprobe);
294 } while (atomic_read(&rm_uprobes_child_cnt));
302 ******************************************************************************
304 ******************************************************************************
306 static void mr_handler(struct task_struct *task)
308 struct mm_struct *mm = task->mm;
311 pr_err("mm is NULL\n");
315 /* TODO: this lock for synchronizing to disarm urp */
316 down_write(&mm->mmap_sem);
317 if (task != task->group_leader) {
318 struct sspt_proc *proc;
320 if (task != current) {
321 pr_err("call mm_release in isn't current context\n");
325 /* if the thread is killed we need to discard pending
326 * uretprobe instances which have not triggered yet */
327 proc = sspt_proc_by_task(task);
329 swap_uretprobe_free_task(task, task, true);
331 call_mm_release(task);
333 up_write(&mm->mmap_sem);
336 /* Detects when target process removes IPs. */
337 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
339 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
341 if (is_kthread(task))
350 static struct kprobe mr_kprobe = {
351 .pre_handler = mr_pre_handler
354 static int register_mr(void)
358 ret = swap_register_kprobe(&mr_kprobe);
361 "swap_register_kprobe(mm_release) ret=%d!\n", ret);
366 static void unregister_mr(void)
368 swap_unregister_kprobe(&mr_kprobe);
376 ******************************************************************************
378 ******************************************************************************
385 static atomic_t unmap_cnt = ATOMIC_INIT(0);
387 struct msg_unmap_data {
392 static void msg_unmap(struct sspt_filter *f, void *data)
394 if (f->pfg_is_inst) {
395 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
397 if (cb && cb->msg_unmap) {
398 struct msg_unmap_data *msg_data;
400 msg_data = (struct msg_unmap_data *)data;
401 cb->msg_unmap(msg_data->start, msg_data->end);
406 static void __remove_unmap_probes(struct sspt_proc *proc,
407 struct unmap_data *umd)
409 unsigned long start = umd->start;
410 size_t len = umd->len;
413 if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
414 struct sspt_file *file, *n;
415 unsigned long end = start + len;
416 struct task_struct *task = proc->leader;
418 list_for_each_entry_safe(file, n, &head, list) {
419 if (file->vm_start >= end)
422 if (file->vm_start >= start)
423 sspt_file_uninstall(file, task, US_UNINSTALL);
424 /* TODO: else: uninstall pages: * start..file->vm_end */
427 sspt_proc_insert_files(proc, &head);
431 static unsigned long cb_munmap(void *data)
433 struct sspt_proc *proc;
434 struct unmap_data *umd = (struct unmap_data *)data;
436 proc = sspt_proc_get_by_task(current);
438 struct msg_unmap_data msg_data = {
440 .end = umd->start + umd->len,
443 __remove_unmap_probes(proc, umd);
445 /* send unmap region */
446 sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data);
451 atomic_dec(&unmap_cnt);
455 static int entry_handler_unmap(struct kretprobe_instance *ri,
456 struct pt_regs *regs)
458 struct unmap_data *data = (struct unmap_data *)ri->data;
460 data->start = swap_get_karg(regs, 1);
461 data->len = (size_t)PAGE_ALIGN(swap_get_karg(regs, 2));
463 atomic_inc(&unmap_cnt);
467 static int ret_handler_unmap(struct kretprobe_instance *ri,
468 struct pt_regs *regs)
472 if (regs_return_value(regs)) {
473 atomic_dec(&unmap_cnt);
477 ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_munmap,
478 (struct unmap_data *)ri->data,
479 sizeof(struct unmap_data));
481 ri->ret_addr = (unsigned long *)get_jump_addr();
484 atomic_dec(&unmap_cnt);
490 static struct kretprobe unmap_kretprobe = {
491 .entry_handler = entry_handler_unmap,
492 .handler = ret_handler_unmap,
493 .data_size = sizeof(struct unmap_data)
496 static int register_unmap(void)
500 ret = swap_register_kretprobe(&unmap_kretprobe);
502 printk(KERN_INFO "swap_register_kprobe(do_munmap) ret=%d!\n",
508 static void unregister_unmap(void)
510 swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
513 } while (atomic_read(&unmap_cnt));
514 swap_unregister_kretprobe_bottom(&unmap_kretprobe);
522 ******************************************************************************
524 ******************************************************************************
526 static void msg_map(struct sspt_filter *f, void *data)
528 if (f->pfg_is_inst) {
529 struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg);
531 if (cb && cb->msg_map)
532 cb->msg_map((struct vm_area_struct *)data);
536 static int ret_handler_mmap(struct kretprobe_instance *ri,
537 struct pt_regs *regs)
539 struct sspt_proc *proc;
540 struct task_struct *task;
541 unsigned long start_addr;
542 struct vm_area_struct *vma;
544 task = current->group_leader;
545 if (is_kthread(task))
548 start_addr = regs_return_value(regs);
549 if (IS_ERR_VALUE(start_addr))
552 proc = sspt_proc_get_by_task(task);
556 vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
557 if (vma && check_vma(vma))
558 sspt_proc_on_each_filter(proc, msg_map, (void *)vma);
564 static struct kretprobe mmap_kretprobe = {
565 .handler = ret_handler_mmap
568 static int register_mmap(void)
572 ret = swap_register_kretprobe(&mmap_kretprobe);
574 printk(KERN_INFO "swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n",
580 static void unregister_mmap(void)
582 swap_unregister_kretprobe(&mmap_kretprobe);
590 ******************************************************************************
592 ******************************************************************************
595 struct task_struct *task;
598 static unsigned long cb_check_and_install(void *data)
600 check_task_and_install(current);
605 static int entry_handler_comm(struct kretprobe_instance *ri,
606 struct pt_regs *regs)
608 struct comm_data *data = (struct comm_data *)ri->data;
610 data->task = (struct task_struct *)swap_get_karg(regs, 0);
615 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
617 struct task_struct *task;
620 if (is_kthread(current))
623 task = ((struct comm_data *)ri->data)->task;
627 ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
628 cb_check_and_install, NULL, 0);
630 ri->ret_addr = (unsigned long *)get_jump_addr();
635 static struct kretprobe comm_kretprobe = {
636 .entry_handler = entry_handler_comm,
637 .handler = ret_handler_comm,
638 .data_size = sizeof(struct comm_data)
641 static int register_comm(void)
645 ret = swap_register_kretprobe(&comm_kretprobe);
647 printk(KERN_INFO "swap_register_kretprobe(set_task_comm) ret=%d!\n",
653 static void unregister_comm(void)
655 swap_unregister_kretprobe(&comm_kretprobe);
662 ******************************************************************************
664 ******************************************************************************
666 static int release_task_h(struct kprobe *p, struct pt_regs *regs)
668 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
669 struct task_struct *cur = current;
671 if (cur->flags & PF_KTHREAD)
674 /* EXEC: change group leader */
675 if (cur != task && task->pid == cur->pid)
676 sspt_change_leader(task, cur);
681 struct kprobe release_task_kp = {
682 .pre_handler = release_task_h,
685 static int reg_release_task(void)
687 return swap_register_kprobe(&release_task_kp);
690 static void unreg_release_task(void)
692 swap_unregister_kprobe(&release_task_kp);
700 * @brief Registration of helper
704 int register_helper(void)
708 atomic_set(&stop_flag, 0);
710 /* tracking group leader changing */
711 ret = reg_release_task();
716 * install probe on 'set_task_comm' to detect when field comm struct
717 * task_struct changes
719 ret = register_comm();
723 /* install probe on 'do_munmap' to detect when for remove US probes */
724 ret = register_unmap();
728 /* install probe on 'mm_release' to detect when for remove US probes */
733 /* install probe on 'copy_process' to disarm children process */
738 /* install probe on 'do_mmap_pgoff' to detect when mapping file */
739 ret = register_mmap();
744 * install probe on 'handle_mm_fault' to detect when US pages will be
769 unreg_release_task();
775 * @brief Unegistration of helper bottom
779 void unregister_helper_top(void)
782 atomic_set(&stop_flag, 1);
786 * @brief Unegistration of helper top
790 void unregister_helper_bottom(void)
797 unreg_release_task();
801 * @brief Initialization of helper
805 int once_helper(void)
809 sym = "do_page_fault";
810 mf_kretprobe.kp.addr = swap_ksyms(sym);
811 if (mf_kretprobe.kp.addr == 0)
814 sym = "copy_process";
815 cp_kretprobe.kp.addr = swap_ksyms_substr(sym);
816 if (cp_kretprobe.kp.addr == 0)
818 cp_kprobe.addr = cp_kretprobe.kp.addr;
821 mr_kprobe.addr = swap_ksyms(sym);
822 if (mr_kprobe.addr == 0)
826 unmap_kretprobe.kp.addr = swap_ksyms(sym);
827 if (unmap_kretprobe.kp.addr == 0)
830 sym = "do_mmap_pgoff";
831 mmap_kretprobe.kp.addr = swap_ksyms(sym);
832 if (mmap_kretprobe.kp.addr == 0)
835 sym = "set_task_comm";
836 comm_kretprobe.kp.addr = swap_ksyms(sym);
837 if (comm_kretprobe.kp.addr == 0)
840 sym = "release_task";
841 release_task_kp.addr = swap_ksyms(sym);
842 if (release_task_kp.addr == 0)
848 printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);