[REFACTOR] Preload: separate states on functions 87/54087/1
authorAlexander Aksenov <a.aksenov@samsung.com>
Mon, 23 Nov 2015 13:25:01 +0000 (16:25 +0300)
committerAlexander Aksenov <a.aksenov@samsung.com>
Fri, 11 Dec 2015 08:33:55 +0000 (11:33 +0300)
Change-Id: I57765d34f7f500a308ce9e310a38c37398ffef5c
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
preload/preload_module.c

index 253b422..7f36861 100644 (file)
@@ -532,16 +532,157 @@ static void preload_stop_cb(void)
        swap_unregister_kretprobe(&mmap_rp);
 }
 
+static unsigned long __not_loaded_entry(struct uretprobe_instance *ri,
+                                       struct pt_regs *regs,
+                                       struct process_data *pd)
+{
+       char __user *path = NULL;
+       unsigned long vaddr = 0;
+       unsigned long base;
+
+       /* if linker is still doing its work, we do nothing */
+       if (!__should_we_preload_handlers(current, regs))
+               return 0;
+
+       base = preload_pd_get_loader_base(pd);
+       if (base == 0)
+               return 0;   /* loader isn't mapped */
+
+       /* jump to loader code if ready */
+       vaddr = base + preload_debugfs_get_loader_offset();
+       if (vaddr) {
+               /* save original regs state */
+               __save_uregs(ri, regs);
+               print_regs("PROBE ORIG", regs, ri);
+
+               path = preload_pd_get_path(pd);
+
+               /* set dlopen args: filename, flags */
+               swap_set_arg(regs, 0, (unsigned long)path/*swap_get_stack_ptr(regs)*/);
+               swap_set_arg(regs, 1, 2 /* RTLD_NOW */);
+
+               /* do the jump to dlopen */
+               __prepare_ujump(ri, regs, vaddr);
+               /* set new state */
+               preload_pd_set_state(pd, LOADING);
+       }
+
+       return vaddr;
+}
+
+static unsigned long __loaded_entry(struct uretprobe_instance *ri,
+                                   struct pt_regs *regs,
+                                   struct process_data *pd)
+{
+       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
+       unsigned long offset = ip->desc->info.pl_i.handler;
+       unsigned long vaddr = 0;
+       unsigned long base;
+       unsigned long disable_addr;
+       unsigned long caddr;
+       struct vm_area_struct *cvma;
+       enum preload_call_type ct;
+
+       base = preload_pd_get_handlers_base(pd);
+       if (base == 0)
+               return 0;       /* handlers isn't mapped */
+
+       /* jump to preloaded handler */
+       vaddr = base + offset;
+       if (vaddr) {
+               caddr = get_regs_ret_func(regs);
+               cvma = __get_vma_by_addr(current, caddr);
+               ct = preload_control_call_type(ip, (void *)caddr);
+               disable_addr = __is_probe_non_block(ip) ? ip->orig_addr : 0;
+
+               /* jump only if caller is instumented and it is not a system lib -
+                * this leads to some errors */
+               if ((cvma != NULL) && ((cvma->vm_file != NULL) &&
+                    (cvma->vm_file->f_path.dentry != NULL) &&
+                    !preload_control_check_dentry_is_ignored(cvma->vm_file->f_path.dentry)) &&
+                   __check_flag_and_call_type(ip, ct) &&
+                   !__is_handlers_call(cvma)) {
+                       if (preload_threads_set_data(current, caddr, ct, disable_addr,
+                                                    __should_drop(ip, ct)) != 0)
+                               printk(PRELOAD_PREFIX "Error! Failed to set caller 0x%lx"
+                                      " for %d/%d\n", caddr, current->tgid, current->pid);
+                       /* args are not changed */
+                       __prepare_ujump(ri, regs, vaddr);
+                       if (disable_addr == 0)
+                               set_preload_flags(current, HANDLER_RUNNING);
+               }
+       }
+
+       return vaddr;
+}
+
+static void __loading_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                         struct process_data *pd)
+{
+       struct us_priv *priv = (struct us_priv *)ri->data;
+       unsigned long vaddr = 0;
+
+       /* check if preloading has been completed */
+       vaddr = preload_pd_get_loader_base(pd) + preload_debugfs_get_loader_offset();
+       if (vaddr && (priv->origin == vaddr)) {
+               preload_pd_set_handle(pd, (void __user *)regs_return_value(regs));
+
+               /* restore original regs state */
+               __restore_uregs(ri, regs);
+               print_regs("PROBE REST", regs, ri);
+               /* check if preloading done */
+
+               if (preload_pd_get_handle(pd)) {
+                       preload_pd_set_state(pd, LOADED);
+               } else {
+                       preload_pd_dec_attempts(pd);
+                       preload_pd_set_state(pd, FAILED);
+               }
+       }
+}
+
+static void __loaded_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                        struct process_data *pd)
+{
+       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
+       struct us_priv *priv = (struct us_priv *)ri->data;
+       unsigned long flags = get_preload_flags(current);
+       unsigned long offset = ip->desc->info.pl_i.handler;
+       unsigned long vaddr = 0;
+
+       if ((flags & HANDLER_RUNNING) ||
+           preload_threads_check_disabled_probe(current, ip->orig_addr)) {
+               bool non_blk_probe = __is_probe_non_block(ip);
+
+               /* drop the flag if the handler has completed */
+               vaddr = preload_pd_get_handlers_base(pd) + offset;
+               if (vaddr && (priv->origin == vaddr)) {
+                       if (preload_threads_put_data(current) != 0)
+                               printk(PRELOAD_PREFIX "Error! Failed to put caller slot"
+                                      " for %d/%d\n", current->tgid, current->pid);
+                       if (!non_blk_probe) {
+                               flags &= ~HANDLER_RUNNING;
+                               set_preload_flags(current, flags);
+                       }
+               }
+       }
+}
+
+static void __failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                        struct process_data *pd)
+{
+       if (preload_pd_get_attempts(pd)) {
+               preload_pd_set_state(pd, NOT_LOADED);
+       }
+}
+
 static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
        struct process_data *pd = __get_process_data(ri->rp);
        struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
        struct us_priv *priv = (struct us_priv *)ri->data;
        unsigned long flags = get_preload_flags(current);
