Fix infinite recursion of memory probes handling 14/189114/1
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 10 Sep 2018 16:21:49 +0000 (19:21 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 13 Sep 2018 11:13:51 +0000 (14:13 +0300)
Problem:
  During the processing of the realloc_handler () call,
  there is a recursive loop in the free_handler() call:
    -> plt@realloc() -> realloc_handler() -> lsan_get_sym() -> dlsym() ->
       plt@free() -> free_handler() -> lsan_get_sym() -> dlsym() ->
       plt@free() -> free_handler() -> lsan_get_sym() -> dlsym() ->
       plt@free() -> free_handler() -> lsan_get_sym() -> dlsym() ->
       ...

Solution:
  Find all LSan symbols during library initialization instead of lazy
  symbol search.

Change-Id: Idce7de857a468645be51c21386726ac2a37c1ade
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
helper/libdaprobe.c
helper/lsan_open.c
include/lsan_open.h
probe_memory/libdamemalloc.c
probe_thread/libdathread.c

index 8f5475d..d7ce5cf 100755 (executable)
@@ -561,7 +561,7 @@ void _init_(void)
                update_heap_memory_size(true, 0);
        }
 
-       lsan_open_liblsan();
+       lsan_init();
        process_features();
 
        PRINTMSG("dynamic analyzer probe helper so loading... pid[%d]\n",
@@ -589,7 +589,7 @@ void _uninit_(void)
 {
        int i;
 
-       lsan_close_liblsan();
+       lsan_uninit();
        cleanup_binaries();
 
        gTraceInfo.init_complete = -1;
index b5a54e9..d179512 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ulimit.h>
+#include <assert.h>
 #include "lsan_open.h"
 #include "binproto.h"
 #include "daprobe.h"
 #include "file_buffer.h"
 #include "lsan/lsan_interface.h"
 
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+
 static void *liblsan_handle;
 int lsan_init_succeeded;
 
@@ -51,6 +56,62 @@ typedef const void *(*lsan_const_void_star_fun)();
 typedef struct LeakedObject LeakedObject;
 
 
+static const char *const sym_name_table[] = {
+       /* libc interceptors */
+       "__interceptor_malloc",
+       "__interceptor_calloc",
+       "__interceptor_realloc",
+       "__interceptor_free",
+       "__interceptor_posix_memalign",
+       "__interceptor_strdup",
+
+       /* pthread interceptors */
+       "__interceptor_pthread_create",
+       "__interceptor_pthread_join",
+};
+
+static_assert(LSAN_SID_CNT == ARRAY_SIZE(sym_name_table),
+             "LSan: Incorrect table of symbol names");
+
+static void *sym_table[LSAN_SID_CNT];
+
+static bool sym_table_init(void *lsan_handle)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(sym_table); ++i) {
+               const char *sym_name = sym_name_table[i];
+               void *addr = dlsym(lsan_handle, sym_name);
+               if (addr) {
+                       PRINTMSG("Loaded LSan symbol %s at address %p",
+                                sym_name, addr);
+               } else {
+                       PRINTERR("Cannot found LSan symbol: %s", sym_name);
+                       return false;
+               }
+
+               sym_table[i] = addr;
+       }
+
+       return true;
+}
+
+static void sym_table_uninit()
+{
+       for (size_t i = 0; i < ARRAY_SIZE(sym_table); ++i)
+               sym_table[i] = NULL;
+}
+
+void *lsan_sym(enum lsan_sym_id id)
+{
+       unsigned int idx = id;
+
+       if (idx < ARRAY_SIZE(sym_table))
+               return sym_table[idx];
+
+       PRINTERR("LSan: Incorrect sym_id: %u", idx);
+       return NULL;
+}
+
+
 static size_t pack_report_msg(char *p, const char *path, size_t *path_offset)
 {
        char *msg_buf = p;
@@ -197,33 +258,43 @@ static char *get_report_file_name()
        return report_file_name;
 }
 
