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/dbi_kprobes.h>
27 #include <kprobe/dbi_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_mf(struct kretprobe_instance *ri, struct pt_regs *regs)
54 struct pf_data *data = (struct pf_data *)ri->data;
57 data->addr = swap_get_karg(regs, 0);
58 #else /* CONFIG_ARM */
59 data->addr = swap_get_karg(regs, 2);
60 #endif /* CONFIG_ARM */
66 static unsigned long cb_pf(void *data)
68 unsigned long page_addr = *(unsigned long *)data;
70 call_page_fault(current, page_addr);
74 #endif /* CONFIG_ARM */
76 /* Detects when IPs are really loaded into phy mem and installs probes. */
77 static int ret_handler_mf(struct kretprobe_instance *ri, struct pt_regs *regs)
79 struct task_struct *task = current;
80 unsigned long page_addr;
85 /* TODO: check return value */
86 page_addr = ((struct pf_data *)ri->data)->addr & PAGE_MASK;
89 set_jump_cb((unsigned long)ri->ret_addr, regs, cb_pf,
90 &page_addr, sizeof(page_addr));
91 ri->ret_addr = (unsigned long *)get_jump_addr();
92 #else /* CONFIG_ARM */
93 call_page_fault(task, page_addr);
94 #endif /* CONFIG_ARM */
99 static struct kretprobe mf_kretprobe = {
100 .entry_handler = entry_handler_mf,
101 .handler = ret_handler_mf,
102 .data_size = sizeof(struct pf_data)
105 static int register_mf(void)
109 ret = dbi_register_kretprobe(&mf_kretprobe);
111 printk("dbi_register_kretprobe(handle_mm_fault) ret=%d!\n",
117 static void unregister_mf(void)
119 dbi_unregister_kretprobe(&mf_kretprobe);
128 ******************************************************************************
129 * workaround for already running *
130 ******************************************************************************
132 static int ctx_task_pre_handler(struct kprobe *p, struct pt_regs *regs)
134 struct sspt_proc *proc;
135 unsigned long page_addr;
136 struct task_struct *task = current;
138 if (is_kthread(task) || check_task_on_filters(task) == 0)
141 proc = sspt_proc_get_by_task(task);
142 if (proc && proc->first_install)
146 set_kjump_cb((unsigned long)p->ainsn.insn, regs, cb_pf,
147 &page_addr, sizeof(page_addr));
150 p->ss_addr[smp_processor_id()] = (unsigned long *)get_kjump_addr();
155 static struct kprobe ctx_task_kprobe = {
156 .pre_handler = ctx_task_pre_handler,
159 static int register_ctx_task(void)
163 ret = dbi_register_kprobe(&ctx_task_kprobe);
165 printk("dbi_register_kprobe(workaround) ret=%d!\n", ret);
170 static void unregister_ctx_task(void)
172 dbi_unregister_kprobe(&ctx_task_kprobe);
174 #endif /* CONFIG_ARM */
181 ******************************************************************************
183 ******************************************************************************
185 static atomic_t copy_process_cnt = ATOMIC_INIT(0);
187 static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
189 sspt_proc_uninstall(proc, child_task, US_DISARM);
190 dbi_disarm_urp_inst_for_task(current, child_task);
193 static void rm_uprobes_child(struct task_struct *task)
195 struct sspt_proc *proc;
197 sspt_proc_write_lock();
199 proc = sspt_proc_get_by_task(current);
201 recover_child(task, proc);
203 sspt_proc_write_unlock();
206 static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
208 atomic_inc(©_process_cnt);
210 if (atomic_read(&stop_flag))
211 call_mm_release(current);
216 /* Delete uprobs in children at fork */
217 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
219 struct task_struct *task = (struct task_struct *)regs_return_value(regs);
221 if(!task || IS_ERR(task))
224 if(task->mm != current->mm) { /* check flags CLONE_VM */
225 rm_uprobes_child(task);
228 atomic_dec(©_process_cnt);
233 static struct kretprobe cp_kretprobe = {
234 .entry_handler = entry_handler_cp,
235 .handler = ret_handler_cp,
238 static int register_cp(void)
242 ret = dbi_register_kretprobe(&cp_kretprobe);
244 printk("dbi_register_kretprobe(copy_process) ret=%d!\n", ret);
249 static void unregister_cp(void)
251 dbi_unregister_kretprobe_top(&cp_kretprobe, 0);
254 } while (atomic_read(©_process_cnt));
255 dbi_unregister_kretprobe_bottom(&cp_kretprobe);
263 ******************************************************************************
265 ******************************************************************************
268 /* Detects when target process removes IPs. */
269 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
271 struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
273 if (is_kthread(task))
276 if (task->tgid != task->pid) {
277 /* if the thread is killed we need to discard pending
278 * uretprobe instances which have not triggered yet */
279 dbi_discard_pending_uretprobes(task);
283 call_mm_release(task);
288 static struct kprobe mr_kprobe = {
289 .pre_handler = mr_pre_handler
292 static int register_mr(void)
296 ret = dbi_register_kprobe(&mr_kprobe);
298 printk("dbi_register_kprobe(mm_release) ret=%d!\n", ret);
303 static void unregister_mr(void)
305 dbi_unregister_kprobe(&mr_kprobe);
313 ******************************************************************************
315 ******************************************************************************
322 static atomic_t unmap_cnt = ATOMIC_INIT(0);
324 static void __remove_unmap_probes(struct sspt_proc *proc,
325 struct unmap_data *umd)
327 struct task_struct *task = proc->task;
328 unsigned long start = umd->start;
329 size_t len = PAGE_ALIGN(umd->len);
332 if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
333 struct sspt_file *file, *n;
334 unsigned long end = start + len;
336 list_for_each_entry_safe(file, n, &head, list) {
337 if (file->vm_start >= end)
340 if (file->vm_start >= start) {
341 sspt_file_uninstall(file, task, US_UNINSTALL);
343 /* TODO: uninstall pages: start..file->vm_end */
347 sspt_proc_insert_files(proc, &head);
349 proc_unmap_msg(start, end);
353 static void remove_unmap_probes(struct task_struct *task,
354 struct unmap_data *umd)
356 struct sspt_proc *proc;
358 sspt_proc_write_lock();
360 proc = sspt_proc_get_by_task(task);
362 __remove_unmap_probes(proc, umd);
364 sspt_proc_write_unlock();
367 static int entry_handler_unmap(struct kretprobe_instance *ri,
368 struct pt_regs *regs)
370 struct unmap_data *data = (struct unmap_data *)ri->data;
371 struct task_struct *task = current->group_leader;
373 atomic_inc(&unmap_cnt);
375 data->start = swap_get_karg(regs, 1);
376 data->len = (size_t)swap_get_karg(regs, 2);
378 if (!is_kthread(task) && atomic_read(&stop_flag))
379 remove_unmap_probes(task, data);
384 static int ret_handler_unmap(struct kretprobe_instance *ri,
385 struct pt_regs *regs)
387 struct task_struct *task;
389 task = current->group_leader;
390 if (is_kthread(task) ||
391 get_regs_ret_val(regs))
394 remove_unmap_probes(task, (struct unmap_data *)ri->data);
396 atomic_dec(&unmap_cnt);
401 static struct kretprobe unmap_kretprobe = {
402 .entry_handler = entry_handler_unmap,
403 .handler = ret_handler_unmap,
404 .data_size = sizeof(struct unmap_data)
407 static int register_unmap(void)
411 ret = dbi_register_kretprobe(&unmap_kretprobe);
413 printk("dbi_register_kprobe(do_munmap) ret=%d!\n", ret);
418 static void unregister_unmap(void)
420 dbi_unregister_kretprobe_top(&unmap_kretprobe, 0);
423 } while (atomic_read(&unmap_cnt));
424 dbi_unregister_kretprobe_bottom(&unmap_kretprobe);
432 ******************************************************************************
434 ******************************************************************************
436 static int ret_handler_mmap(struct kretprobe_instance *ri,
437 struct pt_regs *regs)
439 struct sspt_proc *proc;
440 struct task_struct *task;
441 unsigned long start_addr;
442 struct vm_area_struct *vma;
444 task = current->group_leader;
445 if (is_kthread(task))
448 start_addr = (unsigned long)get_regs_ret_val(regs);
449 if (IS_ERR_VALUE(start_addr))
452 proc = sspt_proc_get_by_task(task);
456 vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
457 if (vma && check_vma(vma))
463 static struct kretprobe mmap_kretprobe = {
464 .handler = ret_handler_mmap
467 static int register_mmap(void)
471 ret = dbi_register_kretprobe(&mmap_kretprobe);
473 printk("dbi_register_kretprobe(do_mmap_pgoff) ret=%d!\n", ret);
478 static void unregister_mmap(void)
480 dbi_unregister_kretprobe(&mmap_kretprobe);
487 int register_helper(void)
491 atomic_set(&stop_flag, 0);
493 /* install probe on 'do_munmap' to detect when for remove US probes */
494 ret = register_unmap();
498 /* install probe on 'mm_release' to detect when for remove US probes */
503 /* install probe on 'copy_process' to disarm children process */
508 /* install probe on 'do_mmap_pgoff' to detect when mapping file */
509 ret = register_mmap();
514 * install probe on 'handle_mm_fault' to detect when US pages will be
522 /* install probe to detect already running process */
523 ret = register_ctx_task();
526 #endif /* CONFIG_ARM */
533 #endif /* CONFIG_ARM */
550 void unregister_helper_top(void)
553 unregister_ctx_task();
554 #endif /* CONFIG_ARM */
556 atomic_set(&stop_flag, 1);
559 void unregister_helper_bottom(void)
567 int init_helper(void)
572 addr = swap_ksyms("do_page_fault");
573 #else /* CONFIG_ARM */
574 addr = swap_ksyms("handle_mm_fault");
575 #endif /* CONFIG_ARM */
578 printk("Cannot find address for handle_mm_fault function!\n");
581 mf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
583 addr = swap_ksyms_substr("copy_process");
585 printk("Cannot find address for copy_process function!\n");
588 cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
590 addr = swap_ksyms("mm_release");
592 printk("Cannot find address for mm_release function!\n");
595 mr_kprobe.addr = (kprobe_opcode_t *)addr;
597 addr = swap_ksyms("do_munmap");
599 printk("Cannot find address for do_munmap function!\n");
602 unmap_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
604 addr = swap_ksyms("do_mmap_pgoff");
606 printk("Cannot find address for do_mmap_pgoff function!\n");
609 mmap_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
612 addr = swap_ksyms("ret_to_user");
614 printk("Cannot find address for ret_to_user function!\n");
617 ctx_task_kprobe.addr = (kprobe_opcode_t *)addr;
618 #endif /* CONFIG_ARM */
623 void uninit_helper(void)