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 <dbi_kprobes.h>
27 #include <dbi_kprobes_deps.h>
29 #include "us_slot_manager.h"
30 #include "sspt/sspt.h"
35 struct task_struct *check_task(struct task_struct *task);
38 ******************************************************************************
40 ******************************************************************************
47 static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
49 struct pf_data *data = (struct pf_data *)ri->data;
51 #if defined(CONFIG_X86)
52 data->addr = read_cr2();
53 #elif defined(CONFIG_ARM)
54 data->addr = regs->ARM_r0;
56 #error this architecture is not supported
62 /* Detects when IPs are really loaded into phy mem and installs probes. */
63 static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs)
65 struct task_struct *task;
66 unsigned long page_addr;
68 task = current->group_leader;
72 page_addr = ((struct pf_data *)ri->data)->addr & PAGE_MASK;
73 call_page_fault(task, page_addr);
78 static struct kretprobe pf_kretprobe = {
79 .entry_handler = entry_handler_pf,
80 .handler = ret_handler_pf,
81 .data_size = sizeof(struct pf_data)
87 ******************************************************************************
89 ******************************************************************************
92 static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
94 sspt_proc_uninstall(proc, child_task, US_DISARM);
95 dbi_disarm_urp_inst_for_task(current, child_task);
98 static void rm_uprobes_child(struct task_struct *task)
100 struct sspt_proc *proc = sspt_proc_get_by_task(current);
102 recover_child(task, proc);
106 /* Delete uprobs in children at fork */
107 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
109 struct task_struct *task = (struct task_struct *)regs_return_value(regs);
111 if(!task || IS_ERR(task))
114 if(task->mm != current->mm) { /* check flags CLONE_VM */
115 rm_uprobes_child(task);
118 * Ignoring page_addr, because it is
119 * first calling call_page_fault()
121 call_page_fault(task, 0xbadc0de);
127 static struct kretprobe cp_kretprobe = {
128 .handler = ret_handler_cp,
134 ******************************************************************************
136 ******************************************************************************
139 /* Detects when target process removes IPs. */
140 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
142 struct sspt_proc *proc = NULL;
143 struct task_struct *task;
145 #if defined(CONFIG_X86)
146 task = (struct task_struct *)regs->EREG(ax);
147 #elif defined(CONFIG_ARM)
148 task = (struct task_struct *)regs->ARM_r0;
150 #error this architecture is not supported
153 if (is_kthread(task))
156 if (task->tgid != task->pid) {
160 call_mm_release(task);
165 static struct kprobe mr_kprobe = {
166 .pre_handler = mr_pre_handler
172 ******************************************************************************
174 ******************************************************************************
177 static int remove_unmap_probes(struct task_struct *task, struct sspt_proc *proc, unsigned long start, size_t len)
179 struct mm_struct *mm = task->mm;
180 struct vm_area_struct *vma;
182 /* FIXME: not implemented */
185 if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
189 if ((len = PAGE_ALIGN(len)) == 0) {
193 vma = find_vma(mm, start);
194 if (vma && check_vma(vma)) {
195 struct sspt_file *file;
196 unsigned long end = start + len;
197 struct dentry *dentry = vma->vm_file->f_dentry;
199 file = sspt_proc_find_file(proc, dentry);
201 if (vma->vm_start == start || vma->vm_end == end) {
202 sspt_file_uninstall(file, task, US_UNREGS_PROBE);
205 unsigned long page_addr;
206 struct sspt_page *page;
208 for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
209 page = sspt_find_page_mapped(file, page_addr);
211 sspt_unregister_page(page, US_UNREGS_PROBE, task);
215 if (sspt_file_check_install_pages(file)) {
225 /* Detects when target removes IPs. */
226 static int unmap_pre_handler(struct kprobe *p, struct pt_regs *regs)
229 struct mm_struct *mm;
233 #if defined(CONFIG_X86)
234 mm = (struct mm_struct *)regs->EREG(ax);
235 start = regs->EREG(dx);
236 len = (size_t)regs->EREG(cx);
237 #elif defined(CONFIG_ARM)
238 mm = (struct mm_struct *)regs->ARM_r0;
239 start = regs->ARM_r1;
240 len = (size_t)regs->ARM_r2;
242 #error this architecture is not supported
245 struct sspt_proc *proc = NULL;
246 struct task_struct *task = current;
248 if (is_kthread(task))
251 proc = sspt_proc_get_by_task(task);
253 if (remove_unmap_probes(task, proc, start, len)) {
254 printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
262 static struct kprobe unmap_kprobe = {
263 .pre_handler = unmap_pre_handler
268 int register_helper(void)
272 /* install kprobe on 'do_munmap' to detect when for remove user space probes */
273 ret = dbi_register_kprobe(&unmap_kprobe);
275 printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
279 /* install kprobe on 'mm_release' to detect when for remove user space probes */
280 ret = dbi_register_kprobe(&mr_kprobe);
282 printk("dbi_register_kprobe(mm_release) result=%d!\n", ret);
283 goto unregister_unmap;
287 /* install kretprobe on 'copy_process' */
288 ret = dbi_register_kretprobe(&cp_kretprobe);
290 printk("dbi_register_kretprobe(copy_process) result=%d!\n", ret);
294 /* install kretprobe on 'do_page_fault' to detect when they will be loaded */
295 ret = dbi_register_kretprobe(&pf_kretprobe);
297 printk("dbi_register_kretprobe(do_page_fault) result=%d!\n", ret);
304 dbi_unregister_kretprobe(&cp_kretprobe);
307 dbi_unregister_kprobe(&mr_kprobe, NULL);
310 dbi_unregister_kprobe(&unmap_kprobe, NULL);
315 void unregister_helper(void)
317 /* uninstall kretprobe with 'do_page_fault' */
318 dbi_unregister_kretprobe(&pf_kretprobe);
320 /* uninstall kretprobe with 'copy_process' */
321 dbi_unregister_kretprobe(&cp_kretprobe);
323 /* uninstall kprobe with 'mm_release' */
324 dbi_unregister_kprobe(&mr_kprobe, NULL);
326 /* uninstall kprobe with 'do_munmap' */
327 dbi_unregister_kprobe(&unmap_kprobe, NULL);
330 int init_helper(void)
333 addr = swap_ksyms("do_page_fault");
335 printk("Cannot find address for page fault function!\n");
338 pf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
340 addr = swap_ksyms("copy_process");
342 printk("Cannot find address for copy_process function!\n");
345 cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
347 addr = swap_ksyms("mm_release");
349 printk("Cannot find address for mm_release function!\n");
352 mr_kprobe.addr = (kprobe_opcode_t *)addr;
354 addr = swap_ksyms("do_munmap");
356 printk("Cannot find address for do_munmap function!\n");
359 unmap_kprobe.addr = (kprobe_opcode_t *)addr;
364 void uninit_helper(void)