[IMPROVE] Preload: breakpoint probe msgs saving 35/42535/4
authorAlexander Aksenov <a.aksenov@samsung.com>
Fri, 27 Feb 2015 12:00:37 +0000 (15:00 +0300)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Thu, 2 Jul 2015 09:57:44 +0000 (02:57 -0700)
Change-Id: I4a8e3e7942a65ad3a128f616e15ae0370ee95b18
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
parser/msg_parser.c
preload/preload_module.c
preload/preload_module.h
preload/preload_probe.c
preload/preload_probe.h
us_manager/probes/probes.h

index f9b51f5..82ec28d 100644 (file)
@@ -379,6 +379,7 @@ void put_preload_probe(struct probe_info *pi)
  * @param pi Pointer to the probe_info struct.
  * @return 0 on success, error code on error.
  */
+
 int get_get_caller_probe(struct msg_buf *mb, struct probe_info *pi)
 {
        pi->probe_type = SWAP_GET_CALLER;
@@ -422,6 +423,31 @@ void put_get_call_type_probe(struct probe_info *pi)
 {
 }
 
+/**
+ * @brief Gets preload write_msg and puts it to the probe_info struct.
+ *
+ * @param mb Pointer to the message buffer.
+ * @param pi Pointer to the probe_info struct.
+ * @return 0 on success, error code on error.
+ */
+int get_write_msg_probe(struct msg_buf *mb, struct probe_info *pi)
+{
+       pi->probe_type = SWAP_WRITE_MSG;
+       pi->size = sizeof(pi->wm_i);
+
+       return 0;
+}
+
+/**
+ * @brief Preload write_msg type probe data cleanup.
+ *
+ * @param pi Pointer to the probe_info comprising retprobe.
+ * @return Void.
+ */
+void put_write_msg_probe(struct probe_info *pi)
+{
+}
+
 
 
 
@@ -620,6 +646,10 @@ struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
                if (get_fbi_probe(mb, &(fi->probe_i)) != 0)
                        goto free_func_inst;
                break;
+       case SWAP_WRITE_MSG:
+               if (get_write_msg_probe(mb, &(fi->probe_i)) != 0)
+                       goto free_func_inst;
+               break;
        default:
                printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
                       type);
@@ -660,6 +690,9 @@ void destroy_func_inst_data(struct func_inst_data *fi)
        case SWAP_FBIPROBE:
                put_fbi_probe(&(fi->probe_i));
                break;
+       case SWAP_WRITE_MSG:
+               put_write_msg_probe(&(fi->probe_i));
+               break;
        default:
                printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
                   fi->probe_i.probe_type);
index e0a8195..af4613e 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/err.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
 #include <kprobe/swap_kprobes.h>
 #include <us_manager/us_manager_common.h>
 #include <us_manager/sspt/sspt_page.h>
@@ -16,6 +18,7 @@
 #include <us_manager/callbacks.h>
 #include <writer/kernel_operations.h>
 #include <master/swap_initializer.h>
+#include <writer/swap_msg.h>
 #include <task_data/task_data.h>
 #include "preload.h"
 #include "preload_probe.h"
@@ -326,6 +329,22 @@ is_handlers_call_out:
        return res;
 }
 
+static inline int __msg_sanitization(char *user_msg, size_t len,
+                                    char *call_type_p, char *caller_p)
+{
+       int ret;
+
+       ret = access_ok(VERIFY_READ, (unsigned long)user_msg, (unsigned long)len);
+       if (ret == 0)
+               return -EINVAL;
+
+       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,6 +398,34 @@ 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 char call_type = 0;
+       unsigned long caller = 0;
+       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);
+       }
+
+       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;
+}
+
+
 
 
 enum mmap_type_t {
@@ -673,6 +720,58 @@ static int get_call_type_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
+static int write_msg_handler(struct kprobe *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;
+       int ret;
+
+       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);
+
+       ret = __msg_sanitization(user_buf, len, call_type_p, caller_p);
+       if (ret != 0) {
+               printk(PRELOAD_PREFIX "Invalid message pointers!\n");
+               return 0;
+       }
+
+       buf = kmalloc(len, GFP_KERNEL);
+       if (buf == NULL) {
+               printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
+               return 0;
+       }
+
+       if (copy_from_user(buf, user_buf, len)) {
+               printk(PRELOAD_PREFIX "Cannot copy data from userspace! Size = %d"
+                                     " ptr 0x%lx\n", len, (unsigned long)user_buf);
+               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);
+
+       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;
+}
+
 
 
 
