Skip to content

Commit

Permalink
libbpf: Remove any use of reallocarray() in libbpf
Browse files Browse the repository at this point in the history
Re-implement glibc's reallocarray() for libbpf internal-only use.
reallocarray(), unfortunately, is not available in all versions of glibc, so
requires extra feature detection and using reallocarray() stub from
<tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates build
of libbpf unnecessarily and is just a maintenance burden. Instead, it's
trivial to implement libbpf-specific internal version and use it throughout
libbpf.

Which is what this patch does, along with converting some realloc() uses that
should really have been reallocarray() in the first place.

Signed-off-by: Andrii Nakryiko <[email protected]>
Signed-off-by: Alexei Starovoitov <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
anakryiko authored and Alexei Starovoitov committed Aug 19, 2020
1 parent 00b2e95 commit 029258d
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 29 deletions.
6 changes: 1 addition & 5 deletions tools/lib/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ ifndef VERBOSE
endif

FEATURE_USER = .libbpf
FEATURE_TESTS = libelf libelf-mmap zlib bpf reallocarray
FEATURE_TESTS = libelf libelf-mmap zlib bpf
FEATURE_DISPLAY = libelf zlib bpf

INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
Expand Down Expand Up @@ -102,10 +102,6 @@ ifeq ($(feature-libelf-mmap), 1)
override CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
endif

ifeq ($(feature-reallocarray), 0)
override CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
endif

# Append required CFLAGS
override CFLAGS += $(EXTRA_WARNINGS) -Wno-switch-enum
override CFLAGS += -Werror -Wall
Expand Down
11 changes: 5 additions & 6 deletions tools/lib/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
expand_by = max(btf->types_size >> 2, 16U);
new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by);

new_types = realloc(btf->types, sizeof(*new_types) * new_size);
new_types = libbpf_reallocarray(btf->types, new_size, sizeof(*new_types));
if (!new_types)
return -ENOMEM;

