remove uprobes, when the task is removed (called jprobe on function 'mm_release')
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 22 Aug 2012 08:52:54 +0000 (12:52 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 29 Aug 2012 12:37:56 +0000 (16:37 +0400)
driver/probes_manager.c
driver/probes_manager.h
driver/storage.c
driver/us_proc_inst.c
driver/us_proc_inst.h

index d6b058c..8b8a212 100644 (file)
 
 unsigned long pf_addr;
 unsigned long cp_addr;
+unsigned long mr_addr;
 unsigned long exit_addr;
-unsigned long exec_addr;
 kernel_probe_t *pf_probe = NULL;
 kernel_probe_t *cp_probe = NULL;
+kernel_probe_t *mr_probe = NULL;
 kernel_probe_t *exit_probe = NULL;
-kernel_probe_t *exec_probe = NULL;
 unsigned int probes_flags = 0;
 
 int
@@ -63,21 +63,21 @@ probes_manager_init (void)
                return -EINVAL;
        }
 
-    cp_addr = lookup_name("copy_process");
-    if (cp_addr == 0) {
-        EPRINTF("Cannot find address for copy_process function!");
-        return -EINVAL;
-    }
+       cp_addr = lookup_name("copy_process");
+       if (cp_addr == 0) {
+               EPRINTF("Cannot find address for copy_process function!");
+               return -EINVAL;
+       }
 
