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_mf(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 = regs->EREG(cx);
53 #elif defined(CONFIG_ARM)
54 data->addr = regs->ARM_r2;
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_mf(struct kretprobe_instance *ri, struct pt_regs *regs)
65 struct task_struct *task;
66 unsigned long page_addr;
68 task = current->group_leader;
72 /* TODO: check return value */
73 page_addr = ((struct pf_data *)ri->data)->addr & PAGE_MASK;
74 call_page_fault(task, page_addr);
79 static struct kretprobe mf_kretprobe = {
80 .entry_handler = entry_handler_mf,
81 .handler = ret_handler_mf,
82 .data_size = sizeof(struct pf_data)
88 ******************************************************************************
90 ******************************************************************************
93 static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
95 sspt_proc_uninstall(proc, child_task, US_DISARM);
96 dbi_disarm_urp_inst_for_task(current, child_task);
99 static void rm_uprobes_child(struct task_struct *task)
101 struct sspt_proc *proc = sspt_proc_get_by_task(current);
103 recover_child(task, proc);
107 /* Delete uprobs in children at fork */
108 static int ret_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
110 struct task_struct *task = (struct task_struct *)regs_return_value(regs);
112 if(!task || IS_ERR(task))
115 if(task->mm != current->mm) { /* check flags CLONE_VM */
116 rm_uprobes_child(task);
119 * Ignoring page_addr, because it is
120 * first calling call_page_fault()
122 call_page_fault(task, 0xbadc0de);
128 static struct kretprobe cp_kretprobe = {
129 .handler = ret_handler_cp,
135 ******************************************************************************
137 ******************************************************************************
140 /* Detects when target process removes IPs. */
141 static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
143 struct sspt_proc *proc = NULL;
144 struct task_struct *task;
146 #if defined(CONFIG_X86)
147 task = (struct task_struct *)regs->EREG(ax);
148 #elif defined(CONFIG_ARM)
149 task = (struct task_struct *)regs->ARM_r0;
151 #error this architecture is not supported
154 if (is_kthread(task))
157 if (task->tgid != task->pid) {
161 call_mm_release(task);
166 static struct kprobe mr_kprobe = {
167 .pre_handler = mr_pre_handler
173 ******************************************************************************
175 ******************************************************************************
178 static int remove_unmap_probes(struct task_struct *task, struct sspt_proc *proc, unsigned long start, size_t len)
180 struct mm_struct *mm = task->mm;
181 struct vm_area_struct *vma;
183 /* FIXME: not implemented */
186 if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
190 if ((len = PAGE_ALIGN(len)) == 0) {
194 vma = find_vma(mm, start);
195 if (vma && check_vma(vma)) {
196 struct sspt_file *file;
197 unsigned long end = start + len;
198 struct dentry *dentry = vma->vm_file->f_dentry;
200 file = sspt_proc_find_file(proc, dentry);
202 if (vma->vm_start == start || vma->vm_end == end) {
203 sspt_file_uninstall(file, task, US_UNREGS_PROBE);
206 unsigned long page_addr;
207 struct sspt_page *page;
209 for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
210 page = sspt_find_page_mapped(file, page_addr);
212 sspt_unregister_page(page, US_UNREGS_PROBE, task);
216 if (sspt_file_check_install_pages(file)) {
226 /* Detects when target removes IPs. */
227 static int unmap_pre_handler(struct kprobe *p, struct pt_regs *regs)
230 struct mm_struct *mm;
234 #if defined(CONFIG_X86)
235 mm = (struct mm_struct *)regs->EREG(ax);
236 start = regs->EREG(dx);
237 len = (size_t)regs->EREG(cx);
238 #elif defined(CONFIG_ARM)
239 mm = (struct mm_struct *)regs->ARM_r0;
240 start = regs->ARM_r1;
241 len = (size_t)regs->ARM_r2;
243 #error this architecture is not supported
246 struct sspt_proc *proc = NULL;
247 struct task_struct *task = current;
249 if (is_kthread(task))
252 proc = sspt_proc_get_by_task(task);
254 if (remove_unmap_probes(task, proc, start, len)) {
255 printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
263 static struct kprobe unmap_kprobe = {
264 .pre_handler = unmap_pre_handler
269 int register_helper(void)
273 /* install kprobe on 'do_munmap' to detect when for remove user space probes */
274 ret = dbi_register_kprobe(&unmap_kprobe);
276 printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
280 /* install kprobe on 'mm_release' to detect when for remove user space probes */
281 ret = dbi_register_kprobe(&mr_kprobe);
283 printk("dbi_register_kprobe(mm_release) result=%d!\n", ret);
284 goto unregister_unmap;
288 /* install kretprobe on 'copy_process' */
289 ret = dbi_register_kretprobe(&cp_kretprobe);
291 printk("dbi_register_kretprobe(copy_process) result=%d!\n", ret);
295 /* install kretprobe on 'handle_mm_fault' to detect when they will be loaded */
296 ret = dbi_register_kretprobe(&mf_kretprobe);
298 printk("dbi_register_kretprobe(do_page_fault) result=%d!\n", ret);
305 dbi_unregister_kretprobe(&cp_kretprobe);
308 dbi_unregister_kprobe(&mr_kprobe);
311 dbi_unregister_kprobe(&unmap_kprobe);
316 void unregister_helper(void)
318 /* uninstall kretprobe with 'handle_mm_fault' */
319 dbi_unregister_kretprobe(&mf_kretprobe);
321 /* uninstall kretprobe with 'copy_process' */
322 dbi_unregister_kretprobe(&cp_kretprobe);
324 /* uninstall kprobe with 'mm_release' */
325 dbi_unregister_kprobe(&mr_kprobe);
327 /* uninstall kprobe with 'do_munmap' */
328 dbi_unregister_kprobe(&unmap_kprobe);
331 int init_helper(void)
334 addr = swap_ksyms("handle_mm_fault");
336 printk("Cannot find address for handle_mm_fault function!\n");
339 mf_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
341 addr = swap_ksyms("copy_process");
343 printk("Cannot find address for copy_process function!\n");
346 cp_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
348 addr = swap_ksyms("mm_release");
350 printk("Cannot find address for mm_release function!\n");
353 mr_kprobe.addr = (kprobe_opcode_t *)addr;
355 addr = swap_ksyms("do_munmap");
357 printk("Cannot find address for do_munmap function!\n");
360 unmap_kprobe.addr = (kprobe_opcode_t *)addr;
365 void uninit_helper(void)