summaryrefslogtreecommitdiff
path: root/us_manager/helper.c
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2013-10-16 21:30:49 +0400
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2013-10-17 13:19:04 +0400
commitdefc0b17009d0eccd1810fa855942717a90e43f5 (patch)
tree31b1f8719ca52f4864c8f746e16c3b8d420e9431 /us_manager/helper.c
parentb03569b52ef8a82545892f8625f211b347ee527c (diff)
downloadswap-modules-defc0b17009d0eccd1810fa855942717a90e43f5.tar.gz
swap-modules-defc0b17009d0eccd1810fa855942717a90e43f5.tar.bz2
swap-modules-defc0b17009d0eccd1810fa855942717a90e43f5.zip
[FIX] uninstall probes on do_munmap() call
Change-Id: I370fb69f8d41bea3d007c90dfa9b671b3a99ec81 Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
Diffstat (limited to 'us_manager/helper.c')
-rw-r--r--us_manager/helper.c121
1 files changed, 53 insertions, 68 deletions
diff --git a/us_manager/helper.c b/us_manager/helper.c
index 0c4307b7..d829242c 100644
--- a/us_manager/helper.c
+++ b/us_manager/helper.c
@@ -26,6 +26,7 @@
#include <dbi_kprobes.h>
#include <dbi_kprobes_deps.h>
#include <ksyms.h>
+#include <writer/kernel_operations.h>
#include "us_slot_manager.h"
#include "sspt/sspt.h"
#include "helper.h"
@@ -174,94 +175,78 @@ static struct kprobe mr_kprobe = {
* do_munmap() *
******************************************************************************
*/
+struct unmap_data {
+ unsigned long start;
+ size_t len;
+};
-static int remove_unmap_probes(struct task_struct *task, struct sspt_proc *proc, unsigned long start, size_t len)
+static void remove_unmap_probes(struct sspt_proc *proc, struct unmap_data *umd)
{
- struct mm_struct *mm = task->mm;
- struct vm_area_struct *vma;
+ struct task_struct *task = proc->task;
+ unsigned long start = umd->start;
+ size_t len = umd->len;
+ LIST_HEAD(head);
- /* FIXME: not implemented */
- return 0;
+ if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
+ struct sspt_file *file, *n;
+ unsigned long end = start + len;
- if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
- return -EINVAL;
- }
+ list_for_each_entry_safe(file, n, &head, list) {
+ if (file->vm_start >= end)
+ continue;
- if ((len = PAGE_ALIGN(len)) == 0) {
- return -EINVAL;
- }
-
- vma = find_vma(mm, start);
- if (vma && check_vma(vma)) {
- struct sspt_file *file;
- unsigned long end = start + len;
- struct dentry *dentry = vma->vm_file->f_dentry;
-
- file = sspt_proc_find_file(proc, dentry);
- if (file) {
- if (vma->vm_start == start || vma->vm_end == end) {
- sspt_file_uninstall(file, task, US_UNREGS_PROBE);
- file->loaded = 0;
- } else {
- unsigned long page_addr;
- struct sspt_page *page;
-
- for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
- page = sspt_find_page_mapped(file, page_addr);
- if (page) {
- sspt_unregister_page(page, US_UNREGS_PROBE, task);
- }
- }
-
- if (sspt_file_check_install_pages(file)) {
- file->loaded = 0;
- }
+ if (file->vm_start >= start)
+ sspt_file_uninstall(file, task, US_UNINSTALL);
+ else {
+ /* TODO: uninstall pages: start..file->vm_end */
}
}
- }
- return 0;
+ sspt_proc_insert_files(proc, &head);
+ }
}
-/* Detects when target removes IPs. */
-static int unmap_pre_handler(struct kprobe *p, struct pt_regs *regs)
+
+static int entry_handler_unmap(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
{
- /* for ARM */
- struct mm_struct *mm;
- unsigned long start;
- size_t len;
+ struct unmap_data *data = (struct unmap_data *)ri->data;
#if defined(CONFIG_X86)
- mm = (struct mm_struct *)regs->EREG(ax);
- start = regs->EREG(dx);
- len = (size_t)regs->EREG(cx);
+ data->start = regs->dx;
+ data->len = (size_t)regs->cx;
#elif defined(CONFIG_ARM)
- mm = (struct mm_struct *)regs->ARM_r0;
- start = regs->ARM_r1;
- len = (size_t)regs->ARM_r2;
+ data->start = regs->ARM_r1;
+ data->len = (size_t)regs->ARM_r2;
#else
#error this architecture is not supported
#endif
- struct sspt_proc *proc = NULL;
- struct task_struct *task = current;
+ return 0;
+}
- if (is_kthread(task))
- goto out;
+static int ret_handler_unmap(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ struct task_struct *task;
+ struct sspt_proc *proc;
+
+ task = current->group_leader;
+ if (is_kthread(task) ||
+ get_regs_ret_val(regs))
+ return 0;
proc = sspt_proc_get_by_task(task);
- if (proc) {
- if (remove_unmap_probes(task, proc, start, len)) {
- printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
- }
- }
+ if (proc)
+ remove_unmap_probes(proc, (struct unmap_data *)ri->data);
-out:
return 0;
}
-static struct kprobe unmap_kprobe = {
- .pre_handler = unmap_pre_handler
+static struct kretprobe unmap_kretprobe = {
+ .entry_handler = entry_handler_unmap,
+ .handler = ret_handler_unmap,
+ .data_size = sizeof(struct unmap_data)
};
@@ -271,7 +256,7 @@ int register_helper(void)
int ret = 0;
/* install kprobe on 'do_munmap' to detect when for remove user space probes */
- ret = dbi_register_kprobe(&unmap_kprobe);
+ ret = dbi_register_kretprobe(&unmap_kretprobe);
if (ret) {
printk("dbi_register_kprobe(do_munmap) result=%d!\n", ret);
return ret;
@@ -308,7 +293,7 @@ unregister_mr:
dbi_unregister_kprobe(&mr_kprobe);
unregister_unmap:
- dbi_unregister_kprobe(&unmap_kprobe);
+ dbi_unregister_kretprobe(&unmap_kretprobe);
return ret;
}
@@ -324,8 +309,8 @@ void unregister_helper(void)
/* uninstall kprobe with 'mm_release' */
dbi_unregister_kprobe(&mr_kprobe);
- /* uninstall kprobe with 'do_munmap' */
- dbi_unregister_kprobe(&unmap_kprobe);
+ /* uninstall kretprobe with 'do_munmap' */
+ dbi_unregister_kretprobe(&unmap_kretprobe);
}
int init_helper(void)
@@ -357,7 +342,7 @@ int init_helper(void)
printk("Cannot find address for do_munmap function!\n");
return -EINVAL;
}
- unmap_kprobe.addr = (kprobe_opcode_t *)addr;
+ unmap_kretprobe.kp.addr = (kprobe_opcode_t *)addr;
return 0;
}