Expand Down Expand Up @@ -1574,7 +1574,7 @@ static int btf_dedup_hypot_map_add(struct btf_dedup *d,
__u32 *new_list;

d->hypot_cap += max((size_t)16, d->hypot_cap / 2);
new_list = realloc(d->hypot_list, sizeof(__u32) * d->hypot_cap);
new_list = libbpf_reallocarray(d->hypot_list, d->hypot_cap, sizeof(__u32));
if (!new_list)
return -ENOMEM;
d->hypot_list = new_list;
Expand Down Expand Up @@ -1870,8 +1870,7 @@ static int btf_dedup_strings(struct btf_dedup *d)
struct btf_str_ptr *new_ptrs;

strs.cap += max(strs.cnt / 2, 16U);
new_ptrs = realloc(strs.ptrs,
sizeof(strs.ptrs[0]) * strs.cap);
new_ptrs = libbpf_reallocarray(strs.ptrs, strs.cap, sizeof(strs.ptrs[0]));
if (!new_ptrs) {
err = -ENOMEM;
goto done;
Expand Down Expand Up @@ -2956,8 +2955,8 @@ static int btf_dedup_compact_types(struct btf_dedup *d)
d->btf->nr_types = next_type_id - 1;
d->btf->types_size = d->btf->nr_types;
d->btf->hdr->type_len = p - types_start;
new_types = realloc(d->btf->types,
(1 + d->btf->nr_types) * sizeof(struct btf_type *));
new_types = libbpf_reallocarray(d->btf->types, (1 + d->btf->nr_types),
sizeof(struct btf_type *));
if (!new_types)
return -ENOMEM;
d->btf->types = new_types;
Expand Down
6 changes: 2 additions & 4 deletions tools/lib/bpf/btf_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,7 @@ static int btf_dump_add_emit_queue_id(struct btf_dump *d, __u32 id)

if (d->emit_queue_cnt >= d->emit_queue_cap) {
new_cap = max(16, d->emit_queue_cap * 3 / 2);
new_queue = realloc(d->emit_queue,
new_cap * sizeof(new_queue[0]));
new_queue = libbpf_reallocarray(d->emit_queue, new_cap, sizeof(new_queue[0]));
if (!new_queue)
return -ENOMEM;
d->emit_queue = new_queue;
Expand Down Expand Up @@ -1003,8 +1002,7 @@ static int btf_dump_push_decl_stack_id(struct btf_dump *d, __u32 id)

if (d->decl_stack_cnt >= d->decl_stack_cap) {
new_cap = max(16, d->decl_stack_cap * 3 / 2);
new_stack = realloc(d->decl_stack,
new_cap * sizeof(new_stack[0]));
new_stack = libbpf_reallocarray(d->decl_stack, new_cap, sizeof(new_stack[0]));
if (!new_stack)
return -ENOMEM;
d->decl_stack = new_stack;
Expand Down
21 changes: 10 additions & 11 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#include <sys/vfs.h>
#include <sys/utsname.h>
#include <sys/resource.h>
#include <tools/libc_compat.h>
#include <libelf.h>
#include <gelf.h>
#include <zlib.h>
Expand Down Expand Up @@ -567,7 +566,7 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
progs = obj->programs;
nr_progs = obj->nr_programs;

progs = reallocarray(progs, nr_progs + 1, sizeof(progs[0]));
progs = libbpf_reallocarray(progs, nr_progs + 1, sizeof(progs[0]));
if (!progs) {
/*
* In this case the original obj->programs
Expand Down Expand Up @@ -1292,7 +1291,7 @@ static struct bpf_map *bpf_object__add_map(struct bpf_object *obj)
return &obj->maps[obj->nr_maps++];

new_cap = max((size_t)4, obj->maps_cap * 3 / 2);
new_maps = realloc(obj->maps, new_cap * sizeof(*obj->maps));
new_maps = libbpf_reallocarray(obj->maps, new_cap, sizeof(*obj->maps));
if (!new_maps) {
pr_warn("alloc maps for object failed\n");
return ERR_PTR(-ENOMEM);
Expand Down Expand Up @@ -2721,8 +2720,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
continue;
}

sects = reallocarray(sects, nr_sects + 1,
sizeof(*obj->efile.reloc_sects));
sects = libbpf_reallocarray(sects, nr_sects + 1,
sizeof(*obj->efile.reloc_sects));
if (!sects) {
pr_warn("reloc_sects realloc failed\n");
return -ENOMEM;
Expand Down Expand Up @@ -2925,7 +2924,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj)
continue;

ext = obj->externs;
ext = reallocarray(ext, obj->nr_extern + 1, sizeof(*ext));
ext = libbpf_reallocarray(ext, obj->nr_extern + 1, sizeof(*ext));
if (!ext)
return -ENOMEM;
obj->externs = ext;
Expand Down Expand Up @@ -4362,9 +4361,9 @@ static struct ids_vec *bpf_core_find_cands(const struct btf *local_btf,
pr_debug("CO-RE relocating [%d] %s %s: found target candidate [%d] %s %s\n",
local_type_id, btf_kind_str(local_t),
local_name, i, targ_kind, targ_name);
new_ids = reallocarray(cand_ids->data,
cand_ids->len + 1,
sizeof(*cand_ids->data));
new_ids = libbpf_reallocarray(cand_ids->data,
cand_ids->len + 1,
sizeof(*cand_ids->data));
if (!new_ids) {
err = -ENOMEM;
goto err_out;
Expand Down Expand Up @@ -5231,7 +5230,7 @@ bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,
return -LIBBPF_ERRNO__RELOC;
}
new_cnt = prog->insns_cnt + text->insns_cnt;
new_insn = reallocarray(prog->insns, new_cnt, sizeof(*insn));
new_insn = libbpf_reallocarray(prog->insns, new_cnt, sizeof(*insn));
if (!new_insn) {
pr_warn("oom in prog realloc\n");
return -ENOMEM;
Expand Down Expand Up @@ -5473,7 +5472,7 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj,
moff /= bpf_ptr_sz;
if (moff >= map->init_slots_sz) {
new_sz = moff + 1;
tmp = realloc(map->init_slots, new_sz * host_ptr_sz);
tmp = libbpf_reallocarray(map->init_slots, new_sz, host_ptr_sz);
if (!tmp)
return -ENOMEM;
map->init_slots = tmp;
Expand Down
25 changes: 25 additions & 0 deletions tools/lib/bpf/libbpf_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef __LIBBPF_LIBBPF_INTERNAL_H
#define __LIBBPF_LIBBPF_INTERNAL_H

#include <stdlib.h>
#include "libbpf.h"

#define BTF_INFO_ENC(kind, kind_flag, vlen) \
Expand All @@ -23,6 +24,12 @@
#define BTF_PARAM_ENC(name, type) (name), (type)
#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)

#ifndef likely
#define likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#ifndef min
# define min(x, y) ((x) < (y) ? (x) : (y))
#endif
Expand Down Expand Up @@ -63,6 +70,24 @@ do { \
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)

/*
* Re-implement glibc's reallocarray() for libbpf internal-only use.
* reallocarray(), unfortunately, is not available in all versions of glibc,
* so requires extra feature detection and using reallocarray() stub from
* <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
* build of libbpf unnecessarily and is just a maintenance burden. Instead,
* it's trivial to implement libbpf-specific internal version and use it
* throughout libbpf.
*/
static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
{
size_t total;

if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
return NULL;
return realloc(ptr, total);
}

static inline bool libbpf_validate_opts(const char *opts,
size_t opts_sz, size_t user_sz,
const char *type_name)
Expand Down
5 changes: 2 additions & 3 deletions tools/lib/bpf/ringbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <asm/barrier.h>
#include <sys/mman.h>
#include <sys/epoll.h>
#include <tools/libc_compat.h>

#include "libbpf.h"
#include "libbpf_internal.h"
Expand Down Expand Up @@ -82,12 +81,12 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
return -EINVAL;
}

tmp = reallocarray(rb->rings, rb->ring_cnt + 1, sizeof(*rb->rings));
tmp = libbpf_reallocarray(rb->rings, rb->ring_cnt + 1, sizeof(*rb->rings));
if (!tmp)
return -ENOMEM;
rb->rings = tmp;

tmp = reallocarray(rb->events, rb->ring_cnt + 1, sizeof(*rb->events));
tmp = libbpf_reallocarray(rb->events, rb->ring_cnt + 1, sizeof(*rb->events));
if (!tmp)
return -ENOMEM;
rb->events = tmp;
Expand Down

0 comments on commit 029258d

Please sign in to comment.