Skip to content

Commit

Permalink
bpf-tools: Add new feature(leaksanitizer) on BPF CO-RE
Browse files Browse the repository at this point in the history
Add leaksanitizer(lsan) feature on BPF CO-RE
lsan feature originally comes from llvm-project
https://github.com/llvm/llvm-project
cvector.h comes from c-vector project
https://github.com/eteran/c-vector
uthash.h comes from uthash project
https://github.com/troydhanson/uthash
This tool detect and report dangling pointers periodically

Usage: lsan [OPTION...]
Detect memory leak resulting from dangling pointers.

Either -c or -p is a mandatory option
EXAMPLES:
    lsan -p 1234             # Detect leaks on process id 1234
    lsan -c a.out            # Detect leaks on a.out
    lsan -c 'a.out arg'      # Detect leaks on a.out with argument
    lsan -c "a.out arg"      # Detect leaks on a.out with argument

  -c, --command=COMMAND      Execute and trace the specified command
  -i, --interval=INTERVAL    Set interval in second to detect leak
  -p, --pid=PID              Set pid
  -s, --suppressions=SUPPRESSIONS
                             Suppressions file name
  -T, --top=TOP              Report only specified amount of backtraces
  -v, --verbose              Verbose debug output
  -w, --stop-the-world       Stop the world during tracing
  -?, --help                 Give this help list
      --usage                Give a short usage message
  -V, --version              Print program version

Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.

Report example:
$ sudo ./lsan -c a.out -s suppr.txt
Info: Execute child process: a.out
Info: execute command: a.out(pid 8335)

[2022-07-19 16:07:26] Print leaks:
Could not open [uprobes]
4 bytes direct leak found in 1 allocations from stack id(19863)
        #1 0x00564465ed71bf foo
        #2 0x00564465ed721b main
        #3 0x007fc0a33f7d90 __libc_init_first

[2022-07-19 16:07:36] Print leaks:
8 bytes direct leak found in 2 allocations from stack id(19863)
        #1 0x00564465ed71bf foo
        #2 0x00564465ed721b main
        #3 0x007fc0a33f7d90 __libc_init_first

[2022-07-19 16:07:46] Print leaks:
12 bytes direct leak found in 3 allocations from stack id(19863)
        #1 0x00564465ed71bf foo
        #2 0x00564465ed721b main
        #3 0x007fc0a33f7d90 __libc_init_first

Source code of test program:
\#include <stdio.h>
\#include <stdlib.h>
\#include <unistd.h>

int* foo() {
        int *tmp = malloc(sizeof(int));
        *tmp = 99;
        return tmp;
}

int* bar() {
        int *tmp = malloc(sizeof(int));
        *tmp = 22;
        return tmp;
}

int main() {
        int *a = NULL;
        while (1) {
                a = foo();
                printf("%d\n", *a);
                a = bar();
                free(a);
                sleep(10);
        }
}
  • Loading branch information
Bojun-Seo committed Jul 19, 2022
1 parent 9a5a22b commit 3473249
Show file tree
Hide file tree
Showing 6 changed files with 2,953 additions and 0 deletions.
1 change: 1 addition & 0 deletions libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ APPS = \
hardirqs \
klockstat \
ksnoop \
lsan \
llcstat \
mdflush \
mountsnoop \
Expand Down
198 changes: 198 additions & 0 deletions libbpf-tools/cvector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@

#ifndef CVECTOR_H_
#define CVECTOR_H_

#include <assert.h> /* for assert */
#include <stdlib.h> /* for malloc/realloc/free */

/**
* @brief cvector_vector_type - The vector type used in this library
*/
#define cvector_vector_type(type) type *

/**
* @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector
* @param vec - the vector
* @param size - the new capacity to set
* @return void
*/
#define cvector_set_capacity(vec, size) \
do { \
if (vec) { \
((size_t *)(vec))[-1] = (size); \
} \
} while (0)

/**
* @brief cvector_set_size - For internal use, sets the size variable of the vector
* @param vec - the vector
* @param size - the new capacity to set
* @return void
*/
#define cvector_set_size(vec, size) \
do { \
if (vec) { \
((size_t *)(vec))[-2] = (size); \
} \
} while (0)

/**
* @brief cvector_capacity - gets the current capacity of the vector
* @param vec - the vector
* @return the capacity as a size_t
*/
#define cvector_capacity(vec) \
((vec) ? ((size_t *)(vec))[-1] : (size_t)0)