-       exit_addr = lookup_name("do_exit");
-       if (exit_addr == 0) {
-               EPRINTF("Cannot find address for do_exit function!");
+       mr_addr = lookup_name("mm_release");
+       if (mr_addr == 0) {
+               EPRINTF("Cannot find address for mm_release function!");
                return -EINVAL;
        }
 
-       exec_addr = lookup_name("do_execve");
-       if (exec_addr == 0) {
-               EPRINTF("Cannot find address for do_execve function!");
+       exit_addr = lookup_name("do_exit");
+       if (exit_addr == 0) {
+               EPRINTF("Cannot find address for do_exit function!");
                return -EINVAL;
        }
 
@@ -95,9 +95,9 @@ static int
 register_kernel_jprobe (kernel_probe_t * probe)
 {
        int result;
-       if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
+       if((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
            ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
-           ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD)) ||
+           ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
            ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)))
        {
                return 0;       // probe is already registered
@@ -114,10 +114,10 @@ register_kernel_jprobe (kernel_probe_t * probe)
 static int
 unregister_kernel_jprobe (kernel_probe_t * probe)
 {
-       if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
-        ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
-               ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ||
-               ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
+       if((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
+           ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
+           ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
+           ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
                return 0;       // probe is necessary for user space instrumentation
        }
        dbi_unregister_jprobe (&probe->jprobe);
@@ -128,10 +128,11 @@ static int
 register_kernel_retprobe (kernel_probe_t * probe)
 {
        int result;
-       if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
-        ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
-               ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ||
-               ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
+       if( ((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
+           ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
+           ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
+           ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
+
                return 0;       // probe is already registered
        }
 
@@ -147,10 +148,10 @@ register_kernel_retprobe (kernel_probe_t * probe)
 static int
 unregister_kernel_retprobe (kernel_probe_t * probe)
 {
-       if (((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
-        ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
-               ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ||
-               ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
+       if((probe == pf_probe) && (us_proc_probes & US_PROC_PF_INSTLD)) ||
+           ((probe == cp_probe) && (us_proc_probes & US_PROC_CP_INSTLD)) ||
+           ((probe == mr_probe) && (us_proc_probes & US_PROC_MR_INSTLD)) ||
+           ((probe == exit_probe) && (us_proc_probes & US_PROC_EXIT_INSTLD)) ) {
                return 0;       // probe is necessary for user space instrumentation
        }
        dbi_unregister_kretprobe (&probe->retprobe);
@@ -231,14 +232,14 @@ add_probe (unsigned long addr)
                }
                pprobe = &pf_probe;
        }
-    else if (addr == cp_addr) {
-        probes_flags |= PROBE_FLAG_CP_INSTLD;
-        if (us_proc_probes & US_PROC_CP_INSTLD)
-        {
-            return 0;
-        }
-        pprobe = &cp_probe;
-    }
+       else if (addr == cp_addr) {
+               probes_flags |= PROBE_FLAG_CP_INSTLD;
+               if (us_proc_probes & US_PROC_CP_INSTLD)
+               {
+                       return 0;
+               }
+               pprobe = &cp_probe;
+       }
        else if (addr == exit_addr) {
                probes_flags |= PROBE_FLAG_EXIT_INSTLD;
                if (us_proc_probes & US_PROC_EXIT_INSTLD)
@@ -247,24 +248,24 @@ add_probe (unsigned long addr)
                }
                pprobe = &exit_probe;
        }
-       else if (addr == exec_addr) {
-               probes_flags |= PROBE_FLAG_EXEC_INSTLD;
-               if (us_proc_probes & US_PROC_EXEC_INSTLD) {
+       else if (addr == mr_addr) {
+               probes_flags |= PROBE_FLAG_MR_INSTLD;
+               if (us_proc_probes & US_PROC_MR_INSTLD) {
                        return 0;
                }
-               pprobe = &exec_probe;
+               pprobe = &mr_probe;
        }
 
        result = add_probe_to_list (addr, pprobe);
        if (result) {
                if (addr == pf_addr)
                        probes_flags &= ~PROBE_FLAG_PF_INSTLD;
-        else if (addr == cp_addr)
-            probes_flags &= ~PROBE_FLAG_CP_INSTLD;
+               else if (addr == cp_addr)
+                       probes_flags &= ~PROBE_FLAG_CP_INSTLD;
                else if (addr == exit_addr)
                        probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
-               else if (addr == exec_addr)
-                       probes_flags &= ~PROBE_FLAG_EXEC_INSTLD;
+               else if (addr == mr_addr)
+                       probes_flags &= ~PROBE_FLAG_MR_INSTLD;
        }
        return result;
 }
@@ -278,15 +279,15 @@ int reset_probes()
                if (p->addr == pf_addr) {
                        probes_flags &= ~PROBE_FLAG_PF_INSTLD;
                        pf_probe = NULL;
-        } else if (p->addr == cp_addr) {
-            probes_flags &= ~PROBE_FLAG_CP_INSTLD;
-            cp_probe = NULL;
+               } else if (p->addr == cp_addr) {
+                       probes_flags &= ~PROBE_FLAG_CP_INSTLD;
+                       cp_probe = NULL;
                } else if (p->addr == exit_addr) {
                        probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
                        exit_probe = NULL;
-               } else if (p->addr == exec_addr) {
-                       probes_flags &= ~PROBE_FLAG_EXEC_INSTLD;
-                       exec_probe = NULL;
+               } else if (p->addr == mr_addr) {
+                       probes_flags &= ~PROBE_FLAG_MR_INSTLD;
+                       mr_probe = NULL;
                }
                hlist_del(node);
                kfree(p);
@@ -296,15 +297,15 @@ int reset_probes()
                if (p->addr == pf_addr) {
                        probes_flags &= ~PROBE_FLAG_PF_INSTLD;
                        pf_probe = NULL;
-        } else if (p->addr == cp_addr) {
-            probes_flags &= ~PROBE_FLAG_CP_INSTLD;
-            cp_probe = NULL;
+               } else if (p->addr == cp_addr) {
+                       probes_flags &= ~PROBE_FLAG_CP_INSTLD;
+                       cp_probe = NULL;
                } else if (p->addr == exit_addr) {
                        probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
                        exit_probe = NULL;
-               } else if (p->addr == exec_addr) {
-                       probes_flags &= ~PROBE_FLAG_EXEC_INSTLD;
-                       exec_probe = NULL;
+               } else if (p->addr == mr_addr) {
+                       probes_flags &= ~PROBE_FLAG_MR_INSTLD;
+                       mr_probe = NULL;
                }
                hlist_del(node);
                kfree(p);
@@ -332,14 +333,21 @@ remove_probe (unsigned long addr)
                }
                pf_probe = NULL;
        }
-    else if (addr == cp_addr) {
-        probes_flags &= ~PROBE_FLAG_CP_INSTLD;
-        if (us_proc_probes & US_PROC_CP_INSTLD)
-        {
-            return 0;
-        }
-        cp_probe = NULL;
-    }
+       else if (addr == cp_addr) {
+               probes_flags &= ~PROBE_FLAG_CP_INSTLD;
+               if (us_proc_probes & US_PROC_CP_INSTLD)
+               {
+                       return 0;
+               }
+               cp_probe = NULL;
+       }
+       else if (addr == mr_addr) {
+               probes_flags &= ~PROBE_FLAG_MR_INSTLD;
+               if (us_proc_probes & US_PROC_MR_INSTLD) {
+                       return 0;
+               }
+               mr_probe = NULL;
+       }
        else if (addr == exit_addr) {
                probes_flags &= ~PROBE_FLAG_EXIT_INSTLD;
                if (us_proc_probes & US_PROC_EXIT_INSTLD)
@@ -348,13 +356,6 @@ remove_probe (unsigned long addr)
                }
                exit_probe = NULL;
        }
-       else if (addr == exec_addr) {
-               probes_flags &= ~PROBE_FLAG_EXEC_INSTLD;
-               if (us_proc_probes & US_PROC_EXEC_INSTLD) {
-                       return 0;
-               }
-               exec_probe = NULL;
-       }
 
        result = remove_probe_from_list (addr);
 
@@ -396,28 +397,23 @@ def_jprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long
                        skip = 1;
 #endif /* CONFIG_X86 */
        }
-    else if (cp_probe == probe)
-    {
-        if (!(probes_flags & PROBE_FLAG_CP_INSTLD))
-            skip = 1;
-    }
-       else if (exit_probe == probe)
+       else if (cp_probe == probe)
        {
-               if (us_proc_probes & US_PROC_EXIT_INSTLD)
-                       do_exit_probe_pre_code ();
-               if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
+               if (!(probes_flags & PROBE_FLAG_CP_INSTLD))
                        skip = 1;
        }
-       else if (exec_probe == probe)
+       else if (mr_probe == probe)
+       {
+               if (us_proc_probes & US_PROC_MR_INSTLD)
+                       mm_release_probe_pre_code();
+               if (!(probes_flags & PROBE_FLAG_MR_INSTLD))
+                       skip = 1;
+       }
+       else if (exit_probe == probe)
        {
-               if (us_proc_probes & US_PROC_EXEC_INSTLD)
-                       /*
-                        * FIXME: This is not a good choice to call do_exit_probe_pre_code()
-                        * here.  The function should have more common name explaining that
-                        * we deinstall all the user space instrumentation from this task.
-                        */
-                       do_exit_probe_pre_code ();
-               if (!(probes_flags & PROBE_FLAG_EXEC_INSTLD))
+               if (us_proc_probes & US_PROC_EXIT_INSTLD)
+                       do_exit_probe_pre_code();
+               if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
                        skip = 1;
        }
 
@@ -447,6 +443,11 @@ def_retprobe_event_handler (struct kretprobe_instance *pi, struct pt_regs *regs,
                if (!(probes_flags & PROBE_FLAG_CP_INSTLD))
                        skip = 1;
        }
+       else if (mr_probe == probe)
+       {
+               if (!(probes_flags & PROBE_FLAG_MR_INSTLD))
+                       skip = 1;
+       }
        else if (exit_probe == probe)
        {
                if (!(probes_flags & PROBE_FLAG_EXIT_INSTLD))
index 473150f..9ebe1c1 100644 (file)
@@ -54,22 +54,22 @@ int install_kern_otg_probe(unsigned long addr,
 
 extern unsigned long pf_addr;
 extern unsigned long cp_addr;
+extern unsigned long mr_addr;
 extern unsigned long exit_addr;
-extern unsigned long exec_addr;
 extern kernel_probe_t *pf_probe;
 extern kernel_probe_t *cp_probe;
+extern kernel_probe_t *mr_probe;
 extern kernel_probe_t *exit_probe;
-extern kernel_probe_t *exec_probe;
 extern unsigned int probes_flags;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
 extern spinlock_t ec_probe_spinlock;
 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
 
 enum {
-    PROBE_FLAG_PF_INSTLD   = (1 << 0),
-    PROBE_FLAG_CP_INSTLD   = (1 << 1),
-    PROBE_FLAG_EXIT_INSTLD = (1 << 2),
-    PROBE_FLAG_EXEC_INSTLD = (1 << 3)
+       PROBE_FLAG_PF_INSTLD   = (1 << 0),
+       PROBE_FLAG_CP_INSTLD   = (1 << 1),
+       PROBE_FLAG_MR_INSTLD   = (1 << 2),
+       PROBE_FLAG_EXIT_INSTLD = (1 << 3)
 };
 
 #endif // !defined(__PROBES_MANAGER_H__)
index db7d6ef..117acac 100644 (file)
@@ -1596,9 +1596,9 @@ void pack_event_info (probe_id_t probe_id, record_type_t record_type, const char
                va_start(args, fmt);
                addr = get_probe_func_addr(fmt, args);
                va_end(args);
-               if (((addr == pf_addr) && !(probes_flags & PROBE_FLAG_PF_INSTLD)) ||
-                       ((addr == exit_addr) && !(probes_flags & PROBE_FLAG_EXIT_INSTLD)) ||
-                       ((addr == exec_addr) && !(probes_flags & PROBE_FLAG_EXEC_INSTLD))) {
+               if((addr == pf_addr) && !(probes_flags & PROBE_FLAG_PF_INSTLD)) ||
+                   ((addr == mr_addr) && !(probes_flags & PROBE_FLAG_MR_INSTLD)) ||
+                   ((addr == exit_addr) && !(probes_flags & PROBE_FLAG_EXIT_INSTLD)) ) {
                        return;
                }
        }
index 7d9a3e8..3cccc7b 100644 (file)
@@ -1039,28 +1039,28 @@ int deinst_usr_space_proc (void)
 
        //if user-space instrumentation is not set
        if (!us_proc_info.path)
-           return 0;
+               return 0;
 
        iRet = uninstall_kernel_probe (pf_addr, US_PROC_PF_INSTLD,
                        0, &pf_probe);
        if (iRet)
                EPRINTF ("uninstall_kernel_probe(do_page_fault) result=%d!", iRet);
 
-    iRet = uninstall_kernel_probe (cp_addr, US_PROC_CP_INSTLD,
-            0, &cp_probe);
-    if (iRet)
-        EPRINTF ("uninstall_kernel_probe(copy_process) result=%d!", iRet);
+       iRet = uninstall_kernel_probe (cp_addr, US_PROC_CP_INSTLD,
+                       0, &cp_probe);
+       if (iRet)
+               EPRINTF ("uninstall_kernel_probe(copy_process) result=%d!", iRet);
+
+        iRet = uninstall_kernel_probe (mr_addr, US_PROC_MR_INSTLD,
+                        0, &mr_probe);
+        if (iRet)
+                EPRINTF ("uninstall_kernel_probe(mm_release) result=%d!", iRet);
 
        iRet = uninstall_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD,
                        0, &exit_probe);
        if (iRet)
                EPRINTF ("uninstall_kernel_probe(do_exit) result=%d!", iRet);
 
-       iRet = uninstall_kernel_probe (exec_addr, US_PROC_EXEC_INSTLD,
-                       0, &exec_probe);
-       if (iRet)
-               EPRINTF ("uninstall_kernel_probe(do_execve) result=%d!", iRet);
-
        if (!strcmp(us_proc_info.path,"*"))
        {
                for_each_process (task)
@@ -1307,7 +1307,7 @@ int inst_usr_space_proc (void)
                EPRINTF ("install_kernel_probe(do_page_fault) result=%d!", ret);
                return ret;
        }
-       // enable 'do_exit' probe to detect when user proc exits in order to remove user space probes
+       // enable 'do_exit' probe to detect for remove task_struct
        ret = install_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD, 0, &exit_probe);
        if (ret != 0)
        {
@@ -1321,21 +1321,17 @@ int inst_usr_space_proc (void)
                EPRINTF ("instpall_kernel_probe(copy_process) result=%d!", ret);
                return ret;
        }
-       /*
-        * When do_execve occurs we need to unregister all the uprobes from
-        * this address space because VMAs may change.
-        */
-       ret = install_kernel_probe (exec_addr, US_PROC_EXEC_INSTLD, 0, &exec_probe);
+
+       // enable 'mm_release' probe to detect when for remove user space probes
+       ret = install_kernel_probe (mr_addr, US_PROC_MR_INSTLD, 0, &mr_probe);
        if (ret != 0)
        {
-               EPRINTF ("install_kernel_probe(do_execve) result=%d!", ret);
+               EPRINTF ("install_kernel_probe(mm_release) result=%d!", ret);
                return ret;
        }
        return 0;
 }
 
-char expath[512];
-
 void do_page_fault_ret_pre_code (void)
 {
        struct mm_struct *mm;
@@ -1440,8 +1436,15 @@ void do_page_fault_ret_pre_code (void)
 
 EXPORT_SYMBOL_GPL(do_page_fault_ret_pre_code);
 
+
 void do_exit_probe_pre_code (void)
 {
+       // TODO: remove task
+}
+EXPORT_SYMBOL_GPL(do_exit_probe_pre_code);
+
+void mm_release_probe_pre_code(void)
+{
        int iRet, del = 0;
        struct task_struct *task;
        inst_us_proc_t *task_inst_info = NULL;
@@ -1491,38 +1494,44 @@ void do_exit_probe_pre_code (void)
                }
        }
 }
-EXPORT_SYMBOL_GPL(do_exit_probe_pre_code);
+EXPORT_SYMBOL_GPL(mm_release_probe_pre_code);
 
 
 static void recover_child(struct task_struct *child_task, inst_us_proc_t *parent_iup)
 {
-    int i, k;
-    for (i = 0; i < parent_iup->libs_count; ++i)
-    {
-        for (k = 0; k < parent_iup->p_libs[i].ips_count; ++k)
-            if (parent_iup->p_libs[i].p_ips[k].installed)
-                arch_disarm_uprobe (&parent_iup->p_libs[i].p_ips[k].jprobe.kp, child_task);
-
-        for (k = 0; k < parent_iup->p_libs[i].vtps_count; ++k)
-            if (parent_iup->p_libs[i].p_vtps[k].installed)
-                arch_disarm_uprobe (&parent_iup->p_libs[i].p_vtps[k].jprobe.kp, child_task);
-    }
+       int i, k;
+       for(i = 0; i < parent_iup->libs_count; ++i)
+       {
+               for(k = 0; k < parent_iup->p_libs[i].ips_count; ++k)
+                       if(parent_iup->p_libs[i].p_ips[k].installed)
+                               arch_disarm_uprobe(&parent_iup->p_libs[i].p_ips[k].jprobe.kp, child_task);
+
+               for(k = 0; k < parent_iup->p_libs[i].vtps_count; ++k)
+                       if(parent_iup->p_libs[i].p_vtps[k].installed)
+                               arch_disarm_uprobe(&parent_iup->p_libs[i].p_vtps[k].jprobe.kp, child_task);
+       }
 }
 
-static void rm_uprobs_child(struct task_struct *new_task)
+static void rm_uprobes_child(struct task_struct *new_task)
 {
-    if(us_proc_info.path && (us_proc_info.tgid == current->tgid)) {
-        recover_child(new_task, &us_proc_info);
-    }
+       if(!strcmp(us_proc_info.path, "*")) {
+               inst_us_proc_t *task_inst_info = get_task_inst_node(current);
+               if(task_inst_info)
+                       recover_child(new_task, task_inst_info);
+       } else {
+               if(us_proc_info.tgid == current->tgid) {
+                       recover_child(new_task, &us_proc_info);
+               }
+       }
 }
 
 void copy_process_ret_pre_code(struct task_struct *p)
 {
-    if(!p || IS_ERR(p))
-        return;
+       if(!p || IS_ERR(p))
+               return;
 
-    if(p->mm != current->mm)    // check flags CLONE_VM
-        rm_uprobs_child(p);
+       if(p->mm != current->mm)    // check flags CLONE_VM
+               rm_uprobes_child(p);
 }
 
 
index b46e40a..71e9130 100644 (file)
@@ -31,9 +31,12 @@ extern int deinst_usr_space_proc (void);
 extern void do_page_fault_ret_pre_code (void);
 extern void  otg_probe_list_clean(char*);
 
-/* Detects when target process exits and removes IPs. */
+/* Detects when target process exits. */
 extern void do_exit_probe_pre_code (void);
 
+/* Detects when target process removes IPs. */
+extern void mm_release_probe_pre_code(void);
+
 /* Delete uprobs in children at fork */
 extern void copy_process_ret_pre_code(struct task_struct *p);
 
@@ -41,10 +44,10 @@ extern int us_proc_probes;
 extern pid_t gl_nNotifyTgid;
 
 enum {
-    US_PROC_PF_INSTLD   = (1 << 0),
-    US_PROC_CP_INSTLD   = (1 << 1),
-    US_PROC_EXIT_INSTLD = (1 << 2),
-    US_PROC_EXEC_INSTLD = (1 << 3)
+       US_PROC_PF_INSTLD   = (1 << 0),
+       US_PROC_CP_INSTLD   = (1 << 1),
+       US_PROC_MR_INSTLD   = (1 << 2),
+       US_PROC_EXIT_INSTLD = (1 << 3)
 };
 
 /* forward declarations */