mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge branch 'selftests-bpf-fixes-for-userspace-asan'
Ihor Solodrai says: ==================== selftests/bpf: Fixes for userspace ASAN This series includes various fixes aiming to enable test_progs run with userspace address sanitizer on BPF CI. The first five patches add a simplified implementation of strscpy() to selftests/bpf and then replace strcpy/strncpy usages across the tests with it. See relevant discussions [1][2]. Patch #6 fixes the selftests/bpf/test_progs build with: SAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer" The subsequent patches fix bugs reported by the address sanitizer on attempt to run the tests. [1] https://lore.kernel.org/bpf/CAADnVQ+9uw2_o388j43EWiAPdMB=3FLx2jq-9zRSvqrv-wgRag@mail.gmail.com/ [2] https://lore.kernel.org/bpf/20260220182011.802116-1-ihor.solodrai@linux.dev/ --- v3->v4: - combine strscpy and ASAN series into one (Alexei) - make the count arg of strscpy() optional via macro and fixup relevant call sites (Alexei) - remove strscpy_cat() from this series (Alexei) v3: https://lore.kernel.org/bpf/20260220222604.1155148-1-ihor.solodrai@linux.dev/ v2->v3: - rebase on top of "selftests/bpf: Add and use strscpy()" - https://lore.kernel.org/bpf/20260220182011.802116-1-ihor.solodrai@linux.dev/ - uprobe_multi_test.c: memset static struct child at the beginning of a test *and* zero out child->thread in release_child (patch #9, Mykyta) - nits in test_sysctl.c (patch #11, Eduard) - bpftool_helpers.c: update to use strscpy (patch #14, Alexei) - add __asan_on_error handler to still dump test logs even with ASAN build (patch #15, Mykyta) v2: https://lore.kernel.org/bpf/20260218003041.1156774-1-ihor.solodrai@linux.dev/ v1->v2: - rebase on bpf (v1 was targeting bpf-next) - add ASAN flag handling in selftests/bpf/Makefile (Eduard) - don't override SIGSEGV handler in test_progs with ASAN (Eduard) - add error messages in detect_bpftool_path (Mykyta) - various nits (Eduard, Jiri, Mykyta, Alexis) v1: https://lore.kernel.org/bpf/20260212011356.3266753-1-ihor.solodrai@linux.dev/ ==================== Link: https://patch.msgid.link/20260223190736.649171-1-ihor.solodrai@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
@@ -65,6 +65,9 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OU
|
||||
LIBELF_FLAGS := $(shell $(HOSTPKG_CONFIG) libelf --cflags 2>/dev/null)
|
||||
LIBELF_LIBS := $(shell $(HOSTPKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf)
|
||||
|
||||
ZLIB_LIBS := $(shell $(HOSTPKG_CONFIG) zlib --libs 2>/dev/null || echo -lz)
|
||||
ZSTD_LIBS := $(shell $(HOSTPKG_CONFIG) libzstd --libs 2>/dev/null || echo -lzstd)
|
||||
|
||||
HOSTCFLAGS_resolve_btfids += -g \
|
||||
-I$(srctree)/tools/include \
|
||||
-I$(srctree)/tools/include/uapi \
|
||||
@@ -73,7 +76,7 @@ HOSTCFLAGS_resolve_btfids += -g \
|
||||
$(LIBELF_FLAGS) \
|
||||
-Wall -Werror
|
||||
|
||||
LIBS = $(LIBELF_LIBS) -lz
|
||||
LIBS = $(LIBELF_LIBS) $(ZLIB_LIBS) $(ZSTD_LIBS)
|
||||
|
||||
export srctree OUTPUT HOSTCFLAGS_resolve_btfids Q HOSTCC HOSTLD HOSTAR
|
||||
include $(srctree)/tools/build/Makefile.include
|
||||
@@ -83,7 +86,7 @@ $(BINARY_IN): fixdep FORCE prepare | $(OUTPUT)
|
||||
|
||||
$(BINARY): $(BPFOBJ) $(SUBCMDOBJ) $(BINARY_IN)
|
||||
$(call msg,LINK,$@)
|
||||
$(Q)$(HOSTCC) $(BINARY_IN) $(KBUILD_HOSTLDFLAGS) -o $@ $(BPFOBJ) $(SUBCMDOBJ) $(LIBS)
|
||||
$(Q)$(HOSTCC) $(BINARY_IN) $(KBUILD_HOSTLDFLAGS) $(EXTRA_LDFLAGS) -o $@ $(BPFOBJ) $(SUBCMDOBJ) $(LIBS)
|
||||
|
||||
clean_objects := $(wildcard $(OUTPUT)/*.o \
|
||||
$(OUTPUT)/.*.o.cmd \
|
||||
|
||||
@@ -226,7 +226,7 @@ static struct btf_id *btf_id__find(struct rb_root *root, const char *name)
|
||||
}
|
||||
|
||||
static struct btf_id *__btf_id__add(struct rb_root *root,
|
||||
char *name,
|
||||
const char *name,
|
||||
enum btf_id_kind kind,
|
||||
bool unique)
|
||||
{
|
||||
@@ -250,7 +250,11 @@ static struct btf_id *__btf_id__add(struct rb_root *root,
|
||||
id = zalloc(sizeof(*id));
|
||||
if (id) {
|
||||
pr_debug("adding symbol %s\n", name);
|
||||
id->name = name;
|
||||
id->name = strdup(name);
|
||||
if (!id->name) {
|
||||
free(id);
|
||||
return NULL;
|
||||
}
|
||||
id->kind = kind;
|
||||
rb_link_node(&id->rb_node, parent, p);
|
||||
rb_insert_color(&id->rb_node, root);
|
||||
@@ -258,17 +262,21 @@ static struct btf_id *__btf_id__add(struct rb_root *root,
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline struct btf_id *btf_id__add(struct rb_root *root, char *name, enum btf_id_kind kind)
|
||||
static inline struct btf_id *btf_id__add(struct rb_root *root,
|
||||
const char *name,
|
||||
enum btf_id_kind kind)
|
||||
{
|
||||
return __btf_id__add(root, name, kind, false);
|
||||
}
|
||||
|
||||
static inline struct btf_id *btf_id__add_unique(struct rb_root *root, char *name, enum btf_id_kind kind)
|
||||
static inline struct btf_id *btf_id__add_unique(struct rb_root *root,
|
||||
const char *name,
|
||||
enum btf_id_kind kind)
|
||||
{
|
||||
return __btf_id__add(root, name, kind, true);
|
||||
}
|
||||
|
||||
static char *get_id(const char *prefix_end)
|
||||
static int get_id(const char *prefix_end, char *buf, size_t buf_sz)
|
||||
{
|
||||
/*
|
||||
* __BTF_ID__func__vfs_truncate__0
|
||||
@@ -277,28 +285,28 @@ static char *get_id(const char *prefix_end)
|
||||
*/
|
||||
int len = strlen(prefix_end);
|
||||
int pos = sizeof("__") - 1;
|
||||
char *p, *id;
|
||||
char *p;
|
||||
|
||||
if (pos >= len)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
id = strdup(prefix_end + pos);
|
||||
if (id) {
|
||||
/*
|
||||
* __BTF_ID__func__vfs_truncate__0
|
||||
* id = ^
|
||||
*
|
||||
* cut the unique id part
|
||||
*/
|
||||
p = strrchr(id, '_');
|
||||
p--;
|
||||
if (*p != '_') {
|
||||
free(id);
|
||||
return NULL;
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
return id;
|
||||
if (len - pos >= buf_sz)
|
||||
return -1;
|
||||
|
||||
strcpy(buf, prefix_end + pos);
|
||||
/*
|
||||
* __BTF_ID__func__vfs_truncate__0
|
||||
* buf = ^
|
||||
*
|
||||
* cut the unique id part
|
||||
*/
|
||||
p = strrchr(buf, '_');
|
||||
p--;
|
||||
if (*p != '_')
|
||||
return -1;
|
||||
*p = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_kind kind)
|
||||
@@ -335,10 +343,9 @@ static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_kind k
|
||||
|
||||
static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
|
||||
{
|
||||
char *id;
|
||||
char id[KSYM_NAME_LEN];
|
||||
|
||||
id = get_id(name + size);
|
||||
if (!id) {
|
||||
if (get_id(name + size, id, sizeof(id))) {
|
||||
pr_err("FAILED to parse symbol name: %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
@@ -346,6 +353,21 @@ static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
|
||||
return btf_id__add(root, id, BTF_ID_KIND_SYM);
|
||||
}
|
||||
|
||||
static void btf_id__free_all(struct rb_root *root)
|
||||
{
|
||||
struct rb_node *next;
|
||||
struct btf_id *id;
|
||||
|
||||
next = rb_first(root);
|
||||
while (next) {
|
||||
id = rb_entry(next, struct btf_id, rb_node);
|
||||
next = rb_next(&id->rb_node);
|
||||
rb_erase(&id->rb_node, root);
|
||||
free(id->name);
|
||||
free(id);
|
||||
}
|
||||
}
|
||||
|
||||
static void bswap_32_data(void *data, u32 nr_bytes)
|
||||
{
|
||||
u32 cnt, i;
|
||||
@@ -1547,6 +1569,11 @@ dump_btf:
|
||||
out:
|
||||
btf__free(obj.base_btf);
|
||||
btf__free(obj.btf);
|
||||
btf_id__free_all(&obj.structs);
|
||||
btf_id__free_all(&obj.unions);
|
||||
btf_id__free_all(&obj.typedefs);
|
||||
btf_id__free_all(&obj.funcs);
|
||||
btf_id__free_all(&obj.sets);
|
||||
if (obj.efile.elf) {
|
||||
elf_end(obj.efile.elf);
|
||||
close(obj.efile.fd);
|
||||
|
||||
@@ -22,7 +22,11 @@
|
||||
#define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
|
||||
/* Concatenate two parameters, but allow them to be expanded beforehand. */
|
||||
#ifndef __CONCAT
|
||||
#define __CONCAT(a, b) a ## b
|
||||
#endif
|
||||
#ifndef CONCATENATE
|
||||
#define CONCATENATE(a, b) __CONCAT(a, b)
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_ARGS_H */
|
||||
|
||||
3
tools/testing/selftests/bpf/DENYLIST.asan
Normal file
3
tools/testing/selftests/bpf/DENYLIST.asan
Normal file
@@ -0,0 +1,3 @@
|
||||
*arena*
|
||||
task_local_data
|
||||
uprobe_multi_test
|
||||
@@ -27,7 +27,11 @@ ifneq ($(wildcard $(GENHDR)),)
|
||||
endif
|
||||
|
||||
BPF_GCC ?= $(shell command -v bpf-gcc;)
|
||||
ifdef ASAN
|
||||
SAN_CFLAGS ?= -fsanitize=address -fno-omit-frame-pointer
|
||||
else
|
||||
SAN_CFLAGS ?=
|
||||
endif
|
||||
SAN_LDFLAGS ?= $(SAN_CFLAGS)
|
||||
RELEASE ?=
|
||||
OPT_FLAGS ?= $(if $(RELEASE),-O2,-O0)
|
||||
@@ -326,8 +330,8 @@ $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
|
||||
$(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
|
||||
ARCH= CROSS_COMPILE= CC="$(HOSTCC)" LD="$(HOSTLD)" \
|
||||
EXTRA_CFLAGS='-g $(OPT_FLAGS) $(EXTRA_CFLAGS)' \
|
||||
EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \
|
||||
EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS) $(EXTRA_CFLAGS)' \
|
||||
EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \
|
||||
OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
|
||||
LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
|
||||
LIBBPF_DESTDIR=$(HOST_SCRATCH_DIR)/ \
|
||||
@@ -338,8 +342,8 @@ $(CROSS_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
|
||||
$(BPFOBJ) | $(BUILD_DIR)/bpftool
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
|
||||
ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) \
|
||||
EXTRA_CFLAGS='-g $(OPT_FLAGS) $(EXTRA_CFLAGS)' \
|
||||
EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \
|
||||
EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS) $(EXTRA_CFLAGS)' \
|
||||
EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \
|
||||
OUTPUT=$(BUILD_DIR)/bpftool/ \
|
||||
LIBBPF_OUTPUT=$(BUILD_DIR)/libbpf/ \
|
||||
LIBBPF_DESTDIR=$(SCRATCH_DIR)/ \
|
||||
@@ -404,6 +408,7 @@ $(RESOLVE_BTFIDS): $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/resolve_btfids \
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/resolve_btfids \
|
||||
CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \
|
||||
LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \
|
||||
EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \
|
||||
OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ)
|
||||
|
||||
# Get Clang's default includes on this system, as opposed to those seen by
|
||||
|
||||
@@ -230,8 +230,8 @@ static void trigger_fentry_setup(void)
|
||||
static void attach_ksyms_all(struct bpf_program *empty, bool kretprobe)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
|
||||
char **syms = NULL;
|
||||
size_t cnt = 0;
|
||||
struct bpf_link *link = NULL;
|
||||
struct ksyms *ksyms = NULL;
|
||||
|
||||
/* Some recursive functions will be skipped in
|
||||
* bpf_get_ksyms -> skip_entry, as they can introduce sufficient
|
||||
@@ -241,16 +241,18 @@ static void attach_ksyms_all(struct bpf_program *empty, bool kretprobe)
|
||||
* So, don't run the kprobe-multi-all and kretprobe-multi-all on
|
||||
* a debug kernel.
|
||||
*/
|
||||
if (bpf_get_ksyms(&syms, &cnt, true)) {
|
||||
if (bpf_get_ksyms(&ksyms, true)) {
|
||||
fprintf(stderr, "failed to get ksyms\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opts.syms = (const char **) syms;
|
||||
opts.cnt = cnt;
|
||||
opts.syms = (const char **)ksyms->filtered_syms;
|
||||
opts.cnt = ksyms->filtered_cnt;
|
||||
opts.retprobe = kretprobe;
|
||||
/* attach empty to all the kernel functions except bpf_get_numa_node_id. */
|
||||
if (!bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts)) {
|
||||
link = bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts);
|
||||
free_kallsyms_local(ksyms);
|
||||
if (!link) {
|
||||
fprintf(stderr, "failed to attach bpf_program__attach_kprobe_multi_opts to all\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <errno.h>
|
||||
#include <syscall.h>
|
||||
#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
|
||||
#include <linux/args.h>
|
||||
|
||||
static inline unsigned int bpf_num_possible_cpus(void)
|
||||
{
|
||||
@@ -21,25 +22,43 @@ static inline unsigned int bpf_num_possible_cpus(void)
|
||||
return possible_cpus;
|
||||
}
|
||||
|
||||
/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst
|
||||
* is zero-terminated string no matter what (unless sz == 0, in which case
|
||||
* it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs
|
||||
* in what is returned. Given this is internal helper, it's trivial to extend
|
||||
* this, when necessary. Use this instead of strncpy inside libbpf source code.
|
||||
/*
|
||||
* Simplified strscpy() implementation. The kernel one is in lib/string.c
|
||||
*/
|
||||
static inline void bpf_strlcpy(char *dst, const char *src, size_t sz)
|
||||
static inline ssize_t sized_strscpy(char *dest, const char *src, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
long res = 0;
|
||||
|
||||
if (sz == 0)
|
||||
return;
|
||||
if (count == 0)
|
||||
return -E2BIG;
|
||||
|
||||
sz--;
|
||||
for (i = 0; i < sz && src[i]; i++)
|
||||
dst[i] = src[i];
|
||||
dst[i] = '\0';
|
||||
while (count > 1) {
|
||||
char c;
|
||||
|
||||
c = src[res];
|
||||
dest[res] = c;
|
||||
if (!c)
|
||||
return res;
|
||||
res++;
|
||||
count--;
|
||||
}
|
||||
|
||||
/* Force NUL-termination. */
|
||||
dest[res] = '\0';
|
||||
|
||||
/* Return E2BIG if the source didn't stop */
|
||||
return src[res] ? -E2BIG : res;
|
||||
}
|
||||
|
||||
#define __strscpy0(dst, src, ...) \
|
||||
sized_strscpy(dst, src, sizeof(dst))
|
||||
#define __strscpy1(dst, src, size) \
|
||||
sized_strscpy(dst, src, size)
|
||||
|
||||
#undef strscpy /* Redefine the placeholder from tools/include/linux/string.h */
|
||||
#define strscpy(dst, src, ...) \
|
||||
CONCATENATE(__strscpy, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__)
|
||||
|
||||
#define __bpf_percpu_val_align __attribute__((__aligned__(8)))
|
||||
|
||||
#define BPF_DECLARE_PERCPU(type, name) \
|
||||
|
||||
@@ -1,24 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include "bpftool_helpers.h"
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bpf_util.h"
|
||||
#include "bpftool_helpers.h"
|
||||
|
||||
#define BPFTOOL_PATH_MAX_LEN 64
|
||||
#define BPFTOOL_FULL_CMD_MAX_LEN 512
|
||||
|
||||
#define BPFTOOL_DEFAULT_PATH "tools/sbin/bpftool"
|
||||
|
||||
static int detect_bpftool_path(char *buffer)
|
||||
static int detect_bpftool_path(char *buffer, size_t size)
|
||||
{
|
||||
char tmp[BPFTOOL_PATH_MAX_LEN];
|
||||
const char *env_path;
|
||||
|
||||
/* First, check if BPFTOOL environment variable is set */
|
||||
env_path = getenv("BPFTOOL");
|
||||
if (env_path && access(env_path, X_OK) == 0) {
|
||||
strscpy(buffer, env_path, size);
|
||||
return 0;
|
||||
} else if (env_path) {
|
||||
fprintf(stderr, "bpftool '%s' doesn't exist or is not executable\n", env_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check default bpftool location (will work if we are running the
|
||||
* default flavor of test_progs)
|
||||
*/
|
||||
snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "./%s", BPFTOOL_DEFAULT_PATH);
|
||||
if (access(tmp, X_OK) == 0) {
|
||||
strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN);
|
||||
strscpy(buffer, tmp, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,11 +40,11 @@ static int detect_bpftool_path(char *buffer)
|
||||
*/
|
||||
snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "../%s", BPFTOOL_DEFAULT_PATH);
|
||||
if (access(tmp, X_OK) == 0) {
|
||||
strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN);
|
||||
strscpy(buffer, tmp, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Failed to find bpftool binary */
|
||||
fprintf(stderr, "Failed to detect bpftool path, use BPFTOOL env var to override\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -44,7 +57,7 @@ static int run_command(char *args, char *output_buf, size_t output_max_len)
|
||||
int ret;
|
||||
|
||||
/* Detect and cache bpftool binary location */
|
||||
if (bpftool_path[0] == 0 && detect_bpftool_path(bpftool_path))
|
||||
if (bpftool_path[0] == 0 && detect_bpftool_path(bpftool_path, sizeof(bpftool_path)))
|
||||
return 1;
|
||||
|
||||
ret = snprintf(command, BPFTOOL_FULL_CMD_MAX_LEN, "%s %s%s",
|
||||
|
||||
@@ -86,7 +86,7 @@ static int __enable_controllers(const char *cgroup_path, const char *controllers
|
||||
enable[len] = 0;
|
||||
close(fd);
|
||||
} else {
|
||||
bpf_strlcpy(enable, controllers, sizeof(enable));
|
||||
strscpy(enable, controllers);
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "%s/cgroup.subtree_control", cgroup_path);
|
||||
|
||||
@@ -122,15 +122,15 @@ static int disasm_one_func(FILE *text_out, uint8_t *image, __u32 len)
|
||||
pc += cnt;
|
||||
}
|
||||
qsort(labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32);
|
||||
for (i = 0; i < labels.cnt; ++i)
|
||||
/* gcc is unable to infer upper bound for labels.cnt and assumes
|
||||
* it to be U32_MAX. U32_MAX takes 10 decimal digits.
|
||||
* snprintf below prints into labels.names[*],
|
||||
* which has space only for two digits and a letter.
|
||||
* To avoid truncation warning use (i % MAX_LOCAL_LABELS),
|
||||
* which informs gcc about printed value upper bound.
|
||||
*/
|
||||
snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i % MAX_LOCAL_LABELS);
|
||||
/* gcc is unable to infer upper bound for labels.cnt and
|
||||
* assumes it to be U32_MAX. U32_MAX takes 10 decimal digits.
|
||||
* snprintf below prints into labels.names[*], which has space
|
||||
* only for two digits and a letter. To avoid truncation
|
||||
* warning use (i < MAX_LOCAL_LABELS), which informs gcc about
|
||||
* printed value upper bound.
|
||||
*/
|
||||
for (i = 0; i < labels.cnt && i < MAX_LOCAL_LABELS; ++i)
|
||||
snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i);
|
||||
|
||||
/* now print with labels */
|
||||
labels.print_phase = true;
|
||||
|
||||
@@ -432,7 +432,7 @@ int make_sockaddr(int family, const char *addr_str, __u16 port,
|
||||
memset(addr, 0, sizeof(*sun));
|
||||
sun->sun_family = family;
|
||||
sun->sun_path[0] = 0;
|
||||
strcpy(sun->sun_path + 1, addr_str);
|
||||
strscpy(sun->sun_path + 1, addr_str, sizeof(sun->sun_path) - 1);
|
||||
if (len)
|
||||
*len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str);
|
||||
return 0;
|
||||
@@ -581,8 +581,7 @@ int open_tuntap(const char *dev_name, bool need_mac)
|
||||
return -1;
|
||||
|
||||
ifr.ifr_flags = IFF_NO_PI | (need_mac ? IFF_TAP : IFF_TUN);
|
||||
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
|
||||
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
||||
strscpy(ifr.ifr_name, dev_name);
|
||||
|
||||
err = ioctl(fd, TUNSETIFF, &ifr);
|
||||
if (!ASSERT_OK(err, "ioctl(TUNSETIFF)")) {
|
||||
|
||||
@@ -346,8 +346,7 @@ static void test_task_sleepable(void)
|
||||
close(finish_pipe[1]);
|
||||
|
||||
test_data = malloc(sizeof(char) * 10);
|
||||
strncpy(test_data, "test_data", 10);
|
||||
test_data[9] = '\0';
|
||||
strscpy(test_data, "test_data", 10);
|
||||
|
||||
test_data_long = malloc(sizeof(char) * 5000);
|
||||
for (int i = 0; i < 5000; ++i) {
|
||||
|
||||
@@ -281,7 +281,7 @@ static void test_dctcp_fallback(void)
|
||||
dctcp_skel = bpf_dctcp__open();
|
||||
if (!ASSERT_OK_PTR(dctcp_skel, "dctcp_skel"))
|
||||
return;
|
||||
strcpy(dctcp_skel->rodata->fallback_cc, "cubic");
|
||||
strscpy(dctcp_skel->rodata->fallback_cc, "cubic");
|
||||
if (!ASSERT_OK(bpf_dctcp__load(dctcp_skel), "bpf_dctcp__load"))
|
||||
goto done;
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ static void test_cgroup_iter_sleepable(int cgroup_fd, __u64 cgroup_id)
|
||||
|
||||
iter_fd = bpf_iter_create(bpf_link__fd(link));
|
||||
if (!ASSERT_GE(iter_fd, 0, "iter_create"))
|
||||
goto out;
|
||||
goto out_link;
|
||||
|
||||
/* trigger the program run */
|
||||
(void)read(iter_fd, buf, sizeof(buf));
|
||||
@@ -210,6 +210,8 @@ static void test_cgroup_iter_sleepable(int cgroup_fd, __u64 cgroup_id)
|
||||
ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id");
|
||||
|
||||
close(iter_fd);
|
||||
out_link:
|
||||
bpf_link__destroy(link);
|
||||
out:
|
||||
cgrp_ls_sleepable__destroy(skel);
|
||||
}
|
||||
|
||||
@@ -308,8 +308,10 @@ static int find_field_offset(struct btf *btf, char *pattern, regmatch_t *matches
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(type_str, type, type_sz);
|
||||
strncpy(field_str, field, field_sz);
|
||||
memcpy(type_str, type, type_sz);
|
||||
type_str[type_sz] = '\0';
|
||||
memcpy(field_str, field, field_sz);
|
||||
field_str[field_sz] = '\0';
|
||||
btf_id = btf__find_by_name(btf, type_str);
|
||||
if (btf_id < 0) {
|
||||
PRINT_FAIL("No BTF info for type %s\n", type_str);
|
||||
|
||||
@@ -137,11 +137,14 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ
|
||||
);
|
||||
|
||||
link = bpf_program__attach(prog);
|
||||
if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
|
||||
if (!ASSERT_OK_PTR(link, "bpf_program__attach")) {
|
||||
bpf_object__close(obj);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = bpf_prog_test_run_opts(aux_prog_fd, &topts);
|
||||
bpf_link__destroy(link);
|
||||
bpf_object__close(obj);
|
||||
|
||||
if (!ASSERT_OK(err, "test_run"))
|
||||
goto cleanup;
|
||||
|
||||
@@ -412,8 +412,8 @@ static void check_fd_array_cnt__fd_array_too_big(void)
|
||||
ASSERT_EQ(prog_fd, -E2BIG, "prog should have been rejected with -E2BIG");
|
||||
|
||||
cleanup_fds:
|
||||
while (i > 0)
|
||||
Close(extra_fds[--i]);
|
||||
while (i-- > 0)
|
||||
Close(extra_fds[i]);
|
||||
}
|
||||
|
||||
void test_fd_array_cnt(void)
|
||||
|
||||
@@ -570,7 +570,7 @@ static int create_tap(const char *ifname)
|
||||
};
|
||||
int fd, ret;
|
||||
|
||||
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
strscpy(ifr.ifr_name, ifname);
|
||||
|
||||
fd = open("/dev/net/tun", O_RDWR);
|
||||
if (fd < 0)
|
||||
@@ -599,7 +599,7 @@ static int ifup(const char *ifname)
|
||||
struct ifreq ifr = {};
|
||||
int sk, ret;
|
||||
|
||||
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
strscpy(ifr.ifr_name, ifname);
|
||||
|
||||
sk = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sk < 0)
|
||||
|
||||
@@ -61,6 +61,7 @@ static void test_reenter_update(void)
|
||||
|
||||
ASSERT_EQ(skel->bss->update_err, -EDEADLK, "no reentrancy");
|
||||
out:
|
||||
free(value);
|
||||
htab_update__destroy(skel);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,11 +104,8 @@ void test_kmem_cache_iter(void)
|
||||
if (!ASSERT_GE(iter_fd, 0, "iter_create"))
|
||||
goto destroy;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
while (read(iter_fd, buf, sizeof(buf)) > 0) {
|
||||
/* Read out all contents */
|
||||
printf("%s", buf);
|
||||
}
|
||||
while (read(iter_fd, buf, sizeof(buf)) > 0)
|
||||
; /* Read out all contents */
|
||||
|
||||
/* Next reads should return 0 */
|
||||
ASSERT_EQ(read(iter_fd, buf, sizeof(buf)), 0, "read");
|
||||
|
||||
@@ -456,25 +456,23 @@ static void test_kprobe_multi_bench_attach(bool kernel)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
|
||||
struct kprobe_multi_empty *skel = NULL;
|
||||
char **syms = NULL;
|
||||
size_t cnt = 0;
|
||||
struct ksyms *ksyms = NULL;
|
||||
|
||||
if (!ASSERT_OK(bpf_get_ksyms(&syms, &cnt, kernel), "bpf_get_ksyms"))
|
||||
if (!ASSERT_OK(bpf_get_ksyms(&ksyms, kernel), "bpf_get_ksyms"))
|
||||
return;
|
||||
|
||||
skel = kprobe_multi_empty__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
|
||||
goto cleanup;
|
||||
|
||||
opts.syms = (const char **) syms;
|
||||
opts.cnt = cnt;
|
||||
opts.syms = (const char **)ksyms->filtered_syms;
|
||||
opts.cnt = ksyms->filtered_cnt;
|
||||
|
||||
do_bench_test(skel, &opts);
|
||||
|
||||
cleanup:
|
||||
kprobe_multi_empty__destroy(skel);
|
||||
if (syms)
|
||||
free(syms);
|
||||
free_kallsyms_local(ksyms);
|
||||
}
|
||||
|
||||
static void test_kprobe_multi_bench_attach_addr(bool kernel)
|
||||
|
||||
@@ -117,7 +117,7 @@ void test_lwt_seg6local(void)
|
||||
const char *ns1 = NETNS_BASE "1";
|
||||
const char *ns6 = NETNS_BASE "6";
|
||||
struct nstoken *nstoken = NULL;
|
||||
const char *foobar = "foobar";
|
||||
const char foobar[] = "foobar";
|
||||
ssize_t bytes;
|
||||
int sfd, cfd;
|
||||
char buf[7];
|
||||
|
||||
@@ -28,9 +28,9 @@ static void test_queue_stack_map_by_type(int type)
|
||||
vals[i] = rand();
|
||||
|
||||
if (type == QUEUE)
|
||||
strncpy(file, "./test_queue_map.bpf.o", sizeof(file));
|
||||
strscpy(file, "./test_queue_map.bpf.o");
|
||||
else if (type == STACK)
|
||||
strncpy(file, "./test_stack_map.bpf.o", sizeof(file));
|
||||
strscpy(file, "./test_stack_map.bpf.o");
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ void test_setget_sockopt(void)
|
||||
if (!ASSERT_OK_PTR(skel, "open skel"))
|
||||
goto done;
|
||||
|
||||
strcpy(skel->rodata->veth, "binddevtest1");
|
||||
strscpy(skel->rodata->veth, "binddevtest1");
|
||||
skel->rodata->veth_ifindex = if_nametoindex("binddevtest1");
|
||||
if (!ASSERT_GT(skel->rodata->veth_ifindex, 0, "if_nametoindex"))
|
||||
goto done;
|
||||
|
||||
@@ -34,7 +34,7 @@ void test_skc_to_unix_sock(void)
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
strncpy(sockaddr.sun_path, sock_path, strlen(sock_path));
|
||||
strscpy(sockaddr.sun_path, sock_path);
|
||||
sockaddr.sun_path[0] = '\0';
|
||||
|
||||
err = bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
@@ -204,7 +204,7 @@ static void test_skmsg_helpers_with_link(enum bpf_map_type map_type)
|
||||
/* Fail since bpf_link for the same prog type has been created. */
|
||||
link2 = bpf_program__attach_sockmap(prog_clone, map);
|
||||
if (!ASSERT_ERR_PTR(link2, "bpf_program__attach_sockmap")) {
|
||||
bpf_link__detach(link2);
|
||||
bpf_link__destroy(link2);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ static void test_skmsg_helpers_with_link(enum bpf_map_type map_type)
|
||||
if (!ASSERT_OK(err, "bpf_link_update"))
|
||||
goto out;
|
||||
out:
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
test_skmsg_load_helpers__destroy(skel);
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ static void test_sockmap_skb_verdict_attach_with_link(void)
|
||||
if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap"))
|
||||
goto out;
|
||||
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
|
||||
err = bpf_prog_attach(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT, 0);
|
||||
if (!ASSERT_OK(err, "bpf_prog_attach"))
|
||||
@@ -426,7 +426,7 @@ static void test_sockmap_skb_verdict_attach_with_link(void)
|
||||
/* Fail since attaching with the same prog/map has been done. */
|
||||
link = bpf_program__attach_sockmap(prog, map);
|
||||
if (!ASSERT_ERR_PTR(link, "bpf_program__attach_sockmap"))
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
|
||||
err = bpf_prog_detach2(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT);
|
||||
if (!ASSERT_OK(err, "bpf_prog_detach2"))
|
||||
@@ -747,13 +747,13 @@ static void test_sockmap_skb_verdict_peek_with_link(void)
|
||||
test_sockmap_skb_verdict_peek_helper(map);
|
||||
ASSERT_EQ(pass->bss->clone_called, 1, "clone_called");
|
||||
out:
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
test_sockmap_pass_prog__destroy(pass);
|
||||
}
|
||||
|
||||
static void test_sockmap_unconnected_unix(void)
|
||||
{
|
||||
int err, map, stream = 0, dgram = 0, zero = 0;
|
||||
int err, map, stream = -1, dgram = -1, zero = 0;
|
||||
struct test_sockmap_pass_prog *skel;
|
||||
|
||||
skel = test_sockmap_pass_prog__open_and_load();
|
||||
@@ -764,22 +764,22 @@ static void test_sockmap_unconnected_unix(void)
|
||||
|
||||
stream = xsocket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (stream < 0)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
dgram = xsocket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (dgram < 0) {
|
||||
close(stream);
|
||||
return;
|
||||
}
|
||||
if (dgram < 0)
|
||||
goto out;
|
||||
|
||||
err = bpf_map_update_elem(map, &zero, &stream, BPF_ANY);
|
||||
ASSERT_ERR(err, "bpf_map_update_elem(stream)");
|
||||
if (!ASSERT_ERR(err, "bpf_map_update_elem(stream)"))
|
||||
goto out;
|
||||
|
||||
err = bpf_map_update_elem(map, &zero, &dgram, BPF_ANY);
|
||||
ASSERT_OK(err, "bpf_map_update_elem(dgram)");
|
||||
|
||||
out:
|
||||
close(stream);
|
||||
close(dgram);
|
||||
test_sockmap_pass_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static void test_sockmap_many_socket(void)
|
||||
@@ -1027,7 +1027,7 @@ static void test_sockmap_skb_verdict_vsock_poll(void)
|
||||
if (xrecv_nonblock(conn, &buf, 1, 0) != 1)
|
||||
FAIL("xrecv_nonblock");
|
||||
detach:
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
close:
|
||||
xclose(conn);
|
||||
xclose(peer);
|
||||
|
||||
@@ -899,7 +899,7 @@ static void test_msg_redir_to_listening_with_link(struct test_sockmap_listen *sk
|
||||
|
||||
redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS);
|
||||
|
||||
bpf_link__detach(link);
|
||||
bpf_link__destroy(link);
|
||||
}
|
||||
|
||||
static void redir_partial(int family, int sotype, int sock_map, int parser_map)
|
||||
|
||||
@@ -142,7 +142,7 @@ static int getsetsockopt(void)
|
||||
|
||||
/* TCP_CONGESTION can extend the string */
|
||||
|
||||
strcpy(buf.cc, "nv");
|
||||
strscpy(buf.cc, "nv");
|
||||
err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
|
||||
if (err) {
|
||||
log_err("Failed to call setsockopt(TCP_CONGESTION)");
|
||||
|
||||
@@ -54,9 +54,7 @@ static void test_private_stack_fail(void)
|
||||
}
|
||||
|
||||
err = struct_ops_private_stack_fail__load(skel);
|
||||
if (!ASSERT_ERR(err, "struct_ops_private_stack_fail__load"))
|
||||
goto cleanup;
|
||||
return;
|
||||
ASSERT_ERR(err, "struct_ops_private_stack_fail__load");
|
||||
|
||||
cleanup:
|
||||
struct_ops_private_stack_fail__destroy(skel);
|
||||
|
||||
@@ -262,7 +262,7 @@ retry:
|
||||
if (!atomic_compare_exchange_strong(&tld_meta_p->cnt, &cnt, cnt + 1))
|
||||
goto retry;
|
||||
|
||||
strncpy(tld_meta_p->metadata[i].name, name, TLD_NAME_LEN);
|
||||
strscpy(tld_meta_p->metadata[i].name, name);
|
||||
atomic_store(&tld_meta_p->metadata[i].size, size);
|
||||
return (tld_key_t){(__s16)off};
|
||||
}
|
||||
|
||||
@@ -1360,10 +1360,8 @@ static void test_tc_opts_dev_cleanup_target(int target)
|
||||
|
||||
assert_mprog_count_ifindex(ifindex, target, 4);
|
||||
|
||||
ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth");
|
||||
ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed");
|
||||
ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed");
|
||||
return;
|
||||
goto cleanup;
|
||||
|
||||
cleanup3:
|
||||
err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
|
||||
ASSERT_OK(err, "prog_detach");
|
||||
|
||||
@@ -1095,7 +1095,7 @@ static int tun_open(char *name)
|
||||
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
if (*name)
|
||||
strncpy(ifr.ifr_name, name, IFNAMSIZ);
|
||||
strscpy(ifr.ifr_name, name);
|
||||
|
||||
err = ioctl(fd, TUNSETIFF, &ifr);
|
||||
if (!ASSERT_OK(err, "ioctl TUNSETIFF"))
|
||||
|
||||
@@ -27,6 +27,7 @@ struct sysctl_test {
|
||||
OP_EPERM,
|
||||
SUCCESS,
|
||||
} result;
|
||||
struct bpf_object *obj;
|
||||
};
|
||||
|
||||
static struct sysctl_test tests[] = {
|
||||
@@ -1471,6 +1472,7 @@ static int load_sysctl_prog_file(struct sysctl_test *test)
|
||||
return -1;
|
||||
}
|
||||
|
||||
test->obj = obj;
|
||||
return prog_fd;
|
||||
}
|
||||
|
||||
@@ -1573,6 +1575,7 @@ out:
|
||||
/* Detaching w/o checking return code: best effort attempt. */
|
||||
if (progfd != -1)
|
||||
bpf_prog_detach(cgfd, atype);
|
||||
bpf_object__close(test->obj);
|
||||
close(progfd);
|
||||
printf("[%s]\n", err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
|
||||
@@ -699,7 +699,7 @@ void test_tc_tunnel(void)
|
||||
return;
|
||||
|
||||
if (!ASSERT_OK(setup(), "global setup"))
|
||||
return;
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(subtests_cfg); i++) {
|
||||
cfg = &subtests_cfg[i];
|
||||
@@ -711,4 +711,7 @@ void test_tc_tunnel(void)
|
||||
subtest_cleanup(cfg);
|
||||
}
|
||||
cleanup();
|
||||
|
||||
out:
|
||||
test_tc_tunnel__destroy(skel);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ static struct fixture *init_fixture(void)
|
||||
|
||||
/* for no_alu32 and cpuv4 veristat is in parent folder */
|
||||
if (access("./veristat", F_OK) == 0)
|
||||
strcpy(fix->veristat, "./veristat");
|
||||
strscpy(fix->veristat, "./veristat");
|
||||
else if (access("../veristat", F_OK) == 0)
|
||||
strcpy(fix->veristat, "../veristat");
|
||||
strscpy(fix->veristat, "../veristat");
|
||||
else
|
||||
PRINT_FAIL("Can't find veristat binary");
|
||||
|
||||
|
||||
@@ -2003,9 +2003,17 @@ int testapp_stats_tx_invalid_descs(struct test_spec *test)
|
||||
|
||||
int testapp_stats_rx_full(struct test_spec *test)
|
||||
{
|
||||
if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE))
|
||||
struct pkt_stream *tmp;
|
||||
|
||||
tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE);
|
||||
if (!tmp)
|
||||
return TEST_FAILURE;
|
||||
test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
|
||||
test->ifobj_tx->xsk->pkt_stream = tmp;
|
||||
|
||||
tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
|
||||
if (!tmp)
|
||||
return TEST_FAILURE;
|
||||
test->ifobj_rx->xsk->pkt_stream = tmp;
|
||||
|
||||
test->ifobj_rx->xsk->rxqsize = DEFAULT_UMEM_BUFFERS;
|
||||
test->ifobj_rx->release_rx = false;
|
||||
@@ -2015,9 +2023,17 @@ int testapp_stats_rx_full(struct test_spec *test)
|
||||
|
||||
int testapp_stats_fill_empty(struct test_spec *test)
|
||||
{
|
||||
if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE))
|
||||
struct pkt_stream *tmp;
|
||||
|
||||
tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE);
|
||||
if (!tmp)
|
||||
return TEST_FAILURE;
|
||||
test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
|
||||
test->ifobj_tx->xsk->pkt_stream = tmp;
|
||||
|
||||
tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
|
||||
if (!tmp)
|
||||
return TEST_FAILURE;
|
||||
test->ifobj_rx->xsk->pkt_stream = tmp;
|
||||
|
||||
test->ifobj_rx->use_fill_ring = false;
|
||||
test->ifobj_rx->validation_func = validate_fill_empty;
|
||||
|
||||
@@ -62,8 +62,10 @@ static void release_child(struct child *child)
|
||||
return;
|
||||
close(child->go[1]);
|
||||
close(child->go[0]);
|
||||
if (child->thread)
|
||||
if (child->thread) {
|
||||
pthread_join(child->thread, NULL);
|
||||
child->thread = 0;
|
||||
}
|
||||
close(child->c2p[0]);
|
||||
close(child->c2p[1]);
|
||||
if (child->pid > 0)
|
||||
@@ -331,6 +333,8 @@ test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi
|
||||
{
|
||||
static struct child child;
|
||||
|
||||
memset(&child, 0, sizeof(child));
|
||||
|
||||
/* no pid filter */
|
||||
__test_attach_api(binary, pattern, opts, NULL);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ static int load_prog(struct bpf_prog_load_opts *opts, bool expect_load_error)
|
||||
static void verif_log_subtest(const char *name, bool expect_load_error, int log_level)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_prog_load_opts, opts);
|
||||
char *exp_log, prog_name[16], op_name[32];
|
||||
char *exp_log, prog_name[24], op_name[32];
|
||||
struct test_log_buf *skel;
|
||||
struct bpf_program *prog;
|
||||
size_t fixed_log_sz;
|
||||
|
||||
@@ -126,10 +126,10 @@ static int open_xsk(int ifindex, struct xsk *xsk)
|
||||
|
||||
static void close_xsk(struct xsk *xsk)
|
||||
{
|
||||
if (xsk->umem)
|
||||
xsk_umem__delete(xsk->umem);
|
||||
if (xsk->socket)
|
||||
xsk_socket__delete(xsk->socket);
|
||||
if (xsk->umem)
|
||||
xsk_umem__delete(xsk->umem);
|
||||
munmap(xsk->umem_area, UMEM_SIZE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1261,14 +1261,8 @@ int get_bpf_max_tramp_links(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_BACKTRACE_SZ 128
|
||||
void crash_handler(int signum)
|
||||
static void dump_crash_log(void)
|
||||
{
|
||||
void *bt[MAX_BACKTRACE_SZ];
|
||||
size_t sz;
|
||||
|
||||
sz = backtrace(bt, ARRAY_SIZE(bt));
|
||||
|
||||
fflush(stdout);
|
||||
stdout = env.stdout_saved;
|
||||
stderr = env.stderr_saved;
|
||||
@@ -1277,12 +1271,32 @@ void crash_handler(int signum)
|
||||
env.test_state->error_cnt++;
|
||||
dump_test_log(env.test, env.test_state, true, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_BACKTRACE_SZ 128
|
||||
|
||||
void crash_handler(int signum)
|
||||
{
|
||||
void *bt[MAX_BACKTRACE_SZ];
|
||||
size_t sz;
|
||||
|
||||
sz = backtrace(bt, ARRAY_SIZE(bt));
|
||||
|
||||
dump_crash_log();
|
||||
|
||||
if (env.worker_id != -1)
|
||||
fprintf(stderr, "[%d]: ", env.worker_id);
|
||||
fprintf(stderr, "Caught signal #%d!\nStack trace:\n", signum);
|
||||
backtrace_symbols_fd(bt, sz, STDERR_FILENO);
|
||||
}
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
void __asan_on_error(void)
|
||||
{
|
||||
dump_crash_log();
|
||||
}
|
||||
#endif
|
||||
|
||||
void hexdump(const char *prefix, const void *buf, size_t len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
@@ -1799,7 +1813,7 @@ static int worker_main_send_subtests(int sock, struct test_state *state)
|
||||
|
||||
msg.subtest_done.num = i;
|
||||
|
||||
strncpy(msg.subtest_done.name, subtest_state->name, MAX_SUBTEST_NAME);
|
||||
strscpy(msg.subtest_done.name, subtest_state->name, MAX_SUBTEST_NAME);
|
||||
|
||||
msg.subtest_done.error_cnt = subtest_state->error_cnt;
|
||||
msg.subtest_done.skipped = subtest_state->skipped;
|
||||
@@ -1944,13 +1958,15 @@ int main(int argc, char **argv)
|
||||
.parser = parse_arg,
|
||||
.doc = argp_program_doc,
|
||||
};
|
||||
int err, i;
|
||||
|
||||
#ifndef __SANITIZE_ADDRESS__
|
||||
struct sigaction sigact = {
|
||||
.sa_handler = crash_handler,
|
||||
.sa_flags = SA_RESETHAND,
|
||||
};
|
||||
int err, i;
|
||||
|
||||
};
|
||||
sigaction(SIGSEGV, &sigact, NULL);
|
||||
#endif
|
||||
|
||||
env.stdout_saved = stdout;
|
||||
env.stderr_saved = stderr;
|
||||
|
||||
@@ -1320,7 +1320,7 @@ static bool cmp_str_seq(const char *log, const char *exp)
|
||||
printf("FAIL\nTestcase bug\n");
|
||||
return false;
|
||||
}
|
||||
strncpy(needle, exp, len);
|
||||
memcpy(needle, exp, len);
|
||||
needle[len] = 0;
|
||||
q = strstr(log, needle);
|
||||
if (!q) {
|
||||
|
||||
@@ -212,6 +212,7 @@ int parse_test_list_file(const char *path,
|
||||
break;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
fclose(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
#define TRACEFS_PIPE "/sys/kernel/tracing/trace_pipe"
|
||||
#define DEBUGFS_PIPE "/sys/kernel/debug/tracing/trace_pipe"
|
||||
|
||||
struct ksyms {
|
||||
struct ksym *syms;
|
||||
size_t sym_cap;
|
||||
size_t sym_cnt;
|
||||
};
|
||||
|
||||
static struct ksyms *ksyms;
|
||||
static pthread_mutex_t ksyms_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -54,6 +48,8 @@ void free_kallsyms_local(struct ksyms *ksyms)
|
||||
if (!ksyms)
|
||||
return;
|
||||
|
||||
free(ksyms->filtered_syms);
|
||||
|
||||
if (!ksyms->syms) {
|
||||
free(ksyms);
|
||||
return;
|
||||
@@ -610,7 +606,7 @@ static int search_kallsyms_compare(const void *p1, const struct ksym *p2)
|
||||
return compare_name(p1, p2->name);
|
||||
}
|
||||
|
||||
int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
|
||||
int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel)
|
||||
{
|
||||
size_t cap = 0, cnt = 0;
|
||||
char *name = NULL, *ksym_name, **syms = NULL;
|
||||
@@ -637,8 +633,10 @@ int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
|
||||
else
|
||||
f = fopen("/sys/kernel/debug/tracing/available_filter_functions", "r");
|
||||
|
||||
if (!f)
|
||||
if (!f) {
|
||||
free_kallsyms_local(ksyms);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = hashmap__new(symbol_hash, symbol_equal, NULL);
|
||||
if (IS_ERR(map)) {
|
||||
@@ -679,15 +677,18 @@ int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
|
||||
syms[cnt++] = ksym_name;
|
||||
}
|
||||
|
||||
*symsp = syms;
|
||||
*cntp = cnt;
|
||||
ksyms->filtered_syms = syms;
|
||||
ksyms->filtered_cnt = cnt;
|
||||
*ksymsp = ksyms;
|
||||
|
||||
error:
|
||||
free(name);
|
||||
fclose(f);
|
||||
hashmap__free(map);
|
||||
if (err)
|
||||
if (err) {
|
||||
free(syms);
|
||||
free_kallsyms_local(ksyms);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,14 @@ struct ksym {
|
||||
long addr;
|
||||
char *name;
|
||||
};
|
||||
struct ksyms;
|
||||
|
||||
struct ksyms {
|
||||
struct ksym *syms;
|
||||
size_t sym_cap;
|
||||
size_t sym_cnt;
|
||||
char **filtered_syms;
|
||||
size_t filtered_cnt;
|
||||
};
|
||||
|
||||
typedef int (*ksym_cmp_t)(const void *p1, const void *p2);
|
||||
typedef int (*ksym_search_cmp_t)(const void *p1, const struct ksym *p2);
|
||||
@@ -53,7 +60,7 @@ ssize_t get_rel_offset(uintptr_t addr);
|
||||
|
||||
int read_build_id(const char *path, char *build_id, size_t size);
|
||||
|
||||
int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel);
|
||||
int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel);
|
||||
int bpf_get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3378,6 +3378,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
free(env.presets[i].atoms);
|
||||
if (env.presets[i].value.type == ENUMERATOR)
|
||||
free(env.presets[i].value.svalue);
|
||||
}
|
||||
free(env.presets);
|
||||
return -err;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <network_helpers.h>
|
||||
|
||||
#include "bpf_util.h"
|
||||
#include "xdp_features.skel.h"
|
||||
#include "xdp_features.h"
|
||||
|
||||
@@ -212,7 +213,7 @@ static void set_env_default(void)
|
||||
env.feature.drv_feature = NETDEV_XDP_ACT_NDO_XMIT;
|
||||
env.feature.action = -EINVAL;
|
||||
env.ifindex = -ENODEV;
|
||||
strcpy(env.ifname, "unknown");
|
||||
strscpy(env.ifname, "unknown");
|
||||
make_sockaddr(AF_INET6, "::ffff:127.0.0.1", DUT_CTRL_PORT,
|
||||
&env.dut_ctrl_addr, NULL);
|
||||
make_sockaddr(AF_INET6, "::ffff:127.0.0.1", DUT_ECHO_PORT,
|
||||
|
||||
@@ -550,7 +550,7 @@ static int rxq_num(const char *ifname)
|
||||
struct ifreq ifr = {
|
||||
.ifr_data = (void *)&ch,
|
||||
};
|
||||
strncpy(ifr.ifr_name, ifname, IF_NAMESIZE - 1);
|
||||
strscpy(ifr.ifr_name, ifname);
|
||||
int fd, ret;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
@@ -571,7 +571,7 @@ static void hwtstamp_ioctl(int op, const char *ifname, struct hwtstamp_config *c
|
||||
struct ifreq ifr = {
|
||||
.ifr_data = (void *)cfg,
|
||||
};
|
||||
strncpy(ifr.ifr_name, ifname, IF_NAMESIZE - 1);
|
||||
strscpy(ifr.ifr_name, ifname);
|
||||
int fd, ret;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
|
||||
Reference in New Issue
Block a user