-int lsan_open_liblsan()
+bool lsan_init()
 {
        if (!isOptionEnabled(FL_LSAN, 0))
-               return 0;
+               return false;
 
        if (!isOptionEnabled(FL_MEMORY_ALLOC_ALWAYS_PROBING, 0)) {
                PRINTERR("lsan cannot operate "
                         "with disabled alloc always feature");
-               return 0;
+               return false;
        }
 
        liblsan_handle = dlopen(PROBELIB_LSAN, RTLD_NOW);
-       if (liblsan_handle != NULL) {
-               lsan_init_succeeded = 1;
-               send_msg_to_host("da_swap_lsan.so init done!\n",
-                                LSAN_MSG_STATUS | LSAN_INIT_DONE);
-       } else {
-               PRINTERR("Cannot open da_swap_lsan.so due to reason: %s!\n",
-                        dlerror());
+       if (liblsan_handle == NULL) {
+               PRINTERR("Cannot dlopen  due to reason: %s!",
+                        PROBELIB_LSAN, dlerror());
+               return false;
+       }
+
+       bool ret = sym_table_init(liblsan_handle);
+       if (!ret) {
+               dlclose(liblsan_handle);
+               liblsan_handle = NULL;
        }
-       return liblsan_handle != NULL;
+
+       lsan_init_succeeded = 1;
+       send_msg_to_host("da_swap_lsan.so init done!\n",
+                        LSAN_MSG_STATUS | LSAN_INIT_DONE);
+
+       return true;
 }
 
-void lsan_close_liblsan()
+void lsan_uninit()
 {
-       if (liblsan_handle)
+       if (liblsan_handle) {
+               sym_table_uninit();
                dlclose(liblsan_handle);
+       }
 }
 
 static int lsan_call_int_cb(const char *func_name)
index 84c7b21..f9cb038 100644 (file)
 
 #ifdef __cplusplus
 extern "C" {
+#else
+# include <stdbool.h>
 #endif
 
+enum lsan_sym_id {
+       /* libc symbols ID */
+       LSAN_SID_MALLOC,
+       LSAN_SID_CALLOC,
+       LSAN_SID_REALLOC,
+       LSAN_SID_FREE,
+       LSAN_SID_POSIX_MEMALIGN,
+       LSAN_SID_STRDUP,
+
+       /* pthread symbols ID */
+       LSAN_SID_PTHREAD_CREATE,
+       LSAN_SID_PTHREAD_JOIN,
+
+       /* number of symbols */
+       LSAN_SID_CNT
+};
+
 extern int lsan_init_succeeded;
 
-int lsan_open_liblsan();
-void lsan_close_liblsan();
-void *lsan_get_sym(const char *symbol_name);
+bool lsan_init();
+void lsan_uninit();
+void *lsan_sym(enum lsan_sym_id id);
 void lsan_do_leak_check();
 
+/* TODO: Deprecated function, remove it. */
+void *lsan_get_sym(const char *symbol_name);
+
 #ifdef __cplusplus
 }
 #endif
index 153aeb9..3d04412 100755 (executable)
 #include "probe_memory.h"
 #include "lsan_open.h"
 
-/* TODO Split LSan */
-enum mem_symid {
-       MEM_MALLOC,
-       MEM_CALLOC,
-       MEM_REALLOC,
-       MEM_FREE,
-       MEM_POSIX_MEMALIGN,
-       MEM_STRDUP
-};
-
-/* TODO Split LSan */
-static const char *const real_functions[] = {
-       "malloc",
-       "calloc",
-       "realloc",
-       "free",
-       "posix_memalign",
-       "strdup"
-};
-
-/* TODO Split LSan */
-static const char *const lsan_interceptors[] = {
-       "__interceptor_malloc",
-       "__interceptor_calloc",
-       "__interceptor_realloc",
-       "__interceptor_free",
-       "__interceptor_posix_memalign",
-       "__interceptor_strdup"
-};
-
-
 
 HANDLER_WRAPPERS(memory_feature, void *, malloc, size_t, size)
 {
@@ -89,7 +58,7 @@ HANDLER_WRAPPERS(memory_feature, void *, malloc, size_t, size)
        void *pret;
 
        if (lsan_init_succeeded && lsan_mallocp == NULL)
-               lsan_mallocp = lsan_get_sym(lsan_interceptors[MEM_MALLOC]);
+               lsan_mallocp = lsan_sym(LSAN_SID_MALLOC);
 
        /* If LSan is used - call LSan allocator instead of origin */
        mallocp =  lsan_init_succeeded ? lsan_mallocp :
@@ -126,7 +95,7 @@ HANDLER_WRAPPERS_VOID(memory_feature, void, free, void*, ptr)
        DECLARE_VARIABLE_STANDARD;
 
        if (lsan_init_succeeded && lsan_freep == NULL)
-               lsan_freep = lsan_get_sym(lsan_interceptors[MEM_FREE]);
+               lsan_freep = lsan_sym(LSAN_SID_FREE);
 
        /* If LSan is used - call LSan free instead of origin */
        freep = lsan_init_succeeded ? lsan_freep :
@@ -162,7 +131,7 @@ HANDLER_WRAPPERS(memory_feature, void *, realloc, void *, memblock,
        void *pret;
 
        if (lsan_init_succeeded && lsan_reallocp == NULL)
-               lsan_reallocp = lsan_get_sym(lsan_interceptors[MEM_REALLOC]);
+               lsan_reallocp = lsan_sym(LSAN_SID_REALLOC);
 
        /* If LSan is used - call LSan realloc instead of origin */
        reallocp = lsan_init_succeeded ? lsan_reallocp :
@@ -224,7 +193,7 @@ HANDLER_WRAPPERS(memory_feature, void *, calloc, size_t, nelem, size_t, elsize)
 //     }
 
        if (lsan_init_succeeded && lsan_callocp == NULL)
-               lsan_callocp = lsan_get_sym(lsan_interceptors[MEM_CALLOC]);
+               lsan_callocp = lsan_sym(LSAN_SID_CALLOC);
 
        /* If LSan is used - call LSan calloc instead of origin */
        callocp = lsan_init_succeeded ? lsan_callocp :
@@ -264,8 +233,7 @@ HANDLER_WRAPPERS(memory_feature, int, posix_memalign, void**, memptr,
        int iret;
 
        if (lsan_init_succeeded && lsan_posix_memalignp == NULL)
-               lsan_posix_memalignp = lsan_get_sym(
-                                       lsan_interceptors[MEM_POSIX_MEMALIGN]);
+               lsan_posix_memalignp = lsan_sym(LSAN_SID_POSIX_MEMALIGN);
 
        /* If LSan is used - call LSan calloc instead of origin */
        posix_memalignp = lsan_init_succeeded ?
@@ -304,7 +272,7 @@ HANDLER_WRAPPERS(memory_feature, char *, strdup, const char*, s)
        int size = strlen(s);
 
        if (lsan_init_succeeded && lsan_strdupp == NULL)
-               lsan_strdupp = lsan_get_sym(lsan_interceptors[MEM_STRDUP]);
+               lsan_strdupp = lsan_sym(LSAN_SID_STRDUP);
 
        /* If LSan is used - call LSan strdup instead of origin */
        strdupp = lsan_init_succeeded ? lsan_strdupp :
index f10e95e..8038748 100644 (file)
@@ -52,9 +52,6 @@ typedef struct thread_routine_call_t {
 void _da_cleanup_handler(void *data);
 void *_da_ThreadProc(void *params);
 
-/* TODO Split LSan */
-const char lsan_pthread_create[] = "__interceptor_pthread_create";
-const char lsan_pthread_join[] = "__interceptor_pthread_join";
 
 /* Typedef to make HANDLER_WRAPPERS macro work with func pointer */
 typedef void *(*start_routine_t)(void *);
@@ -73,7 +70,7 @@ HANDLER_WRAPPERS(thread_feature, int, pthread_create, pthread_t *, thread,
 
        DECLARE_VARIABLE_STANDARD;
        if (lsan_init_succeeded && lsan_pthread_createp == NULL)
-               lsan_pthread_createp = lsan_get_sym(lsan_pthread_create);
+               lsan_pthread_createp = lsan_sym(LSAN_SID_PTHREAD_CREATE);
 
        pthread_createp = lsan_init_succeeded ? lsan_pthread_createp :
                          (void *)PROBE_GET_FUNC(probe_data);
@@ -117,7 +114,7 @@ HANDLER_WRAPPERS(thread_feature, int , pthread_join, pthread_t, thread,
 
        DECLARE_VARIABLE_STANDARD;
        if (lsan_init_succeeded && lsan_pthread_joinp == NULL)
-               lsan_pthread_joinp = lsan_get_sym(lsan_pthread_join);
+               lsan_pthread_joinp = lsan_sym(LSAN_SID_PTHREAD_JOIN);
 
        pthread_joinp = lsan_init_succeeded ? lsan_pthread_joinp :
                        (void *)PROBE_GET_FUNC(probe_data);