-       unsigned long offset = ip->desc->info.pl_i.handler;
        unsigned long vaddr = 0;
-       unsigned long base;
-       char __user *path = NULL;
 
        if ((flags & HANDLER_RUNNING) ||
            preload_threads_check_disabled_probe(current, ip->orig_addr))
@@ -549,74 +690,13 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
 
        switch (preload_pd_get_state(pd)) {
        case NOT_LOADED:
-               /* if linker is still doing its work, we do nothing */
-               if (!__should_we_preload_handlers(current, regs))
-                       goto out_set_origin;
-
-               base = preload_pd_get_loader_base(pd);
-               if (base == 0)
-                       break;  /* loader isn't mapped */
-
-               /* jump to loader code if ready */
-               vaddr = base + preload_debugfs_get_loader_offset();
-               if (vaddr) {
-                       /* save original regs state */
-                       __save_uregs(ri, regs);
-                       print_regs("ORIG", regs, ri);
-
-                       path = preload_pd_get_path(pd);
-
-                       /* set dlopen args: filename, flags */
-                       swap_set_arg(regs, 0, (unsigned long)path/*swap_get_stack_ptr(regs)*/);
-                       swap_set_arg(regs, 1, 2 /* RTLD_NOW */);
-
-                       /* do the jump to dlopen */
-                       __prepare_ujump(ri, regs, vaddr);
-                       /* set new state */
-                       preload_pd_set_state(pd, LOADING);
-               }
+               vaddr = __not_loaded_entry(ri, regs, pd);
                break;
        case LOADING:
                /* handlers have not yet been loaded... just ignore */
                break;
        case LOADED:
-               base = preload_pd_get_handlers_base(pd);
-               if (base == 0)
-                       break;  /* handlers isn't mapped */
-
-               /* jump to preloaded handler */
-               vaddr = base + offset;
-               if (vaddr) {
-                       unsigned long disable_addr;
-                       unsigned long caddr = get_regs_ret_func(regs);
-                       struct vm_area_struct *cvma = __get_vma_by_addr(current, caddr);
-                       enum preload_call_type ct;
-
-                       ct = preload_control_call_type(ip, (void *)caddr);
-                       disable_addr = __is_probe_non_block(ip) ?
-                                      ip->orig_addr : 0;
-
-                       /* jump only if caller is instumented and it is not a system lib -
-                        * this leads to some errors */
-                       if ((cvma != NULL) && ((cvma->vm_file != NULL) &&
-                            (cvma->vm_file->f_path.dentry != NULL) &&
-                            !preload_control_check_dentry_is_ignored(cvma->vm_file->f_path.dentry)) &&
-                           __check_flag_and_call_type(ip, ct) &&
-                           !__is_handlers_call(cvma)) {
-                               if (preload_threads_set_data(current,
-                                                            caddr, ct,
-                                                            disable_addr,
-                                                            __should_drop(ip,
-                                                            ct)) != 0)
-                                       printk(PRELOAD_PREFIX "Error! Failed to set caller 0x%lx"
-                                              " for %d/%d\n", caddr, current->tgid,
-                                                              current->pid);
-                               /* args are not changed */
-                               __prepare_ujump(ri, regs, vaddr);
-                               if (disable_addr == 0)
-                                       set_preload_flags(current, HANDLER_RUNNING);
-                       }
-               }
+               vaddr = __loaded_entry(ri, regs, pd);
                break;
        case FAILED:
        case ERROR:
@@ -633,60 +713,19 @@ out_set_origin:
 static int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
        struct process_data *pd = __get_process_data(ri->rp);
-       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
-       struct us_priv *priv = (struct us_priv *)ri->data;
-       unsigned long flags = get_preload_flags(current);
-       unsigned long offset = ip->desc->info.pl_i.handler;
-       unsigned long vaddr = 0;
 
        switch (preload_pd_get_state(pd)) {
        case NOT_LOADED:
                /* loader has not yet been mapped... just ignore */
                break;
        case LOADING:
-               /* check if preloading has been completed */
-               vaddr = preload_pd_get_loader_base(pd) + preload_debugfs_get_loader_offset();
-               if (vaddr && (priv->origin == vaddr)) {
-                       preload_pd_set_handle(pd, (void __user *)regs_return_value(regs));
-
-                       /* restore original regs state */
-                       __restore_uregs(ri, regs);
-                       print_regs("REST", regs, ri);
-                       /* check if preloading done */
-
-                       if (preload_pd_get_handle(pd)) {
-                               preload_pd_set_state(pd, LOADED);
-                               preload_pd_put_path(pd);
-                       } else {
-                               preload_pd_dec_attempts(pd);
-                               preload_pd_set_state(pd, FAILED);
-                               preload_pd_put_path(pd);
-                       }
-               }
+               __loading_ret(ri, regs, pd);
                break;
        case LOADED:
-               if ((flags & HANDLER_RUNNING) ||
-                   preload_threads_check_disabled_probe(current, ip->orig_addr)) {
-                       bool non_blk_probe = __is_probe_non_block(ip);
-
-                       /* drop the flag if the handler has completed */
-                       vaddr = preload_pd_get_handlers_base(pd) + offset;
-                       if (vaddr && (priv->origin == vaddr)) {
-                               if (preload_threads_put_data(current) != 0)
-                                       printk(PRELOAD_PREFIX "Error! Failed to put caller slot"
-                                              " for %d/%d\n", current->tgid, current->pid);
-                               if (!non_blk_probe) {
-                                       flags &= ~HANDLER_RUNNING;
-                                       set_preload_flags(current, flags);
-                               }
-                       }
-               }
+               __loaded_ret(ri, regs, pd);
                break;
        case FAILED:
-               if (preload_pd_get_attempts(pd)) {
-                       preload_pd_set_state(pd, NOT_LOADED);
-                       preload_pd_put_path(pd);
-               }
+               __failed_ret(ri, regs, pd);
                break;
        case ERROR:
        default: