Commit 5fd79ed9 authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'Fix leaks in libbpf and selftests'

Andrii Nakryiko says:

====================

Fix all the memory leaks reported by ASAN. All but one are just improper
resource clean up in selftests. But one memory leak was discovered in libbpf,
leaving inner map's name leaked.

First patch fixes selftests' Makefile by passing through SAN_CFLAGS to linker.
Without that compiling with SAN_CFLAGS=-fsanitize=address kept failing.

Running selftests under ASAN in BPF CI is the next step, we just need to make
sure all the necessary libraries (libasan and liblsan) are installed on the
host and inside the VM. Would be great to get some help with that, but for now
make sure that test_progs run is clean from leak sanitizer errors.

v3->v4:
  - rebase on latest bpf-next;
v2->v3:
  - fix per-cpu array memory leaks in btf_iter.c selftests (Hengqi);
v1->v2:
  - call bpf_map__destroy() conditionally if map->inner_map is present.
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 5577f24c 8c7a9552
......@@ -9009,7 +9009,10 @@ int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd)
pr_warn("error: inner_map_fd already specified\n");
return libbpf_err(-EINVAL);
}
zfree(&map->inner_map);
if (map->inner_map) {
bpf_map__destroy(map->inner_map);
zfree(&map->inner_map);
}
map->inner_map_fd = fd;
return 0;
}
......
......@@ -24,6 +24,7 @@ SAN_CFLAGS ?=
CFLAGS += -g -O0 -rdynamic -Wall $(GENFLAGS) $(SAN_CFLAGS) \
-I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT)
LDFLAGS += $(SAN_CFLAGS)
LDLIBS += -lcap -lelf -lz -lrt -lpthread
# Silence some warnings when compiled with clang
......
......@@ -251,18 +251,23 @@ const char *btf_type_c_dump(const struct btf *btf)
d = btf_dump__new(btf, NULL, &opts, btf_dump_printf);
if (libbpf_get_error(d)) {
fprintf(stderr, "Failed to create btf_dump instance: %ld\n", libbpf_get_error(d));
return NULL;
goto err_out;
}
for (i = 1; i < btf__type_cnt(btf); i++) {
err = btf_dump__dump_type(d, i);
if (err) {
fprintf(stderr, "Failed to dump type [%d]: %d\n", i, err);
return NULL;
goto err_out;
}
}
btf_dump__free(d);
fflush(buf_file);
fclose(buf_file);
return buf;
err_out:
btf_dump__free(d);
fclose(buf_file);
return NULL;
}
......@@ -699,14 +699,13 @@ static void test_bpf_percpu_hash_map(void)
char buf[64];
void *val;
val = malloc(8 * bpf_num_possible_cpus());
skel = bpf_iter_bpf_percpu_hash_map__open();
if (CHECK(!skel, "bpf_iter_bpf_percpu_hash_map__open",
"skeleton open failed\n"))
return;
skel->rodata->num_cpus = bpf_num_possible_cpus();
val = malloc(8 * bpf_num_possible_cpus());
err = bpf_iter_bpf_percpu_hash_map__load(skel);
if (CHECK(!skel, "bpf_iter_bpf_percpu_hash_map__load",
......@@ -770,6 +769,7 @@ static void test_bpf_percpu_hash_map(void)
bpf_link__destroy(link);
out:
bpf_iter_bpf_percpu_hash_map__destroy(skel);
free(val);
}
static void test_bpf_array_map(void)
......@@ -870,14 +870,13 @@ static void test_bpf_percpu_array_map(void)
void *val;
int len;
val = malloc(8 * bpf_num_possible_cpus());
skel = bpf_iter_bpf_percpu_array_map__open();
if (CHECK(!skel, "bpf_iter_bpf_percpu_array_map__open",
"skeleton open failed\n"))
return;
skel->rodata->num_cpus = bpf_num_possible_cpus();
val = malloc(8 * bpf_num_possible_cpus());
err = bpf_iter_bpf_percpu_array_map__load(skel);
if (CHECK(!skel, "bpf_iter_bpf_percpu_array_map__load",
......@@ -933,6 +932,7 @@ static void test_bpf_percpu_array_map(void)
bpf_link__destroy(link);
out:
bpf_iter_bpf_percpu_array_map__destroy(skel);
free(val);
}
/* An iterator program deletes all local storage in a map. */
......
......@@ -4046,11 +4046,9 @@ static void *btf_raw_create(const struct btf_header *hdr,
next_str_idx < strs_cnt ? strs_idx[next_str_idx] : NULL;
done:
free(strs_idx);
if (err) {
if (raw_btf)
free(raw_btf);
if (strs_idx)
free(strs_idx);
free(raw_btf);
return NULL;
}
return raw_btf;
......
......@@ -814,21 +814,25 @@ static void test_btf_datasec(struct btf *btf, struct btf_dump *d, char *str,
static void test_btf_dump_datasec_data(char *str)
{
struct btf *btf = btf__parse("xdping_kern.o", NULL);
struct btf *btf;
struct btf_dump_opts opts = { .ctx = str };
char license[4] = "GPL";
struct btf_dump *d;
btf = btf__parse("xdping_kern.o", NULL);
if (!ASSERT_OK_PTR(btf, "xdping_kern.o BTF not found"))
return;
d = btf_dump__new(btf, NULL, &opts, btf_dump_snprintf);
if (!ASSERT_OK_PTR(d, "could not create BTF dump"))
return;
goto out;
test_btf_datasec(btf, d, str, "license",
"SEC(\"license\") char[4] _license = (char[4])['G','P','L',];",
license, sizeof(license));
out:
btf_dump__free(d);
btf__free(btf);
}
void test_btf_dump() {
......
......@@ -433,7 +433,7 @@ static int setup_type_id_case_local(struct core_reloc_test_case *test)
static int setup_type_id_case_success(struct core_reloc_test_case *test) {
struct core_reloc_type_id_output *exp = (void *)test->output;
struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
struct btf *targ_btf;
int err;
err = setup_type_id_case_local(test);
......
......@@ -204,8 +204,8 @@ static int pass_ack(struct migrate_reuseport_test_case *test_case)
{
int err;
err = bpf_link__detach(test_case->link);
if (!ASSERT_OK(err, "bpf_link__detach"))
err = bpf_link__destroy(test_case->link);
if (!ASSERT_OK(err, "bpf_link__destroy"))
return -1;
test_case->link = NULL;
......
......@@ -111,4 +111,6 @@ void test_skb_ctx(void)
"ctx_out_mark",
"skb->mark == %u, expected %d\n",
skb.mark, 10);
bpf_object__close(obj);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment