[IMRPOVE] Preload: load and execution in different files 91/54091/7
authorAlexander Aksenov <a.aksenov@samsung.com>
Tue, 8 Dec 2015 17:27:25 +0000 (20:27 +0300)
committerAlexander Aksenov <a.aksenov@samsung.com>
Fri, 11 Dec 2015 12:57:18 +0000 (15:57 +0300)
Change-Id: I94a1fda7790d3dccd58d297565f372573520a5d2
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
preload/Kbuild
preload/preload_control.h
preload/preload_handlers.c [new file with mode: 0644]
preload/preload_handlers.h [new file with mode: 0644]
preload/preload_module.c
preload/preload_module.h
preload/preload_probe.c
preload/preload_storage.c

index 84aa787..e118bce 100644 (file)
@@ -2,6 +2,7 @@ EXTRA_CFLAGS := $(extra_cflags)
 
 obj-m := swap_preload.o
 swap_preload-y := preload_module.o \
+                  preload_handlers.o \
                   preload_debugfs.o \
                   preload_storage.o \
                   preload_probe.o \
index 38de2dd..67ca2ee 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __PRELOAD_CONTROL_H__
 #define __PRELOAD_CONTROL_H__
 
+struct us_ip;
+
 enum preload_call_type {
        NOT_INSTRUMENTED,
        EXTERNAL_CALL,
diff --git a/preload/preload_handlers.c b/preload/preload_handlers.c
new file mode 100644 (file)
index 0000000..0702a79
--- /dev/null
@@ -0,0 +1,471 @@
+#include <linux/slab.h>
+#include <kprobe/swap_kprobes_deps.h>
+#include <writer/kernel_operations.h>
+#include <writer/swap_msg.h>
+#include <us_manager/sspt/ip.h>
+#include <us_manager/sspt/sspt_page.h>
+#include <us_manager/sspt/sspt_file.h>
+#include "preload.h"
+#include "preload_pd.h"
+#include "preload_control.h"
+#include "preload_threads.h"
+#include "preload_module.h"
+
+#define page_to_proc(page) ((page)->file->proc)
+#define ip_to_proc(ip) page_to_proc((ip)->page)
+
+enum {
+       /* task preload flags */
+       HANDLER_RUNNING = 0x1
+};
+
+static struct dentry *handler_dentry = NULL;
+
+
+static inline struct pd_t *__get_process_data(struct uretprobe *rp)
+{
+       struct us_ip *ip = to_us_ip(rp);
+       struct sspt_proc *proc = ip_to_proc(ip);
+
+       return preload_pd_get(proc);
+}
+
+static inline struct vm_area_struct *__get_vma_by_addr(struct task_struct *task,
+                                                      unsigned long caddr)
+{
+       struct vm_area_struct *vma = NULL;
+
+       if ((task == NULL) && (task->mm == NULL))
+               return NULL;
+       vma = find_vma_intersection(task->mm, caddr, caddr + 1);
+
+       return vma;
+}
+
+static inline bool __is_probe_non_block(struct us_ip *ip)
+{
+       if (ip->desc->info.pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
+               return true;
+
+       return false;
+}
+
+static inline bool __inverted(struct us_ip *ip)
+{
+       unsigned long flags = ip->desc->info.pl_i.flags;
+
+       if (flags & SWAP_PRELOAD_INVERTED_PROBE)
+               return true;
+
+       return false;
+}
+
+static inline bool __check_flag_and_call_type(struct us_ip *ip,
+                                             enum preload_call_type ct)
+{
+       bool inverted = __inverted(ip);
+
+       if (ct != NOT_INSTRUMENTED || inverted)
+               return true;
+
+       return false;
+}
+
+static inline bool __is_handlers_call(struct vm_area_struct *caller,
+                                     struct pd_t *pd)
+{
+       struct hd_t *hd;
+
+       if (caller == NULL || caller->vm_file == NULL ||
+           caller->vm_file->f_path.dentry == NULL) {
+               return false;
+       }
+
+       hd = preload_pd_get_hd(pd, caller->vm_file->f_path.dentry);
+       if (hd != NULL)
+               return true;
+
+       return false;
+}
+
+static inline bool __should_drop(struct us_ip *ip, enum preload_call_type ct)
+{
+       if (ct == NOT_INSTRUMENTED)
+               return true;
+
+       return false;
+}
+
+static inline int __msg_sanitization(char *user_msg, size_t len,
+                                    char *call_type_p, char *caller_p)
+{
+       if ((call_type_p < user_msg) || (call_type_p > user_msg + len) ||
+           (caller_p < user_msg) || (caller_p > user_msg + len))
+               return -EINVAL;
+
+       return 0;
+}
+
+
+
+
+static unsigned long __do_preload_entry(struct uretprobe_instance *ri,
+                                       struct pt_regs *regs,
+                                       struct hd_t *hd)
+{
+       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(hd);
+       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_dentry != NULL) {
+
+                       struct dentry *dentry = cvma->vm_file->f_dentry;
+                       struct pd_t *pd = preload_pd_get_parent_pd(hd);
+
+                       if (!preload_control_check_dentry_is_ignored(dentry) &&
+                           __check_flag_and_call_type(ip, ct) &&
+                           !__is_handlers_call(cvma, pd)) {
+
+                               bool drop = __should_drop(ip, ct);
+                               if (preload_threads_set_data(current, caddr,
+                                                            ct, disable_addr,
+                                                            drop) != 0)
+                                       printk(PRELOAD_PREFIX "Error! Failed "
+                                              "to set caller 0x%lx for "
+                                              "%d/%d\n", caddr,
+                                              current->tgid,
+                                              current->pid);
+                               /* args are not changed */
+                               preload_module_prepare_ujump(ri, regs, vaddr);
+                               if (disable_addr == 0)
+                                       set_preload_flags(current,
+                                                         HANDLER_RUNNING);
+                       }
+               }
+       }
+
+       return vaddr;
+}
+
+static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
+{
+       struct pd_t *pd = __get_process_data(ri->rp);
+       struct hd_t *hd;
+       unsigned long flags = get_preload_flags(current);
+       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
+       unsigned long vaddr = 0;
+
+       if (handler_dentry == NULL)
+               goto out_set_orig;
+
+       if ((flags & HANDLER_RUNNING) ||
+           preload_threads_check_disabled_probe(current, ip->orig_addr))
+               goto out_set_orig;
+
+       hd = preload_pd_get_hd(pd, handler_dentry);
+       if (hd == NULL)
+               goto out_set_orig;
+
+       if ((flags & HANDLER_RUNNING) ||
+               preload_threads_check_disabled_probe(current, ip->orig_addr))
+               goto out_set_orig;
+
+       if (preload_pd_get_state(hd) == NOT_LOADED ||
+           preload_pd_get_state(hd) == FAILED)
+               vaddr = preload_not_loaded_entry(ri, regs, pd, hd);
+       else if (preload_pd_get_state(hd) == LOADED)
+               vaddr =__do_preload_entry(ri, regs, hd);
+
+out_set_orig:
+       preload_set_priv_origin(ri, vaddr);
+
+       return 0;
+}
+
+static void __do_preload_ret(struct uretprobe_instance *ri, struct hd_t *hd)
+{
+       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
+       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(hd) + offset;
+               if (vaddr && (preload_get_priv_origin(ri) == 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 int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs)
+{
+       struct pd_t *pd = __get_process_data(ri->rp);
+       struct hd_t *hd;
+
+       if (handler_dentry == NULL)
+               return 0;
+
+       hd = preload_pd_get_hd(pd, handler_dentry);
+       if (hd == NULL)
+               return 0;
+
+       switch (preload_pd_get_state(hd)) {
+       case NOT_LOADED:
+               /* loader has not yet been mapped... just ignore */
+               break;
+       case LOADING:
+               preload_loading_ret(ri, regs, pd, hd);
+               break;
+       case LOADED:
+               __do_preload_ret(ri, hd);
+               break;
+       case FAILED:
+               preload_failed_ret(ri, regs, pd, hd);
+               break;
+       case ERROR:
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+
+
+
+
+static void __write_data_to_msg(char *msg, size_t len,
+                               unsigned long call_type_off,
+                               unsigned long caller_off,
+                               unsigned long caller_addr)
+{
+       unsigned char call_type = 0;
+       unsigned long caller = 0;
+       int ret;
+
+       if (caller_addr != 0) {
+               caller = caller_addr;
+               call_type =
+                   preload_control_call_type_always_inst((void *)caller);
+       } else {
+               ret = preload_threads_get_caller(current, &caller);
+               if (ret != 0) {
+                       caller = 0xbadbeef;
+                       printk(PRELOAD_PREFIX "Error! Cannot get caller address"
+                              " for %d/%d\n", current->tgid, current->pid);
+               }
+
+               ret = preload_threads_get_call_type(current, &call_type);
+               if (ret != 0) {
+                       call_type = 0xff;
+                       printk(PRELOAD_PREFIX "Error! Cannot get call type for "
+                              "%d/%d\n", current->tgid, current->pid);
+               }
+       }
+
+       /* Using the same types as in the library. */
+       *(uint32_t *)(msg + call_type_off) = (uint32_t)call_type;
+       *(uintptr_t *)(msg + caller_off) = (uintptr_t)caller;
+}
+
+static int write_msg_handler(struct uprobe *p, struct pt_regs *regs)
+{
+       char *user_buf;
+       char *buf;
+       char *caller_p;
+       char *call_type_p;
+       size_t len;
+       unsigned long caller_offset;
+       unsigned long call_type_offset;
+       unsigned long caller_addr;
+       int ret;
+
+       /* FIXME: swap_get_uarg uses get_user(), it might sleep */
+       user_buf = (char *)swap_get_uarg(regs, 0);
+       len = swap_get_uarg(regs, 1);
+       call_type_p = (char *)swap_get_uarg(regs, 2);
+       caller_p = (char *)swap_get_uarg(regs, 3);
+       caller_addr = swap_get_uarg(regs, 4);
+
+       ret = __msg_sanitization(user_buf, len, call_type_p, caller_p);
+       if (ret != 0) {
+               printk(PRELOAD_PREFIX "Invalid message pointers!\n");
+               return 0;
+       }
+
+       ret = preload_threads_get_drop(current);
+       if (ret > 0)
+               return 0;
+
+       buf = kmalloc(len, GFP_ATOMIC);
+       if (buf == NULL) {
+               printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
+               return 0;
+       }
+
+       ret = read_proc_vm_atomic(current, (unsigned long)user_buf, buf, len);
+       if (ret < 0) {
+               printk(PRELOAD_PREFIX "Cannot copy data from userspace! Size = "
+                                     "%d ptr 0x%lx ret %d\n", len,
+                                     (unsigned long)user_buf, ret);
+               goto write_msg_fail;
+       }
+
+       /* Evaluating call_type and caller offset in message:
+        * data offset = data pointer - beginning of the message.
+        */
+       call_type_offset = (unsigned long)(call_type_p - user_buf);
+       caller_offset = (unsigned long)(caller_p - user_buf);
+
+       __write_data_to_msg(buf, len, call_type_offset, caller_offset,
+                           caller_addr);
+
+       ret = swap_msg_raw(buf, len);
+       if (ret != len)
+               printk(PRELOAD_PREFIX "Error writing probe lib message\n");
+
+write_msg_fail:
+       kfree(buf);
+
+       return 0;
+}
+
+
+
+
+
+
+
+
+
+static int get_caller_handler(struct uprobe *p, struct pt_regs *regs)
+{
+       unsigned long caller;
+       int ret;
+
+       ret = preload_threads_get_caller(current, &caller);
+       if (ret != 0) {
+               caller = 0xbadbeef;
+               printk(PRELOAD_PREFIX "Error! Cannot get caller address for "
+                      "%d/%d\n", current->tgid, current->pid);
+       }
+
+       swap_put_uarg(regs, 0, caller);
+
+       return 0;
+}
+
+static int get_call_type_handler(struct uprobe *p, struct pt_regs *regs)
+{
+       unsigned char call_type;
+       int ret;
+
+       ret = preload_threads_get_call_type(current, &call_type);
+       if (ret != 0) {
+               call_type = 0xff;
+               printk(PRELOAD_PREFIX "Error! Cannot get call type for %d/%d\n",
+                      current->tgid, current->pid);
+       }
+
+       swap_put_uarg(regs, 0, call_type);
+
+       return 0;
+}
+
+
+
+
+
+
+int ph_get_caller_init(struct us_ip *ip)
+{
+       struct uprobe *up = &ip->uprobe;
+
+       up->pre_handler = get_caller_handler;
+
+       return 0;
+}
+
+void ph_get_caller_exit(struct us_ip *ip)
+{
+}
+
+int ph_get_call_type_init(struct us_ip *ip)
+{
+       struct uprobe *up = &ip->uprobe;
+
+       up->pre_handler = get_call_type_handler;
+
+       return 0;
+}
+
+void ph_get_call_type_exit(struct us_ip *ip)
+{
+}
+
+int ph_write_msg_init(struct us_ip *ip)
+{
+       struct uprobe *up = &ip->uprobe;
+
+       up->pre_handler = write_msg_handler;
+
+       return 0;
+}
+
+void ph_write_msg_exit(struct us_ip *ip)
+{
+}
+
+void ph_set_handler_dentry(struct dentry *dentry)
+{
+       handler_dentry = dentry;
+}
+
+
+int ph_uprobe_init(struct us_ip *ip)
+{
+       struct uretprobe *rp = &ip->retprobe;
+
+       rp->entry_handler = preload_us_entry;
+       rp->handler = preload_us_ret;
+       /* FIXME actually additional data_size is needed only when we jump
+        * to dlopen */
+       preload_set_rp_data_size(rp);
+
+       return 0;
+}
+
+void ph_uprobe_exit(struct us_ip *ip)
+{
+}
diff --git a/preload/preload_handlers.h b/preload/preload_handlers.h
new file mode 100644 (file)
index 0000000..bf1fbfb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __PRELOAD_HANDLERS_H__
+#define __PRELOAD_HANDLERS_H__
+
+struct us_ip;
+struct dentry;
+
+int ph_uprobe_init(struct us_ip *ip);
+void ph_uprobe_exit(struct us_ip *ip);
+
+int ph_get_caller_init(struct us_ip *ip);
+void ph_get_caller_exit(struct us_ip *ip);
+int ph_get_call_type_init(struct us_ip *ip);
+void ph_get_call_type_exit(struct us_ip *ip);
+int ph_write_msg_init(struct us_ip *ip);
+void ph_write_msg_exit(struct us_ip *ip);
+void ph_set_handler_dentry(struct dentry *dentry);
+
+#endif /* __PRELOAD_HANDLERS_H__ */
index c376086..d5c6b8b 100644 (file)
@@ -29,9 +29,6 @@
 #include "preload_threads.h"
 #include "preload_pd.h"
 
-#define page_to_proc(page) ((page)->file->proc)
-#define page_to_dentry(page) ((page)->file->dentry)
-#define ip_to_proc(ip) page_to_proc((ip)->page)
 
 struct us_priv {
        struct pt_regs regs;
@@ -49,25 +46,11 @@ enum preload_status_t {
        SWAP_PRELOAD_RUNNING = 2
 };
 
-enum {
-       /* task preload flags */
-       HANDLER_RUNNING = 0x1
-};
-
 static enum preload_status_t __preload_status = SWAP_PRELOAD_NOT_READY;
 
 static int __preload_cbs_start_h = -1;
 static int __preload_cbs_stop_h = -1;
 
-static struct dentry *handler_dentry = NULL;
-
-static inline struct pd_t *__get_process_data(struct uretprobe *rp)
-{
-       struct us_ip *ip = to_us_ip(rp);
-       struct sspt_proc *proc = ip_to_proc(ip);
-
-       return preload_pd_get(proc);
-}
 
 static struct dentry *__get_dentry(struct dentry *dentry)
 {
@@ -270,69 +253,9 @@ static inline struct vm_area_struct *__get_vma_by_addr(struct task_struct *task,
        return vma;
 }
 
-static inline bool __inverted(struct us_ip *ip)
-{
-       unsigned long flags = ip->desc->info.pl_i.flags;
-
-       if (flags & SWAP_PRELOAD_INVERTED_PROBE)
-               return true;
-
-       return false;
-}
-
-static inline bool __should_drop(struct us_ip *ip, enum preload_call_type ct)
-{
-       if (ct == NOT_INSTRUMENTED)
-               return true;
-
-       return false;
-}
-
-static inline bool __check_flag_and_call_type(struct us_ip *ip,
-                                             enum preload_call_type ct)
-{
-       bool inverted = __inverted(ip);
-
-       if (ct != NOT_INSTRUMENTED || inverted)
-               return true;
-
-       return false;
-}
-
-static inline bool __is_probe_non_block(struct us_ip *ip)
-{
-       if (ip->desc->info.pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
-               return true;
 
-       return false;
-}
 
-static inline bool __is_handlers_call(struct vm_area_struct *caller,
-                                     struct pd_t *pd)
-{
-       struct hd_t *hd;
 
-       if (caller == NULL || caller->vm_file == NULL ||
-               caller->vm_file->f_path.dentry == NULL) {
-               return false;
-       }
-
-       hd = preload_pd_get_hd(pd, caller->vm_file->f_path.dentry);
-       if (hd != NULL)
-               return true;
-
-       return false;
-}
-
-static inline int __msg_sanitization(char *user_msg, size_t len,
-                                    char *call_type_p, char *caller_p)
-{
-       if ((call_type_p < user_msg) || (call_type_p > user_msg + len) ||
-           (caller_p < user_msg) || (caller_p > user_msg + len))
-               return -EINVAL;
-
-       return 0;
-}
 
 
 
@@ -379,38 +302,6 @@ static bool __should_we_preload_handlers(struct task_struct *task,
        return true;
 }
 
-static inline void __write_data_to_msg(char *msg, size_t len,
-                                      unsigned long call_type_off,
-                                      unsigned long caller_off,
-                                      unsigned long caller_addr)
-{
-       unsigned char call_type = 0;
-       unsigned long caller = 0;
-       int ret;
-
-       if (caller_addr != 0) {
-               caller = caller_addr;
-               call_type = preload_control_call_type_always_inst((void *)caller);
-       } else {
-               ret = preload_threads_get_caller(current, &caller);
-               if (ret != 0) {
-                       caller = 0xbadbeef;
-                       printk(PRELOAD_PREFIX "Error! Cannot get caller address for %d/%d\n",
-                              current->tgid, current->pid);
-               }
-
-               ret = preload_threads_get_call_type(current, &call_type);
-               if (ret != 0) {
-                       call_type = 0xff;
-                       printk(PRELOAD_PREFIX "Error! Cannot get call type for %d/%d\n",
-                              current->tgid, current->pid);
-               }
-       }
-
-       /* Using the same types as in the library. */
-       *(uint32_t *)(msg + call_type_off) = (uint32_t)call_type;
-       *(uintptr_t *)(msg + caller_off) = (uintptr_t)caller;
-}
 
 
 
@@ -610,301 +501,50 @@ static void __failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
 
 
 
-static unsigned long __do_preload_entry(struct uretprobe_instance *ri,
-                                       struct pt_regs *regs,
-                                       struct hd_t *hd)
+unsigned long preload_not_loaded_entry(struct uretprobe_instance *ri,
+                                      struct pt_regs *regs, struct pd_t *pd,
+                                      struct hd_t *hd)
 {
-       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(hd);
-       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, preload_pd_get_parent_pd(hd))) {
-                       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 int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
-       struct pd_t *pd = __get_process_data(ri->rp);
-       struct hd_t *hd;
-       unsigned long flags = get_preload_flags(current);
-       struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
-       struct us_priv *priv = (struct us_priv *)ri->data;
-       unsigned long vaddr = 0;
-
-       if (handler_dentry == NULL)
-               goto out_set_orig;
-
-       if ((flags & HANDLER_RUNNING) ||
-           preload_threads_check_disabled_probe(current, ip->orig_addr))
-               goto out_set_orig;
-
-       hd = preload_pd_get_hd(pd, handler_dentry);
-       if (hd == NULL)
-               goto out_set_orig;
-
-       if ((flags & HANDLER_RUNNING) ||
-           preload_threads_check_disabled_probe(current, ip->orig_addr))
-               goto out_set_orig;
-
-       if (preload_pd_get_state(hd) == NOT_LOADED ||
-           preload_pd_get_state(hd) == FAILED)
-               vaddr = __not_loaded_entry(ri, regs, pd, hd);
-       else if (preload_pd_get_state(hd) == LOADED)
-               vaddr =__do_preload_entry(ri, regs, hd);
-
-out_set_orig:
-       priv->origin = vaddr;
-       return 0;
+       return __not_loaded_entry(ri, regs, pd, hd);
 }
 
-static void __do_preload_ret(struct uretprobe_instance *ri, struct hd_t *hd)
-{
-       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(hd) + 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 int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
-       struct pd_t *pd = __get_process_data(ri->rp);
-       struct hd_t *hd;
-
-       if (handler_dentry == NULL)
-               return 0;
-
-       hd = preload_pd_get_hd(pd, handler_dentry);
-       if (hd == NULL)
-               return 0;
-
-       switch (preload_pd_get_state(hd)) {
-       case NOT_LOADED:
-               /* loader has not yet been mapped... just ignore */
-               break;
-       case LOADING:
-               __loading_ret(ri, regs, pd, hd);
-               break;
-       case LOADED:
-               __do_preload_ret(ri, hd);
-               break;
-       case FAILED:
-               __failed_ret(ri, regs, pd, hd);
-               break;
-       case ERROR:
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-
-
-static int get_caller_handler(struct uprobe *p, struct pt_regs *regs)
-{
-       unsigned long caller;
-       int ret;
-
-       ret = preload_threads_get_caller(current, &caller);
-       if (ret != 0) {
-               caller = 0xbadbeef;
-               printk(PRELOAD_PREFIX "Error! Cannot get caller address for %d/%d\n",
-                      current->tgid, current->pid);
-       }
-
-       swap_put_uarg(regs, 0, caller);
-
-       return 0;
-}
-
-static int get_call_type_handler(struct uprobe *p, struct pt_regs *regs)
-{
-       unsigned char call_type;
-       int ret;
-
-       ret = preload_threads_get_call_type(current, &call_type);
-       if (ret != 0) {
-               call_type = 0xff;
-               printk(PRELOAD_PREFIX "Error! Cannot get call type for %d/%d\n",
-                      current->tgid, current->pid);
-       }
-
-       swap_put_uarg(regs, 0, call_type);
-
-       return 0;
-}
-
-static int write_msg_handler(struct uprobe *p, struct pt_regs *regs)
-{
-       char *user_buf;
-       char *buf;
-       char *caller_p;
-       char *call_type_p;
-       size_t len;
-       unsigned long caller_offset;
-       unsigned long call_type_offset;
-       unsigned long caller_addr;
-       int ret;
-
-       /* FIXME: swap_get_uarg uses get_user(), it might sleep */
-       user_buf = (char *)swap_get_uarg(regs, 0);
-       len = swap_get_uarg(regs, 1);
-       call_type_p = (char *)swap_get_uarg(regs, 2);
-       caller_p = (char *)swap_get_uarg(regs, 3);
-       caller_addr = swap_get_uarg(regs, 4);
-
-       ret = __msg_sanitization(user_buf, len, call_type_p, caller_p);
-       if (ret != 0) {
-               printk(PRELOAD_PREFIX "Invalid message pointers!\n");
-               return 0;
-       }
-
-       ret = preload_threads_get_drop(current);
-       if (ret > 0)
-               return 0;
-
-       buf = kmalloc(len, GFP_ATOMIC);
-       if (buf == NULL) {
-               printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
-               return 0;
-       }
-
-       ret = read_proc_vm_atomic(current, (unsigned long)user_buf, buf, len);
-       if (ret < 0) {
-               printk(PRELOAD_PREFIX "Cannot copy data from userspace! Size = %d"
-                                     " ptr 0x%lx ret %d\n", len, (unsigned long)user_buf, ret);
-               goto write_msg_fail;
-       }
-
-       /* Evaluating call_type and caller offset in message:
-        * data offset = data pointer - beginning of the message.
-        */
-       call_type_offset = (unsigned long)(call_type_p - user_buf);
-       caller_offset = (unsigned long)(caller_p - user_buf);
-
-       __write_data_to_msg(buf, len, call_type_offset, caller_offset, caller_addr);
-
-       ret = swap_msg_raw(buf, len);
-       if (ret != len)
-               printk(PRELOAD_PREFIX "Error writing probe lib message\n");
-
-write_msg_fail:
-       kfree(buf);
-
-       return 0;
-}
-
-
-
-
-int preload_module_get_caller_init(struct us_ip *ip)
+void preload_loading_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                        struct pd_t *pd, struct hd_t *hd)
 {
-       struct uprobe *up = &ip->uprobe;
-
-       up->pre_handler = get_caller_handler;
-
-       return 0;
+       __loading_ret(ri, regs, pd, hd);
 }
 
-void preload_module_get_caller_exit(struct us_ip *ip)
+void preload_failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                       struct pd_t *pd, struct hd_t *hd)
 {
+       __failed_ret(ri, regs, pd, hd);
 }
 
-int preload_module_get_call_type_init(struct us_ip *ip)
+void preload_module_prepare_ujump(struct uretprobe_instance *ri,
+                                 struct pt_regs *regs, unsigned long addr)
 {
-       struct uprobe *up = &ip->uprobe;
-
-       up->pre_handler = get_call_type_handler;
-
-       return 0;
+       __prepare_ujump(ri, regs, addr);
 }
 
-void preload_module_get_call_type_exit(struct us_ip *ip)
+void preload_set_rp_data_size(struct uretprobe *rp)
 {
+       rp->data_size = sizeof(struct us_priv);
 }
 
-int preload_module_write_msg_init(struct us_ip *ip)
+void preload_set_priv_origin(struct uretprobe_instance *ri, unsigned long addr)
 {
-       struct uprobe *up = &ip->uprobe;
-
-       up->pre_handler = write_msg_handler;
-
-       return 0;
-}
+       struct us_priv *priv = (struct us_priv *)ri->data;
 
-void preload_module_write_msg_exit(struct us_ip *ip)
-{
+       priv->origin = addr;
 }
 
-
-int preload_module_uprobe_init(struct us_ip *ip)
+unsigned long preload_get_priv_origin(struct uretprobe_instance *ri)
 {
-       struct uretprobe *rp = &ip->retprobe;
-
-       rp->entry_handler = preload_us_entry;
-       rp->handler = preload_us_ret;
-       /* FIXME actually additional data_size is needed only when we jump
-        * to dlopen */
-       rp->data_size = sizeof(struct us_priv);
+       struct us_priv *priv = (struct us_priv *)ri->data;
 
-       return 0;
+    return priv->origin;
 }
 
-void preload_module_uprobe_exit(struct us_ip *ip)
-{
-}
 
 int preload_set(void)
 {
@@ -922,10 +562,6 @@ void preload_unset(void)
 
 }
 
-void preload_module_set_handler_dentry(struct dentry *dentry)
-{
-       handler_dentry = dentry;
-}
 
 static int preload_module_init(void)
 {
index 3e0fd07..7b0ce2d 100644 (file)
@@ -3,8 +3,11 @@
 
 #include <linux/types.h>
 
-struct us_ip;
 struct dentry;
+struct pd_t;
+struct hd_t;
+struct uretprobe;
+struct uretprobe_instance;
 
 bool preload_module_is_ready(void);
 bool preload_module_is_running(void);
@@ -13,20 +16,26 @@ void preload_module_set_ready(void);
 void preload_module_set_running(void);
 void preload_module_set_not_ready(void);
 
-int preload_module_uprobe_init(struct us_ip *ip);
-void preload_module_uprobe_exit(struct us_ip *ip);
-
-int preload_module_get_caller_init(struct us_ip *ip);
-void preload_module_get_caller_exit(struct us_ip *ip);
-int preload_module_get_call_type_init(struct us_ip *ip);
-void preload_module_get_call_type_exit(struct us_ip *ip);
-int preload_module_write_msg_init(struct us_ip *ip);
-void preload_module_write_msg_exit(struct us_ip *ip);
 
 void preload_module_set_handler_dentry(struct dentry *dentry);
 
 struct dentry *get_dentry(const char *filepath);
 void put_dentry(struct dentry *dentry);
 
+void preload_module_prepare_ujump(struct uretprobe_instance *ri,
+                                 struct pt_regs *regs, unsigned long addr);
+
+unsigned long preload_not_loaded_entry(struct uretprobe_instance *ri,
+                                      struct pt_regs *regs, struct pd_t *pd,
+                                      struct hd_t *hd);
+void preload_loading_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                        struct pd_t *pd, struct hd_t *hd);
+void preload_failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+                       struct pd_t *pd, struct hd_t *hd);
+
+void preload_set_rp_data_size(struct uretprobe *rp);
+void preload_set_priv_origin(struct uretprobe_instance *ri, unsigned long addr);
+unsigned long preload_get_priv_origin(struct uretprobe_instance *ri);
+
 
 #endif /* __PRELOAD_MODULE_H__ */
index f66e214..c7b0f44 100644 (file)
@@ -31,6 +31,7 @@
 #include "preload_probe.h"
 #include "preload.h"
 #include "preload_module.h"
+#include "preload_handlers.h"
 #include "preload_debugfs.h"
 
 static unsigned long long probes_count = 0;
@@ -120,12 +121,12 @@ static void preload_unregister_probe(struct us_ip *ip, int disarm)
 
 static void preload_init(struct us_ip *ip)
 {
-       preload_module_uprobe_init(ip);
+       ph_uprobe_init(ip);
 }
 
 static void preload_uninit(struct us_ip *ip)
 {
-       preload_module_uprobe_exit(ip);
+       ph_uprobe_exit(ip);
 
        preload_info_cleanup(&ip->desc->info);
 }
@@ -169,12 +170,12 @@ static void get_caller_unregister_probe(struct us_ip *ip, int disarm)
 
 static void get_caller_init(struct us_ip *ip)
 {
-       preload_module_get_caller_init(ip);
+       ph_get_caller_init(ip);
 }
 
 static void get_caller_uninit(struct us_ip *ip)
 {
-       preload_module_get_caller_exit(ip);
+       ph_get_caller_exit(ip);
 
        get_caller_info_cleanup(&ip->desc->info);
 }
@@ -191,12 +192,12 @@ static struct probe_iface get_caller_iface = {
 
 static void get_call_type_init(struct us_ip *ip)
 {
-       preload_module_get_call_type_init(ip);
+       ph_get_call_type_init(ip);
 }
 
 static void get_call_type_uninit(struct us_ip *ip)
 {
-       preload_module_get_call_type_exit(ip);
+       ph_get_call_type_exit(ip);
 
        get_caller_info_cleanup(&ip->desc->info);
 }
@@ -213,7 +214,7 @@ static struct probe_iface get_call_type_iface = {
 
 static void write_msg_init(struct us_ip *ip)
 {
-       preload_module_write_msg_init(ip);
+       ph_write_msg_init(ip);
 }
 
 static int write_msg_reg(struct us_ip *ip)
@@ -225,7 +226,7 @@ static int write_msg_reg(struct us_ip *ip)
 
 static void write_msg_uninit(struct us_ip *ip)
 {
-       preload_module_write_msg_exit(ip);
+       ph_write_msg_exit(ip);
 
        get_caller_info_cleanup(&ip->desc->info);
 }
index bf2bad2..f2c9ff1 100644 (file)
@@ -7,6 +7,7 @@
 #include "preload.h"
 #include "preload_module.h"
 #include "preload_storage.h"
+#include "preload_handlers.h"
 
 static struct bin_info __handlers_info = { NULL, NULL };
 static struct bin_info __linker_info = { NULL, NULL };
@@ -191,7 +192,7 @@ int preload_storage_set_handlers_info(char *path)
        if (ret != 0)
                return ret;
 
-       preload_module_set_handler_dentry(__handlers_info.dentry);
+       ph_set_handler_dentry(__handlers_info.dentry);
 
        return ret;
 }