@@ -702,6 +801,20 @@ void preload_module_get_call_type_exit(struct us_ip *ip)
 {
 }
 
+int preload_module_write_msg_init(struct us_ip *ip)
+{
+       struct uprobe *up = &ip->uprobe;
+
+       up->kp.pre_handler = write_msg_handler;
+
+       return 0;
+}
+
+void preload_module_write_msg_exit(struct us_ip *ip)
+{
+}
+
+
 int preload_module_uprobe_init(struct us_ip *ip)
 {
        struct uretprobe *rp = &ip->retprobe;
index cc33f53..62f0bfd 100644 (file)
@@ -20,6 +20,8 @@ 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);
 
 struct dentry *get_dentry(const char *filepath);
 void put_dentry(struct dentry *dentry);
index 400a422..9ca7317 100644 (file)
@@ -211,7 +211,27 @@ static struct probe_iface get_call_type_iface = {
        .cleanup = get_caller_info_cleanup
 };
 
+static void write_msg_init(struct us_ip *ip)
+{
+       preload_module_write_msg_init(ip);
+}
+
+static void write_msg_uninit(struct us_ip *ip)
+{
+       preload_module_write_msg_exit(ip);
 
+       get_caller_info_cleanup(ip->info);
+}
+
+static struct probe_iface write_msg_iface = {
+       .init = write_msg_init,
+       .uninit = write_msg_uninit,
+       .reg = get_caller_register_probe,
+       .unreg = get_caller_unregister_probe,
+       .get_uprobe = get_caller_get_uprobe,
+       .copy = get_caller_info_copy,
+       .cleanup = get_caller_info_cleanup
+};
 
 int register_preload_probes(void)
 {
@@ -226,6 +246,10 @@ int register_preload_probes(void)
                return ret;
 
        ret = swap_register_probe_type(SWAP_GET_CALL_TYPE, &get_call_type_iface);
+       if (ret != 0)
+               return ret;
+
+       ret = swap_register_probe_type(SWAP_WRITE_MSG, &write_msg_iface);
        return ret;
 }
 
@@ -234,4 +258,5 @@ void unregister_preload_probes(void)
        swap_unregister_probe_type(SWAP_PRELOAD_PROBE);
        swap_unregister_probe_type(SWAP_GET_CALLER);
        swap_unregister_probe_type(SWAP_GET_CALL_TYPE);
+       swap_unregister_probe_type(SWAP_WRITE_MSG);
 }
index 5d1f71c..2b06a60 100644 (file)
@@ -53,6 +53,10 @@ struct get_caller_info {
 struct get_call_type_info {
 };
 
+/* Write message probe info */
+struct write_msg_info {
+};
+
 int register_preload_probes(void);
 void unregister_preload_probes(void);
 
index b82eec7..a911d10 100644 (file)
@@ -52,6 +52,8 @@ enum probe_t {
        SWAP_WEBPROBE = 3,          /* Webprobe */
        SWAP_GET_CALLER = 4,        /* Get caller probe. Supports preload */
        SWAP_GET_CALL_TYPE = 5,     /* Get call type probe. Supports preload */
+       SWAP_WRITE_MSG = 6,         /* Write messages from user space directly to 
+                                    * kernel. Supports preload */
        SWAP_NEW_UP,
        SWAP_NEW_URP,
        SWAP_PROBE_MAX_VAL          /* Probes max value. */
@@ -68,6 +70,7 @@ struct probe_info {
                struct preload_info pl_i;
                struct get_caller_info gc_i;
                struct get_call_type_info gct_i;
+               struct write_msg_info wm_i;
        };
 
        char data[0];