/**
* @brief cvector_size - gets the current size of the vector
* @param vec - the vector
* @return the size as a size_t
*/
#define cvector_size(vec) \
((vec) ? ((size_t *)(vec))[-2] : (size_t)0)

/**
* @brief cvector_empty - returns non-zero if the vector is empty
* @param vec - the vector
* @return non-zero if empty, zero if non-empty
*/
#define cvector_empty(vec) \
(cvector_size(vec) == 0)

/**
* @brief cvector_grow - For internal use, ensures that the vector is at least <count> elements big
* @param vec - the vector
* @param count - the new capacity to set
* @return void
*/
#define cvector_grow(vec, count) \
do { \
const size_t cv_sz = (count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \
if (!(vec)) { \
size_t *cv_p = malloc(cv_sz); \
assert(cv_p); \
(vec) = (void *)(&cv_p[2]); \
cvector_set_capacity((vec), (count)); \
cvector_set_size((vec), 0); \
} else { \
size_t *cv_p1 = &((size_t *)(vec))[-2]; \
size_t *cv_p2 = realloc(cv_p1, (cv_sz)); \
assert(cv_p2); \
(vec) = (void *)(&cv_p2[2]); \
cvector_set_capacity((vec), (count)); \
} \
} while (0)

/**
* @brief cvector_pop_back - removes the last element from the vector
* @param vec - the vector
* @return void
*/
#define cvector_pop_back(vec) \
do { \
cvector_set_size((vec), cvector_size(vec) - 1); \
} while (0)

/**
* @brief cvector_erase - removes the element at index i from the vector
* @param vec - the vector
* @param i - index of element to remove
* @return void
*/
#define cvector_erase(vec, i) \
do { \
if (vec) { \
const size_t cv_sz = cvector_size(vec); \
if ((i) < cv_sz) { \
cvector_set_size((vec), cv_sz - 1); \
size_t cv_x; \
for (cv_x = (i); cv_x < (cv_sz - 1); ++cv_x) { \
(vec)[cv_x] = (vec)[cv_x + 1]; \
} \
} \
} \
} while (0)

/**
* @brief cvector_free - frees all memory associated with the vector
* @param vec - the vector
* @return void
*/
#define cvector_free(vec) \
do { \
if (vec) { \
size_t *p1 = &((size_t *)(vec))[-2]; \
free(p1); \
} \
} while (0)

/**
* @brief cvector_begin - returns an iterator to first element of the vector
* @param vec - the vector
* @return a pointer to the first element (or NULL)
*/
#define cvector_begin(vec) \
(vec)

/**
* @brief cvector_end - returns an iterator to one past the last element of the vector
* @param vec - the vector
* @return a pointer to one past the last element (or NULL)
*/
#define cvector_end(vec) \
((vec) ? &((vec)[cvector_size(vec)]) : NULL)

/* user request to use logarithmic growth algorithm */
#ifdef CVECTOR_LOGARITHMIC_GROWTH

/**
* @brief cvector_push_back - adds an element to the end of the vector
* @param vec - the vector
* @param value - the value to add
* @return void
*/
#define cvector_push_back(vec, value) \
do { \
size_t cv_cap = cvector_capacity(vec); \
if (cv_cap <= cvector_size(vec)) { \
cvector_grow((vec), !cv_cap ? cv_cap + 1 : cv_cap * 2); \
} \
vec[cvector_size(vec)] = (value); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)

#else

/**
* @brief cvector_push_back - adds an element to the end of the vector
* @param vec - the vector
* @param value - the value to add
* @return void
*/
#define cvector_push_back(vec, value) \
do { \
size_t cv_cap = cvector_capacity(vec); \
if (cv_cap <= cvector_size(vec)) { \
cvector_grow((vec), cv_cap + 1); \
} \
vec[cvector_size(vec)] = (value); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)

#endif /* CVECTOR_LOGARITHMIC_GROWTH */

/**
* @brief cvector_copy - copy a vector
* @param from - the original vector
* @param to - destination to which the function copy to
* @return void
*/
#define cvector_copy(from, to) \
do { \
for(size_t i = 0; i < cvector_size(from); i++) { \
cvector_push_back(to, from[i]); \
} \
} while (0) \

#endif /* CVECTOR_H_ */
Loading

0 comments on commit 3473249

Please sign in to comment.