[FIX] Preload: total heap allocation data 05/42905/5
authorAlexander Aksenov <a.aksenov@samsung.com>
Thu, 2 Jul 2015 11:36:06 +0000 (14:36 +0300)
committerAlexander Aksenov <a.aksenov@samsung.com>
Mon, 6 Jul 2015 11:22:28 +0000 (14:22 +0300)
Change-Id: I174e04ea81f9713aca94dde70376244fce88463d
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
preload/preload_module.c
preload/preload_probe.h
preload/preload_threads.c
preload/preload_threads.h

index af4613e..b915b8d 100644 (file)
@@ -294,6 +294,35 @@ 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->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->info->pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
@@ -586,16 +615,20 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
                        struct vm_area_struct *cvma = __get_vma_by_addr(current, caddr);
                        enum preload_call_type ct;
 
-                       disable_addr = __is_probe_non_block(ip) ? ip->orig_addr : 0;
                        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 (__not_system_caller(current, cvma) && ct != NOT_INSTRUMENTED &&
+                       if (__not_system_caller(current, cvma) &&
+                           __check_flag_and_call_type(ip, ct) &&
                            !__is_handlers_call(cvma)) {
                                if (preload_threads_set_data(current,
                                                             caddr, ct,
-                                                            disable_addr) != 0)
+                                                            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);
@@ -729,6 +762,7 @@ static int write_msg_handler(struct kprobe *p, struct pt_regs *regs)
        size_t len;
        unsigned long caller_offset;
        unsigned long call_type_offset;
+       bool drop;
        int ret;
 
        user_buf = (char *)swap_get_uarg(regs, 0);
@@ -742,6 +776,10 @@ static int write_msg_handler(struct kprobe *p, struct pt_regs *regs)
                return 0;
        }
 
+       ret = preload_threads_get_drop(current, &drop);
+       if (ret != 0 || drop)
+               return 0;
+
        buf = kmalloc(len, GFP_KERNEL);
        if (buf == NULL) {
                printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
index 2b06a60..c859afd 100644 (file)
  *
  *   00 - probe is disabling internal probes;
  *   10 - probe is non blocking one;
+ *
+ *  000 - probe is executed for instrumented binaries
+ *  100 - probe is executed for non-instrumented binaries
  */
 
 enum {
        SWAP_PRELOAD_ALWAYS_RUN =       (1 << 0),
-       SWAP_PRELOAD_NON_BLOCK_PROBE =  (1 << 1)
+       SWAP_PRELOAD_NON_BLOCK_PROBE =  (1 << 1),
+       SWAP_PRELOAD_INVERTED_PROBE =   (1 << 2)
 };
 
 /* Preload probe info. */
index e6b706d..5f0ffc7 100644 (file)
@@ -20,6 +20,8 @@ struct thread_slot {
                                                 in one thread */
        unsigned long caller;
        unsigned char call_type;
+       bool drop;   /* TODO Workaround, remove when will be possible to install
+                    * several us probes at the same addr. */
 };
 
 struct disabled_addr {
@@ -96,6 +98,7 @@ static inline void __init_slot(struct thread_slot *slot)
        slot->task = NULL;
        slot->caller = 0;
        slot->call_type = 0;
+       slot->drop = false;
        INIT_LIST_HEAD(&slot->disabled_addrs);
 }
 
@@ -107,11 +110,12 @@ static inline void __reinit_slot(struct thread_slot *slot)
 
 static inline void __set_slot(struct thread_slot *slot,
                              struct task_struct *task, unsigned long caller,
-                             unsigned char call_type)
+                             unsigned char call_type, bool drop)
 {
        slot->task = task;
        slot->caller = caller;
        slot->call_type = call_type;
+       slot->drop = drop;
 }
 
 static inline int __add_to_disable_list(struct thread_slot *slot,
@@ -188,7 +192,8 @@ static inline struct thread_slot *__get_task_slot(struct task_struct *task)
 
 
 int preload_threads_set_data(struct task_struct *task, unsigned long caller,
-                            unsigned char call_type, unsigned long disable_addr)
+                            unsigned char call_type,
+                            unsigned long disable_addr, bool drop)
 {
        struct thread_slot *slot;
        int ret = 0;
@@ -197,7 +202,7 @@ int preload_threads_set_data(struct task_struct *task, unsigned long caller,
 
        list_for_each_entry(slot, &thread_slot_list, list) {
                if (__is_slot_free(slot)) {
-                       __set_slot(slot, task, caller, call_type);
+                       __set_slot(slot, task, caller, call_type, drop);
                        if ((disable_addr != 0) && 
                            (__add_to_disable_list(slot, disable_addr) != 0)) {
                                printk(PRELOAD_PREFIX "Cannot alloc memory!\n");
@@ -214,7 +219,7 @@ int preload_threads_set_data(struct task_struct *task, unsigned long caller,
                goto set_data_done;
        }
 
-       __set_slot(slot, task, caller, call_type);
+       __set_slot(slot, task, caller, call_type, drop);
 
 set_data_done:
        __unlock();
@@ -267,6 +272,28 @@ get_call_type_done:
        return ret;
 }
 
+int preload_threads_get_drop(struct task_struct *task, bool *drop)
+{
+       struct thread_slot *slot;
+       int ret = 0;
+
+       __lock();
+
+       slot = __get_task_slot(task);
+       if (slot != NULL) {
+               *drop = slot->drop;
+               goto get_drop_done;
+       }
+
+       /* If we're here - slot was not found */
+       ret = -EINVAL;
+
+get_drop_done:
+       __unlock();
+
+       return ret;
+}
+
 bool preload_threads_check_disabled_probe(struct task_struct *task,
                                          unsigned long addr)
 {
index 8d28c56..64d9b59 100644 (file)
@@ -4,10 +4,12 @@
 struct task_struct;
 
 int preload_threads_set_data(struct task_struct *task, unsigned long caller,
-                            unsigned char call_type, unsigned long disable_addr);
+                            unsigned char call_type,
+                            unsigned long disable_addr, bool drop);
 int preload_threads_get_caller(struct task_struct *task, unsigned long *caller);
 int preload_threads_get_call_type(struct task_struct *task,
                                  unsigned char *call_type);
+int preload_threads_get_drop(struct task_struct *task, bool *drop);
 bool preload_threads_check_disabled_probe(struct task_struct *task,
                                          unsigned long addr);
 void preload_threads_enable_probe(struct task_struct *task, unsigned long addr);