Commit 8feedae9 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

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: default avatarAlexei Starovoitov <ast@kernel.org>
parents 7dff99b3 4c9d0786
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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           \
+54 −27
Original line number Diff line number Diff line
@@ -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) {
	if (len - pos >= buf_sz)
		return -1;

	strcpy(buf, prefix_end + pos);
	/*
	 * __BTF_ID__func__vfs_truncate__0
		 * id =            ^
	 * buf =           ^
	 *
	 * cut the unique id part
	 */
		p = strrchr(id, '_');
	p = strrchr(buf, '_');
	p--;
		if (*p != '_') {
			free(id);
			return NULL;
		}
	if (*p != '_')
		return -1;
	*p = '\0';
	}
	return id;

	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 @@ int main(int argc, const char **argv)
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);
+4 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
*arena*
task_local_data
uprobe_multi_test
+9 −4
Original line number Diff line number Diff line
@@ -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
Loading