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 <writer/swap_writer_module.h>
31 #include "us_slot_manager.h"
32 #include "sspt/sspt.h"
37 struct task_struct *check_task(struct task_struct *task);
39 static atomic_t stop_flag = ATOMIC_INIT(0);
43 ******************************************************************************
45 ******************************************************************************
52 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
54 struct pf_data *data = (struct pf_data *)ri->data;
56 #if defined(CONFIG_ARM)
57 data->addr = swap_get_karg(regs, 0);
58 #elif defined(CONFIG_X86_32)
59 data->addr = read_cr2();
61 #error "this architecture is not supported"
62 #endif /* CONFIG_arch */
67 static unsigned long cb_pf(void *data)
69 unsigned long page_addr = *(unsigned long *)data;
71 call_page_fault(current, page_addr);
76 /* Detects when IPs are really loaded into phy mem and installs probes. */
77 static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
79 struct task_struct *task = current;
80 unsigned long page_addr;
86 /* TODO: check return value */
87 page_addr = ((struct pf_data *)ri->data)->addr & PAGE_MASK;
88 ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_pf,
89 &page_addr, sizeof(page_addr));
92 ri->ret_addr = (unsigned long *)get_jump_addr();
97 static struct kretprobe mf_kretprobe = {
98 .entry_handler = entry_handler_pf,
99 .handler = ret_handler_pf,
100 .data_size = sizeof(struct pf_data)
103 static int register_mf(void)
107 ret = swap_register_kretprobe(&mf_kretprobe);
109 printk("swap_register_kretprobe(handle_mm_fault) ret=%d!\n",
115 static void unregister_mf(void)
117 swap_unregister_kretprobe(&mf_kretprobe);
126 ******************************************************************************
127 * workaround for already running *
128 ******************************************************************************
130 static int ctx_task_pre_handler(struct kprobe *p, struct pt_regs *regs)
132 struct sspt_proc *proc;
133 unsigned long page_addr;
134 struct task_struct *task = current;
136 if (is_kthread(task) || check_task_on_filters(task) == 0)
139 proc = sspt_proc_get_by_task(task);
140 if (proc && proc->first_install)
144 set_kjump_cb(regs, cb_pf, &page_addr, sizeof(page_addr));
149 static struct kprobe ctx_task_kprobe = {
150 .pre_handler = ctx_task_pre_handler,
153 static int register_ctx_task(void)
157 ret = swap_register_kprobe(&ctx_task_kprobe);
159 printk("swap_register_kprobe(workaround) ret=%d!\n", ret);
164 static void unregister_ctx_task(void)
166 swap_unregister_kprobe(&ctx_task_kprobe);
168 #endif /* CONFIG_ARM */
175 ******************************************************************************
177 ******************************************************************************
179 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
181 static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
183 sspt_proc_uninstall(proc, child_task, US_DISARM);
184 swap_disarm_urp_inst_for_task(current, child_task);
187 static void rm_uprobes_child(struct task_struct *task)
189 struct sspt_proc *proc;
191 sspt_proc_write_lock();
193 proc = sspt_proc_get_by_task(current);
195 recover_child(task, proc);
197 sspt_proc_write_unlock();
200 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
202 atomic_inc(©_process_cnt);
204 if (atomic_read(&stop_flag))
205 call_mm_release(current);
210 /* Delete uprobs in children at fork */
211 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
213 struct task_struct *task = (struct task_struct *)regs_return_value(regs);
215 if(!task || IS_ERR(task))
218 if(task->mm != current->mm) { /* check flags CLONE_VM */
219 rm_uprobes_child(task);
222 atomic_dec(©_process_cnt);
227 static struct kretprobe cp_kretprobe = {
228 .entry_handler = entry_handler_cp,
229 .handler = ret_handler_cp,
232 static int register_cp(void)
236 ret = swap_register_kretprobe(&cp_kretprobe);
238 printk("swap_register_kretprobe(copy_process) ret=%d!\n", ret);
243 static void unregister_cp(void)
245 swap_unregister_kretprobe_top(&cp_kretprobe, 0);
248 } while (atomic_read(©_process_cnt));
249 swap_unregister_kretprobe_bottom(&cp_kretprobe);
257 ******************************************************************************
259 ******************************************************************************
262 /* Detects when target process removes IPs. */
263 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
265 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
267 if (is_kthread(task))
270 if (task->tgid != task->pid) {
271 /* if the thread is killed we need to discard pending
272 * uretprobe instances which have not triggered yet */
273 swap_discard_pending_uretprobes(task);
277 call_mm_release(task);
282 static struct kprobe mr_kprobe = {
283 .pre_handler = mr_pre_handler
286 static int register_mr(void)
290 ret = swap_register_kprobe(&mr_kprobe);
292 printk("swap_register_kprobe(mm_release) ret=%d!\n", ret);
297 static void unregister_mr(void)
299 swap_unregister_kprobe(&mr_kprobe);
307 ******************************************************************************
309 ******************************************************************************
316 static atomic_t unmap_cnt = ATOMIC_INIT(0);
318 static void __remove_unmap_probes(struct sspt_proc *proc,
319 struct unmap_data *umd)
321 struct task_struct *task = proc->task;
322 unsigned long start = umd->start;
323 size_t len = PAGE_ALIGN(umd->len);
326 if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
327 struct sspt_file *file, *n;
328 unsigned long end = start + len;
330 list_for_each_entry_safe(file, n, &head, list) {
331 if (file->vm_start >= end)
334 if (file->vm_start >= start) {
335 sspt_file_uninstall(file, task, US_UNINSTALL);
337 /* TODO: uninstall pages: start..file->vm_end */
341 sspt_proc_insert_files(proc, &head);
343 proc_unmap_msg(start, end);
347 static void remove_unmap_probes(struct task_struct *task,
348 struct unmap_data *umd)
350 struct sspt_proc *proc;
352 sspt_proc_write_lock();
354 proc = sspt_proc_get_by_task(task);
356 __remove_unmap_probes(proc, umd);
358 sspt_proc_write_unlock();
361 static int entry_handler_unmap(struct kretprobe_instance *ri,
362 struct pt_regs *regs)
364 struct unmap_data *data = (struct unmap_data *)ri->data;
365 struct task_struct *task = current->group_leader;
367 atomic_inc(&unmap_cnt);
369 data->start = swap_get_karg(regs, 1);
370 data->len = (size_t)swap_get_karg(regs, 2);
372 if (!is_kthread(task) && atomic_read(&stop_flag))
373 remove_unmap_probes(task, data);
378 static int ret_handler_unmap(struct kretprobe_instance *ri,
379 struct pt_regs *regs)
381 struct task_struct *task;
383 task = current->group_leader;
384 if (is_kthread(task) ||
385 get_regs_ret_val(regs))
388 remove_unmap_probes(task, (struct unmap_data *)ri->data);
391 atomic_dec(&unmap_cnt);
396 static struct kretprobe unmap_kretprobe = {
397 .entry_handler = entry_handler_unmap,
398 .handler = ret_handler_unmap,
399 .data_size = sizeof(struct unmap_data)
402 static int register_unmap(void)
406 ret = swap_register_kretprobe(&unmap_kretprobe);
408 printk("swap_register_kprobe(do_munmap) ret=%d!\n", ret);
413 static void unregister_unmap(void)
415 swap_unregister_kretprobe_top(&unmap_kretprobe, 0);
418 } while (atomic_read(&unmap_cnt));
419 swap_unregister_kretprobe_bottom(&unmap_kretprobe);
427 ******************************************************************************
429 ******************************************************************************
431 static int ret_handler_mmap(struct kretprobe_instance *ri,
432 struct pt_regs *regs)
434 struct sspt_proc *proc;
435 struct task_struct *task;
436 unsigned long start_addr;
437 struct vm_area_struct *vma;
439 task = current->group_leader;
440 if (is_kthread(task))
443 start_addr = (unsigned long)get_regs_ret_val(regs);
444 if (IS_ERR_VALUE(start_addr))
447 proc = sspt_proc_get_by_task(task);
451 vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
452 if (vma && check_vma(vma))
458 static struct kretprobe mmap_kretprobe = {
459 .handler = ret_handler_mmap
462 static int register_mmap(void)
466 ret = swap_register_kretprobe(&mmap_kretprobe);
468 printk("swap_register_kretprobe(do_mmap_pgoff) ret=%d!\n", ret);
473 static void unregister_mmap(void)
475 swap_unregister_kretprobe(&mmap_kretprobe);
483 ******************************************************************************
485 ******************************************************************************
488 struct task_struct *task;
491 static int entry_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
493 struct comm_data *data = (struct comm_data *)ri->data;
495 data->task = (struct task_struct *)swap_get_karg(regs, 0);
500 static int ret_handler_comm(struct kretprobe_instance *ri, struct pt_regs *regs)
502 struct task_struct *task;
504 if (is_kthread(current))
507 task = ((struct comm_data *)ri->data)->task;
509 check_task_and_install(task);
514 static struct kretprobe comm_kretprobe = {
515 .entry_handler = entry_handler_comm,
516 .handler = ret_handler_comm,
517 .data_size = sizeof(struct comm_data)
520 static int register_comm(void)
524 ret = swap_register_kretprobe(&comm_kretprobe);
526 printk("swap_register_kretprobe(set_task_comm) ret=%d!\n",
532 static void unregister_comm(void)
534 swap_unregister_kretprobe(&comm_kretprobe);
542 * @brief Registration of helper
546 int register_helper(void)
550 atomic_set(&stop_flag, 0);
553 * install probe on 'set_task_comm' to detect when field comm struct
554 * task_struct changes
556 ret = register_comm();
560 /* install probe on 'do_munmap' to detect when for remove US probes */
561 ret = register_unmap();
565 /* install probe on 'mm_release' to detect when for remove US probes */
570 /* install probe on 'copy_process' to disarm children process */
575 /* install probe on 'do_mmap_pgoff' to detect when mapping file */
576 ret = register_mmap();
581 * install probe on 'handle_mm_fault' to detect when US pages will be
589 /* install probe to detect already running process */
590 ret = register_ctx_task();
593 #endif /* CONFIG_ARM */
600 #endif /* CONFIG_ARM */
621 * @brief Unegistration of helper bottom
625 void unregister_helper_top(void)
628 unregister_ctx_task();
629 #endif /* CONFIG_ARM */
631 atomic_set(&stop_flag, 1);
635 * @brief Unegistration of helper top
639 void unregister_helper_bottom(void)
649 * @brief Initialization of helper
653 int init_helper(void)
657 addr = swap_ksyms("do_page_fault");
659 printk("Cannot find address for handle_mm_fault function!\n");
662 mf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
664 addr = swap_ksyms_substr("copy_process");
666 printk("Cannot find address for copy_process function!\n");
669 cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
671 addr = swap_ksyms("mm_release");
673 printk("Cannot find address for mm_release function!\n");
676 mr_kprobe.addr = (kprobe_opcode_t *)addr;
678 addr = swap_ksyms("do_munmap");
680 printk("Cannot find address for do_munmap function!\n");
683 unmap_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
685 addr = swap_ksyms("do_mmap_pgoff");
687 printk("Cannot find address for do_mmap_pgoff function!\n");
690 mmap_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
692 addr = swap_ksyms("set_task_comm");
694 printk("Cannot find address for set_task_comm function!\n");
697 comm_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
700 addr = swap_ksyms("ret_to_user");
702 printk("Cannot find address for ret_to_user function!\n");
705 ctx_task_kprobe.addr = (kprobe_opcode_t *)addr;
706 #endif /* CONFIG_ARM */
712 * @brief Uninitialization of helper
716 void uninit_helper(void)