Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+290 -163
+5 -2
tools/bpf/resolve_btfids/Makefile
··· 65 65 LIBELF_FLAGS := $(shell $(HOSTPKG_CONFIG) libelf --cflags 2>/dev/null) 66 66 LIBELF_LIBS := $(shell $(HOSTPKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf) 67 67 68 + ZLIB_LIBS := $(shell $(HOSTPKG_CONFIG) zlib --libs 2>/dev/null || echo -lz) 69 + ZSTD_LIBS := $(shell $(HOSTPKG_CONFIG) libzstd --libs 2>/dev/null || echo -lzstd) 70 + 68 71 HOSTCFLAGS_resolve_btfids += -g \ 69 72 -I$(srctree)/tools/include \ 70 73 -I$(srctree)/tools/include/uapi \ ··· 76 73 $(LIBELF_FLAGS) \ 77 74 -Wall -Werror 78 75 79 - LIBS = $(LIBELF_LIBS) -lz 76 + LIBS = $(LIBELF_LIBS) $(ZLIB_LIBS) $(ZSTD_LIBS) 80 77 81 78 export srctree OUTPUT HOSTCFLAGS_resolve_btfids Q HOSTCC HOSTLD HOSTAR 82 79 include $(srctree)/tools/build/Makefile.include ··· 86 83 87 84 $(BINARY): $(BPFOBJ) $(SUBCMDOBJ) $(BINARY_IN) 88 85 $(call msg,LINK,$@) 89 - $(Q)$(HOSTCC) $(BINARY_IN) $(KBUILD_HOSTLDFLAGS) -o $@ $(BPFOBJ) $(SUBCMDOBJ) $(LIBS) 86 + $(Q)$(HOSTCC) $(BINARY_IN) $(KBUILD_HOSTLDFLAGS) $(EXTRA_LDFLAGS) -o $@ $(BPFOBJ) $(SUBCMDOBJ) $(LIBS) 90 87 91 88 clean_objects := $(wildcard $(OUTPUT)/*.o \ 92 89 $(OUTPUT)/.*.o.cmd \
+54 -27
tools/bpf/resolve_btfids/main.c
··· 226 226 } 227 227 228 228 static struct btf_id *__btf_id__add(struct rb_root *root, 229 - char *name, 229 + const char *name, 230 230 enum btf_id_kind kind, 231 231 bool unique) 232 232 { ··· 250 250 id = zalloc(sizeof(*id)); 251 251 if (id) { 252 252 pr_debug("adding symbol %s\n", name); 253 - id->name = name; 253 + id->name = strdup(name); 254 + if (!id->name) { 255 + free(id); 256 + return NULL; 257 + } 254 258 id->kind = kind; 255 259 rb_link_node(&id->rb_node, parent, p); 256 260 rb_insert_color(&id->rb_node, root); ··· 262 258 return id; 263 259 } 264 260 265 - static inline struct btf_id *btf_id__add(struct rb_root *root, char *name, enum btf_id_kind kind) 261 + static inline struct btf_id *btf_id__add(struct rb_root *root, 262 + const char *name, 263 + enum btf_id_kind kind) 266 264 { 267 265 return __btf_id__add(root, name, kind, false); 268 266 } 269 267 270 - static inline struct btf_id *btf_id__add_unique(struct rb_root *root, char *name, enum btf_id_kind kind) 268 + static inline struct btf_id *btf_id__add_unique(struct rb_root *root, 269 + const char *name, 270 + enum btf_id_kind kind) 271 271 { 272 272 return __btf_id__add(root, name, kind, true); 273 273 } 274 274 275 - static char *get_id(const char *prefix_end) 275 + static int get_id(const char *prefix_end, char *buf, size_t buf_sz) 276 276 { 277 277 /* 278 278 * __BTF_ID__func__vfs_truncate__0 ··· 285 277 */ 286 278 int len = strlen(prefix_end); 287 279 int pos = sizeof("__") - 1; 288 - char *p, *id; 280 + char *p; 289 281 290 282 if (pos >= len) 291 - return NULL; 283 + return -1; 292 284 293 - id = strdup(prefix_end + pos); 294 - if (id) { 295 - /* 296 - * __BTF_ID__func__vfs_truncate__0 297 - * id = ^ 298 - * 299 - * cut the unique id part 300 - */ 301 - p = strrchr(id, '_'); 302 - p--; 303 - if (*p != '_') { 304 - free(id); 305 - return NULL; 306 - } 307 - *p = '\0'; 308 - } 309 - return id; 285 + if (len - pos >= buf_sz) 286 + return -1; 287 + 288 + strcpy(buf, prefix_end + pos); 289 + /* 290 + * __BTF_ID__func__vfs_truncate__0 291 + * buf = ^ 292 + * 293 + * cut the unique id part 294 + */ 295 + p = strrchr(buf, '_'); 296 + p--; 297 + if (*p != '_') 298 + return -1; 299 + *p = '\0'; 300 + 301 + return 0; 310 302 } 311 303 312 304 static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_kind kind) ··· 343 335 344 336 static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size) 345 337 { 346 - char *id; 338 + char id[KSYM_NAME_LEN]; 347 339 348 - id = get_id(name + size); 349 - if (!id) { 340 + if (get_id(name + size, id, sizeof(id))) { 350 341 pr_err("FAILED to parse symbol name: %s\n", name); 351 342 return NULL; 352 343 } 353 344 354 345 return btf_id__add(root, id, BTF_ID_KIND_SYM); 346 + } 347 + 348 + static void btf_id__free_all(struct rb_root *root) 349 + { 350 + struct rb_node *next; 351 + struct btf_id *id; 352 + 353 + next = rb_first(root); 354 + while (next) { 355 + id = rb_entry(next, struct btf_id, rb_node); 356 + next = rb_next(&id->rb_node); 357 + rb_erase(&id->rb_node, root); 358 + free(id->name); 359 + free(id); 360 + } 355 361 } 356 362 357 363 static void bswap_32_data(void *data, u32 nr_bytes) ··· 1569 1547 out: 1570 1548 btf__free(obj.base_btf); 1571 1549 btf__free(obj.btf); 1550 + btf_id__free_all(&obj.structs); 1551 + btf_id__free_all(&obj.unions); 1552 + btf_id__free_all(&obj.typedefs); 1553 + btf_id__free_all(&obj.funcs); 1554 + btf_id__free_all(&obj.sets); 1572 1555 if (obj.efile.elf) { 1573 1556 elf_end(obj.efile.elf); 1574 1557 close(obj.efile.fd);
+4
tools/include/linux/args.h
··· 22 22 #define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 23 23 24 24 /* Concatenate two parameters, but allow them to be expanded beforehand. */ 25 + #ifndef __CONCAT 25 26 #define __CONCAT(a, b) a ## b 27 + #endif 28 + #ifndef CONCATENATE 26 29 #define CONCATENATE(a, b) __CONCAT(a, b) 30 + #endif 27 31 28 32 #endif /* _LINUX_ARGS_H */
+3
tools/testing/selftests/bpf/DENYLIST.asan
··· 1 + *arena* 2 + task_local_data 3 + uprobe_multi_test
+9 -4
tools/testing/selftests/bpf/Makefile
··· 27 27 endif 28 28 29 29 BPF_GCC ?= $(shell command -v bpf-gcc;) 30 + ifdef ASAN 31 + SAN_CFLAGS ?= -fsanitize=address -fno-omit-frame-pointer 32 + else 30 33 SAN_CFLAGS ?= 34 + endif 31 35 SAN_LDFLAGS ?= $(SAN_CFLAGS) 32 36 RELEASE ?= 33 37 OPT_FLAGS ?= $(if $(RELEASE),-O2,-O0) ··· 330 326 $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool 331 327 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ 332 328 ARCH= CROSS_COMPILE= CC="$(HOSTCC)" LD="$(HOSTLD)" \ 333 - EXTRA_CFLAGS='-g $(OPT_FLAGS) $(EXTRA_CFLAGS)' \ 334 - EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \ 329 + EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS) $(EXTRA_CFLAGS)' \ 330 + EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ 335 331 OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ 336 332 LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \ 337 333 LIBBPF_DESTDIR=$(HOST_SCRATCH_DIR)/ \ ··· 342 338 $(BPFOBJ) | $(BUILD_DIR)/bpftool 343 339 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ 344 340 ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) \ 345 - EXTRA_CFLAGS='-g $(OPT_FLAGS) $(EXTRA_CFLAGS)' \ 346 - EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \ 341 + EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS) $(EXTRA_CFLAGS)' \ 342 + EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ 347 343 OUTPUT=$(BUILD_DIR)/bpftool/ \ 348 344 LIBBPF_OUTPUT=$(BUILD_DIR)/libbpf/ \ 349 345 LIBBPF_DESTDIR=$(SCRATCH_DIR)/ \ ··· 408 404 $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/resolve_btfids \ 409 405 CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \ 410 406 LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \ 407 + EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ 411 408 OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ) 412 409 413 410 # Get Clang's default includes on this system, as opposed to those seen by
+8 -6
tools/testing/selftests/bpf/benchs/bench_trigger.c
··· 230 230 static void attach_ksyms_all(struct bpf_program *empty, bool kretprobe) 231 231 { 232 232 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 233 - char **syms = NULL; 234 - size_t cnt = 0; 233 + struct bpf_link *link = NULL; 234 + struct ksyms *ksyms = NULL; 235 235 236 236 /* Some recursive functions will be skipped in 237 237 * bpf_get_ksyms -> skip_entry, as they can introduce sufficient ··· 241 241 * So, don't run the kprobe-multi-all and kretprobe-multi-all on 242 242 * a debug kernel. 243 243 */ 244 - if (bpf_get_ksyms(&syms, &cnt, true)) { 244 + if (bpf_get_ksyms(&ksyms, true)) { 245 245 fprintf(stderr, "failed to get ksyms\n"); 246 246 exit(1); 247 247 } 248 248 249 - opts.syms = (const char **) syms; 250 - opts.cnt = cnt; 249 + opts.syms = (const char **)ksyms->filtered_syms; 250 + opts.cnt = ksyms->filtered_cnt; 251 251 opts.retprobe = kretprobe; 252 252 /* attach empty to all the kernel functions except bpf_get_numa_node_id. */ 253 - if (!bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts)) { 253 + link = bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts); 254 + free_kallsyms_local(ksyms); 255 + if (!link) { 254 256 fprintf(stderr, "failed to attach bpf_program__attach_kprobe_multi_opts to all\n"); 255 257 exit(1); 256 258 }
+32 -13
tools/testing/selftests/bpf/bpf_util.h
··· 8 8 #include <errno.h> 9 9 #include <syscall.h> 10 10 #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */ 11 + #include <linux/args.h> 11 12 12 13 static inline unsigned int bpf_num_possible_cpus(void) 13 14 { ··· 22 21 return possible_cpus; 23 22 } 24 23 25 - /* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst 26 - * is zero-terminated string no matter what (unless sz == 0, in which case 27 - * it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs 28 - * in what is returned. Given this is internal helper, it's trivial to extend 29 - * this, when necessary. Use this instead of strncpy inside libbpf source code. 24 + /* 25 + * Simplified strscpy() implementation. The kernel one is in lib/string.c 30 26 */ 31 - static inline void bpf_strlcpy(char *dst, const char *src, size_t sz) 27 + static inline ssize_t sized_strscpy(char *dest, const char *src, size_t count) 32 28 { 33 - size_t i; 29 + long res = 0; 34 30 35 - if (sz == 0) 36 - return; 31 + if (count == 0) 32 + return -E2BIG; 37 33 38 - sz--; 39 - for (i = 0; i < sz && src[i]; i++) 40 - dst[i] = src[i]; 41 - dst[i] = '\0'; 34 + while (count > 1) { 35 + char c; 36 + 37 + c = src[res]; 38 + dest[res] = c; 39 + if (!c) 40 + return res; 41 + res++; 42 + count--; 43 + } 44 + 45 + /* Force NUL-termination. */ 46 + dest[res] = '\0'; 47 + 48 + /* Return E2BIG if the source didn't stop */ 49 + return src[res] ? -E2BIG : res; 42 50 } 51 + 52 + #define __strscpy0(dst, src, ...) \ 53 + sized_strscpy(dst, src, sizeof(dst)) 54 + #define __strscpy1(dst, src, size) \ 55 + sized_strscpy(dst, src, size) 56 + 57 + #undef strscpy /* Redefine the placeholder from tools/include/linux/string.h */ 58 + #define strscpy(dst, src, ...) \ 59 + CONCATENATE(__strscpy, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__) 43 60 44 61 #define __bpf_percpu_val_align __attribute__((__aligned__(8))) 45 62
+19 -6
tools/testing/selftests/bpf/bpftool_helpers.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 - #include "bpftool_helpers.h" 3 2 #include <unistd.h> 4 3 #include <string.h> 5 4 #include <stdbool.h> 5 + 6 + #include "bpf_util.h" 7 + #include "bpftool_helpers.h" 6 8 7 9 #define BPFTOOL_PATH_MAX_LEN 64 8 10 #define BPFTOOL_FULL_CMD_MAX_LEN 512 9 11 10 12 #define BPFTOOL_DEFAULT_PATH "tools/sbin/bpftool" 11 13 12 - static int detect_bpftool_path(char *buffer) 14 + static int detect_bpftool_path(char *buffer, size_t size) 13 15 { 14 16 char tmp[BPFTOOL_PATH_MAX_LEN]; 17 + const char *env_path; 18 + 19 + /* First, check if BPFTOOL environment variable is set */ 20 + env_path = getenv("BPFTOOL"); 21 + if (env_path && access(env_path, X_OK) == 0) { 22 + strscpy(buffer, env_path, size); 23 + return 0; 24 + } else if (env_path) { 25 + fprintf(stderr, "bpftool '%s' doesn't exist or is not executable\n", env_path); 26 + return 1; 27 + } 15 28 16 29 /* Check default bpftool location (will work if we are running the 17 30 * default flavor of test_progs) 18 31 */ 19 32 snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "./%s", BPFTOOL_DEFAULT_PATH); 20 33 if (access(tmp, X_OK) == 0) { 21 - strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN); 34 + strscpy(buffer, tmp, size); 22 35 return 0; 23 36 } 24 37 ··· 40 27 */ 41 28 snprintf(tmp, BPFTOOL_PATH_MAX_LEN, "../%s", BPFTOOL_DEFAULT_PATH); 42 29 if (access(tmp, X_OK) == 0) { 43 - strncpy(buffer, tmp, BPFTOOL_PATH_MAX_LEN); 30 + strscpy(buffer, tmp, size); 44 31 return 0; 45 32 } 46 33 47 - /* Failed to find bpftool binary */ 34 + fprintf(stderr, "Failed to detect bpftool path, use BPFTOOL env var to override\n"); 48 35 return 1; 49 36 } 50 37 ··· 57 44 int ret; 58 45 59 46 /* Detect and cache bpftool binary location */ 60 - if (bpftool_path[0] == 0 && detect_bpftool_path(bpftool_path)) 47 + if (bpftool_path[0] == 0 && detect_bpftool_path(bpftool_path, sizeof(bpftool_path))) 61 48 return 1; 62 49 63 50 ret = snprintf(command, BPFTOOL_FULL_CMD_MAX_LEN, "%s %s%s",
+1 -1
tools/testing/selftests/bpf/cgroup_helpers.c
··· 86 86 enable[len] = 0; 87 87 close(fd); 88 88 } else { 89 - bpf_strlcpy(enable, controllers, sizeof(enable)); 89 + strscpy(enable, controllers); 90 90 } 91 91 92 92 snprintf(path, sizeof(path), "%s/cgroup.subtree_control", cgroup_path);
+9 -9
tools/testing/selftests/bpf/jit_disasm_helpers.c
··· 122 122 pc += cnt; 123 123 } 124 124 qsort(labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32); 125 - for (i = 0; i < labels.cnt; ++i) 126 - /* gcc is unable to infer upper bound for labels.cnt and assumes 127 - * it to be U32_MAX. U32_MAX takes 10 decimal digits. 128 - * snprintf below prints into labels.names[*], 129 - * which has space only for two digits and a letter. 130 - * To avoid truncation warning use (i % MAX_LOCAL_LABELS), 131 - * which informs gcc about printed value upper bound. 132 - */ 133 - snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i % MAX_LOCAL_LABELS); 125 + /* gcc is unable to infer upper bound for labels.cnt and 126 + * assumes it to be U32_MAX. U32_MAX takes 10 decimal digits. 127 + * snprintf below prints into labels.names[*], which has space 128 + * only for two digits and a letter. To avoid truncation 129 + * warning use (i < MAX_LOCAL_LABELS), which informs gcc about 130 + * printed value upper bound. 131 + */ 132 + for (i = 0; i < labels.cnt && i < MAX_LOCAL_LABELS; ++i) 133 + snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i); 134 134 135 135 /* now print with labels */ 136 136 labels.print_phase = true;
+2 -3
tools/testing/selftests/bpf/network_helpers.c
··· 432 432 memset(addr, 0, sizeof(*sun)); 433 433 sun->sun_family = family; 434 434 sun->sun_path[0] = 0; 435 - strcpy(sun->sun_path + 1, addr_str); 435 + strscpy(sun->sun_path + 1, addr_str, sizeof(sun->sun_path) - 1); 436 436 if (len) 437 437 *len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str); 438 438 return 0; ··· 581 581 return -1; 582 582 583 583 ifr.ifr_flags = IFF_NO_PI | (need_mac ? IFF_TAP : IFF_TUN); 584 - strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1); 585 - ifr.ifr_name[IFNAMSIZ - 1] = '\0'; 584 + strscpy(ifr.ifr_name, dev_name); 586 585 587 586 err = ioctl(fd, TUNSETIFF, &ifr); 588 587 if (!ASSERT_OK(err, "ioctl(TUNSETIFF)")) {
+1 -2
tools/testing/selftests/bpf/prog_tests/bpf_iter.c
··· 346 346 close(finish_pipe[1]); 347 347 348 348 test_data = malloc(sizeof(char) * 10); 349 - strncpy(test_data, "test_data", 10); 350 - test_data[9] = '\0'; 349 + strscpy(test_data, "test_data", 10); 351 350 352 351 test_data_long = malloc(sizeof(char) * 5000); 353 352 for (int i = 0; i < 5000; ++i) {
+1 -1
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
··· 281 281 dctcp_skel = bpf_dctcp__open(); 282 282 if (!ASSERT_OK_PTR(dctcp_skel, "dctcp_skel")) 283 283 return; 284 - strcpy(dctcp_skel->rodata->fallback_cc, "cubic"); 284 + strscpy(dctcp_skel->rodata->fallback_cc, "cubic"); 285 285 if (!ASSERT_OK(bpf_dctcp__load(dctcp_skel), "bpf_dctcp__load")) 286 286 goto done; 287 287
+3 -1
tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c
··· 202 202 203 203 iter_fd = bpf_iter_create(bpf_link__fd(link)); 204 204 if (!ASSERT_GE(iter_fd, 0, "iter_create")) 205 - goto out; 205 + goto out_link; 206 206 207 207 /* trigger the program run */ 208 208 (void)read(iter_fd, buf, sizeof(buf)); ··· 210 210 ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id"); 211 211 212 212 close(iter_fd); 213 + out_link: 214 + bpf_link__destroy(link); 213 215 out: 214 216 cgrp_ls_sleepable__destroy(skel); 215 217 }
+4 -2
tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
··· 308 308 return -1; 309 309 } 310 310 311 - strncpy(type_str, type, type_sz); 312 - strncpy(field_str, field, field_sz); 311 + memcpy(type_str, type, type_sz); 312 + type_str[type_sz] = '\0'; 313 + memcpy(field_str, field, field_sz); 314 + field_str[field_sz] = '\0'; 313 315 btf_id = btf__find_by_name(btf, type_str); 314 316 if (btf_id < 0) { 315 317 PRINT_FAIL("No BTF info for type %s\n", type_str);
+4 -1
tools/testing/selftests/bpf/prog_tests/dynptr.c
··· 137 137 ); 138 138 139 139 link = bpf_program__attach(prog); 140 - if (!ASSERT_OK_PTR(link, "bpf_program__attach")) 140 + if (!ASSERT_OK_PTR(link, "bpf_program__attach")) { 141 + bpf_object__close(obj); 141 142 goto cleanup; 143 + } 142 144 143 145 err = bpf_prog_test_run_opts(aux_prog_fd, &topts); 144 146 bpf_link__destroy(link); 147 + bpf_object__close(obj); 145 148 146 149 if (!ASSERT_OK(err, "test_run")) 147 150 goto cleanup;
+2 -2
tools/testing/selftests/bpf/prog_tests/fd_array.c
··· 412 412 ASSERT_EQ(prog_fd, -E2BIG, "prog should have been rejected with -E2BIG"); 413 413 414 414 cleanup_fds: 415 - while (i > 0) 416 - Close(extra_fds[--i]); 415 + while (i-- > 0) 416 + Close(extra_fds[i]); 417 417 } 418 418 419 419 void test_fd_array_cnt(void)
+2 -2
tools/testing/selftests/bpf/prog_tests/flow_dissector.c
··· 570 570 }; 571 571 int fd, ret; 572 572 573 - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 573 + strscpy(ifr.ifr_name, ifname); 574 574 575 575 fd = open("/dev/net/tun", O_RDWR); 576 576 if (fd < 0) ··· 599 599 struct ifreq ifr = {}; 600 600 int sk, ret; 601 601 602 - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 602 + strscpy(ifr.ifr_name, ifname); 603 603 604 604 sk = socket(PF_INET, SOCK_DGRAM, 0); 605 605 if (sk < 0)
+1
tools/testing/selftests/bpf/prog_tests/htab_update.c
··· 61 61 62 62 ASSERT_EQ(skel->bss->update_err, -EDEADLK, "no reentrancy"); 63 63 out: 64 + free(value); 64 65 htab_update__destroy(skel); 65 66 } 66 67
+2 -5
tools/testing/selftests/bpf/prog_tests/kmem_cache_iter.c
··· 104 104 if (!ASSERT_GE(iter_fd, 0, "iter_create")) 105 105 goto destroy; 106 106 107 - memset(buf, 0, sizeof(buf)); 108 - while (read(iter_fd, buf, sizeof(buf)) > 0) { 109 - /* Read out all contents */ 110 - printf("%s", buf); 111 - } 107 + while (read(iter_fd, buf, sizeof(buf)) > 0) 108 + ; /* Read out all contents */ 112 109 113 110 /* Next reads should return 0 */ 114 111 ASSERT_EQ(read(iter_fd, buf, sizeof(buf)), 0, "read");
+5 -7
tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
··· 456 456 { 457 457 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 458 458 struct kprobe_multi_empty *skel = NULL; 459 - char **syms = NULL; 460 - size_t cnt = 0; 459 + struct ksyms *ksyms = NULL; 461 460 462 - if (!ASSERT_OK(bpf_get_ksyms(&syms, &cnt, kernel), "bpf_get_ksyms")) 461 + if (!ASSERT_OK(bpf_get_ksyms(&ksyms, kernel), "bpf_get_ksyms")) 463 462 return; 464 463 465 464 skel = kprobe_multi_empty__open_and_load(); 466 465 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 467 466 goto cleanup; 468 467 469 - opts.syms = (const char **) syms; 470 - opts.cnt = cnt; 468 + opts.syms = (const char **)ksyms->filtered_syms; 469 + opts.cnt = ksyms->filtered_cnt; 471 470 472 471 do_bench_test(skel, &opts); 473 472 474 473 cleanup: 475 474 kprobe_multi_empty__destroy(skel); 476 - if (syms) 477 - free(syms); 475 + free_kallsyms_local(ksyms); 478 476 } 479 477 480 478 static void test_kprobe_multi_bench_attach_addr(bool kernel)
+1 -1
tools/testing/selftests/bpf/prog_tests/lwt_seg6local.c
··· 117 117 const char *ns1 = NETNS_BASE "1"; 118 118 const char *ns6 = NETNS_BASE "6"; 119 119 struct nstoken *nstoken = NULL; 120 - const char *foobar = "foobar"; 120 + const char foobar[] = "foobar"; 121 121 ssize_t bytes; 122 122 int sfd, cfd; 123 123 char buf[7];
+2 -2
tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
··· 28 28 vals[i] = rand(); 29 29 30 30 if (type == QUEUE) 31 - strncpy(file, "./test_queue_map.bpf.o", sizeof(file)); 31 + strscpy(file, "./test_queue_map.bpf.o"); 32 32 else if (type == STACK) 33 - strncpy(file, "./test_stack_map.bpf.o", sizeof(file)); 33 + strscpy(file, "./test_stack_map.bpf.o"); 34 34 else 35 35 return; 36 36
+1 -1
tools/testing/selftests/bpf/prog_tests/setget_sockopt.c
··· 212 212 if (!ASSERT_OK_PTR(skel, "open skel")) 213 213 goto done; 214 214 215 - strcpy(skel->rodata->veth, "binddevtest1"); 215 + strscpy(skel->rodata->veth, "binddevtest1"); 216 216 skel->rodata->veth_ifindex = if_nametoindex("binddevtest1"); 217 217 if (!ASSERT_GT(skel->rodata->veth_ifindex, 0, "if_nametoindex")) 218 218 goto done;
+1 -1
tools/testing/selftests/bpf/prog_tests/skc_to_unix_sock.c
··· 34 34 35 35 memset(&sockaddr, 0, sizeof(sockaddr)); 36 36 sockaddr.sun_family = AF_UNIX; 37 - strncpy(sockaddr.sun_path, sock_path, strlen(sock_path)); 37 + strscpy(sockaddr.sun_path, sock_path); 38 38 sockaddr.sun_path[0] = '\0'; 39 39 40 40 err = bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+14 -14
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
··· 204 204 /* Fail since bpf_link for the same prog type has been created. */ 205 205 link2 = bpf_program__attach_sockmap(prog_clone, map); 206 206 if (!ASSERT_ERR_PTR(link2, "bpf_program__attach_sockmap")) { 207 - bpf_link__detach(link2); 207 + bpf_link__destroy(link2); 208 208 goto out; 209 209 } 210 210 ··· 230 230 if (!ASSERT_OK(err, "bpf_link_update")) 231 231 goto out; 232 232 out: 233 - bpf_link__detach(link); 233 + bpf_link__destroy(link); 234 234 test_skmsg_load_helpers__destroy(skel); 235 235 } 236 236 ··· 417 417 if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap")) 418 418 goto out; 419 419 420 - bpf_link__detach(link); 420 + bpf_link__destroy(link); 421 421 422 422 err = bpf_prog_attach(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT, 0); 423 423 if (!ASSERT_OK(err, "bpf_prog_attach")) ··· 426 426 /* Fail since attaching with the same prog/map has been done. */ 427 427 link = bpf_program__attach_sockmap(prog, map); 428 428 if (!ASSERT_ERR_PTR(link, "bpf_program__attach_sockmap")) 429 - bpf_link__detach(link); 429 + bpf_link__destroy(link); 430 430 431 431 err = bpf_prog_detach2(bpf_program__fd(prog), map, BPF_SK_SKB_STREAM_VERDICT); 432 432 if (!ASSERT_OK(err, "bpf_prog_detach2")) ··· 747 747 test_sockmap_skb_verdict_peek_helper(map); 748 748 ASSERT_EQ(pass->bss->clone_called, 1, "clone_called"); 749 749 out: 750 - bpf_link__detach(link); 750 + bpf_link__destroy(link); 751 751 test_sockmap_pass_prog__destroy(pass); 752 752 } 753 753 754 754 static void test_sockmap_unconnected_unix(void) 755 755 { 756 - int err, map, stream = 0, dgram = 0, zero = 0; 756 + int err, map, stream = -1, dgram = -1, zero = 0; 757 757 struct test_sockmap_pass_prog *skel; 758 758 759 759 skel = test_sockmap_pass_prog__open_and_load(); ··· 764 764 765 765 stream = xsocket(AF_UNIX, SOCK_STREAM, 0); 766 766 if (stream < 0) 767 - return; 767 + goto out; 768 768 769 769 dgram = xsocket(AF_UNIX, SOCK_DGRAM, 0); 770 - if (dgram < 0) { 771 - close(stream); 772 - return; 773 - } 770 + if (dgram < 0) 771 + goto out; 774 772 775 773 err = bpf_map_update_elem(map, &zero, &stream, BPF_ANY); 776 - ASSERT_ERR(err, "bpf_map_update_elem(stream)"); 774 + if (!ASSERT_ERR(err, "bpf_map_update_elem(stream)")) 775 + goto out; 777 776 778 777 err = bpf_map_update_elem(map, &zero, &dgram, BPF_ANY); 779 778 ASSERT_OK(err, "bpf_map_update_elem(dgram)"); 780 - 779 + out: 781 780 close(stream); 782 781 close(dgram); 782 + test_sockmap_pass_prog__destroy(skel); 783 783 } 784 784 785 785 static void test_sockmap_many_socket(void) ··· 1027 1027 if (xrecv_nonblock(conn, &buf, 1, 0) != 1) 1028 1028 FAIL("xrecv_nonblock"); 1029 1029 detach: 1030 - bpf_link__detach(link); 1030 + bpf_link__destroy(link); 1031 1031 close: 1032 1032 xclose(conn); 1033 1033 xclose(peer);
+1 -1
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
··· 899 899 900 900 redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 901 901 902 - bpf_link__detach(link); 902 + bpf_link__destroy(link); 903 903 } 904 904 905 905 static void redir_partial(int family, int sotype, int sock_map, int parser_map)
+1 -1
tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
··· 142 142 143 143 /* TCP_CONGESTION can extend the string */ 144 144 145 - strcpy(buf.cc, "nv"); 145 + strscpy(buf.cc, "nv"); 146 146 err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv")); 147 147 if (err) { 148 148 log_err("Failed to call setsockopt(TCP_CONGESTION)");
+1 -3
tools/testing/selftests/bpf/prog_tests/struct_ops_private_stack.c
··· 54 54 } 55 55 56 56 err = struct_ops_private_stack_fail__load(skel); 57 - if (!ASSERT_ERR(err, "struct_ops_private_stack_fail__load")) 58 - goto cleanup; 59 - return; 57 + ASSERT_ERR(err, "struct_ops_private_stack_fail__load"); 60 58 61 59 cleanup: 62 60 struct_ops_private_stack_fail__destroy(skel);
+1 -1
tools/testing/selftests/bpf/prog_tests/task_local_data.h
··· 262 262 if (!atomic_compare_exchange_strong(&tld_meta_p->cnt, &cnt, cnt + 1)) 263 263 goto retry; 264 264 265 - strncpy(tld_meta_p->metadata[i].name, name, TLD_NAME_LEN); 265 + strscpy(tld_meta_p->metadata[i].name, name); 266 266 atomic_store(&tld_meta_p->metadata[i].size, size); 267 267 return (tld_key_t){(__s16)off}; 268 268 }
+2 -4
tools/testing/selftests/bpf/prog_tests/tc_opts.c
··· 1360 1360 1361 1361 assert_mprog_count_ifindex(ifindex, target, 4); 1362 1362 1363 - ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); 1364 - ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); 1365 - ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); 1366 - return; 1363 + goto cleanup; 1364 + 1367 1365 cleanup3: 1368 1366 err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1369 1367 ASSERT_OK(err, "prog_detach");
+1 -1
tools/testing/selftests/bpf/prog_tests/tc_redirect.c
··· 1095 1095 1096 1096 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 1097 1097 if (*name) 1098 - strncpy(ifr.ifr_name, name, IFNAMSIZ); 1098 + strscpy(ifr.ifr_name, name); 1099 1099 1100 1100 err = ioctl(fd, TUNSETIFF, &ifr); 1101 1101 if (!ASSERT_OK(err, "ioctl TUNSETIFF"))
+3
tools/testing/selftests/bpf/prog_tests/test_sysctl.c
··· 27 27 OP_EPERM, 28 28 SUCCESS, 29 29 } result; 30 + struct bpf_object *obj; 30 31 }; 31 32 32 33 static struct sysctl_test tests[] = { ··· 1472 1471 return -1; 1473 1472 } 1474 1473 1474 + test->obj = obj; 1475 1475 return prog_fd; 1476 1476 } 1477 1477 ··· 1575 1573 /* Detaching w/o checking return code: best effort attempt. */ 1576 1574 if (progfd != -1) 1577 1575 bpf_prog_detach(cgfd, atype); 1576 + bpf_object__close(test->obj); 1578 1577 close(progfd); 1579 1578 printf("[%s]\n", err ? "FAIL" : "PASS"); 1580 1579 return err;
+4 -1
tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
··· 699 699 return; 700 700 701 701 if (!ASSERT_OK(setup(), "global setup")) 702 - return; 702 + goto out; 703 703 704 704 for (i = 0; i < ARRAY_SIZE(subtests_cfg); i++) { 705 705 cfg = &subtests_cfg[i]; ··· 711 711 subtest_cleanup(cfg); 712 712 } 713 713 cleanup(); 714 + 715 + out: 716 + test_tc_tunnel__destroy(skel); 714 717 }
+2 -2
tools/testing/selftests/bpf/prog_tests/test_veristat.c
··· 24 24 25 25 /* for no_alu32 and cpuv4 veristat is in parent folder */ 26 26 if (access("./veristat", F_OK) == 0) 27 - strcpy(fix->veristat, "./veristat"); 27 + strscpy(fix->veristat, "./veristat"); 28 28 else if (access("../veristat", F_OK) == 0) 29 - strcpy(fix->veristat, "../veristat"); 29 + strscpy(fix->veristat, "../veristat"); 30 30 else 31 31 PRINT_FAIL("Can't find veristat binary"); 32 32
+20 -4
tools/testing/selftests/bpf/prog_tests/test_xsk.c
··· 2003 2003 2004 2004 int testapp_stats_rx_full(struct test_spec *test) 2005 2005 { 2006 - if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE)) 2006 + struct pkt_stream *tmp; 2007 + 2008 + tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE); 2009 + if (!tmp) 2007 2010 return TEST_FAILURE; 2008 - test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2011 + test->ifobj_tx->xsk->pkt_stream = tmp; 2012 + 2013 + tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2014 + if (!tmp) 2015 + return TEST_FAILURE; 2016 + test->ifobj_rx->xsk->pkt_stream = tmp; 2009 2017 2010 2018 test->ifobj_rx->xsk->rxqsize = DEFAULT_UMEM_BUFFERS; 2011 2019 test->ifobj_rx->release_rx = false; ··· 2023 2015 2024 2016 int testapp_stats_fill_empty(struct test_spec *test) 2025 2017 { 2026 - if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE)) 2018 + struct pkt_stream *tmp; 2019 + 2020 + tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE); 2021 + if (!tmp) 2027 2022 return TEST_FAILURE; 2028 - test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2023 + test->ifobj_tx->xsk->pkt_stream = tmp; 2024 + 2025 + tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2026 + if (!tmp) 2027 + return TEST_FAILURE; 2028 + test->ifobj_rx->xsk->pkt_stream = tmp; 2029 2029 2030 2030 test->ifobj_rx->use_fill_ring = false; 2031 2031 test->ifobj_rx->validation_func = validate_fill_empty;
+5 -1
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
··· 62 62 return; 63 63 close(child->go[1]); 64 64 close(child->go[0]); 65 - if (child->thread) 65 + if (child->thread) { 66 66 pthread_join(child->thread, NULL); 67 + child->thread = 0; 68 + } 67 69 close(child->c2p[0]); 68 70 close(child->c2p[1]); 69 71 if (child->pid > 0) ··· 332 330 test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts) 333 331 { 334 332 static struct child child; 333 + 334 + memset(&child, 0, sizeof(child)); 335 335 336 336 /* no pid filter */ 337 337 __test_attach_api(binary, pattern, opts, NULL);
+1 -1
tools/testing/selftests/bpf/prog_tests/verifier_log.c
··· 47 47 static void verif_log_subtest(const char *name, bool expect_load_error, int log_level) 48 48 { 49 49 LIBBPF_OPTS(bpf_prog_load_opts, opts); 50 - char *exp_log, prog_name[16], op_name[32]; 50 + char *exp_log, prog_name[24], op_name[32]; 51 51 struct test_log_buf *skel; 52 52 struct bpf_program *prog; 53 53 size_t fixed_log_sz;
+2 -2
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
··· 126 126 127 127 static void close_xsk(struct xsk *xsk) 128 128 { 129 - if (xsk->umem) 130 - xsk_umem__delete(xsk->umem); 131 129 if (xsk->socket) 132 130 xsk_socket__delete(xsk->socket); 131 + if (xsk->umem) 132 + xsk_umem__delete(xsk->umem); 133 133 munmap(xsk->umem_area, UMEM_SIZE); 134 134 } 135 135
+27 -11
tools/testing/selftests/bpf/test_progs.c
··· 1261 1261 return ret; 1262 1262 } 1263 1263 1264 - #define MAX_BACKTRACE_SZ 128 1265 - void crash_handler(int signum) 1264 + static void dump_crash_log(void) 1266 1265 { 1267 - void *bt[MAX_BACKTRACE_SZ]; 1268 - size_t sz; 1269 - 1270 - sz = backtrace(bt, ARRAY_SIZE(bt)); 1271 - 1272 1266 fflush(stdout); 1273 1267 stdout = env.stdout_saved; 1274 1268 stderr = env.stderr_saved; ··· 1271 1277 env.test_state->error_cnt++; 1272 1278 dump_test_log(env.test, env.test_state, true, false, NULL); 1273 1279 } 1280 + } 1281 + 1282 + #define MAX_BACKTRACE_SZ 128 1283 + 1284 + void crash_handler(int signum) 1285 + { 1286 + void *bt[MAX_BACKTRACE_SZ]; 1287 + size_t sz; 1288 + 1289 + sz = backtrace(bt, ARRAY_SIZE(bt)); 1290 + 1291 + dump_crash_log(); 1292 + 1274 1293 if (env.worker_id != -1) 1275 1294 fprintf(stderr, "[%d]: ", env.worker_id); 1276 1295 fprintf(stderr, "Caught signal #%d!\nStack trace:\n", signum); 1277 1296 backtrace_symbols_fd(bt, sz, STDERR_FILENO); 1278 1297 } 1298 + 1299 + #ifdef __SANITIZE_ADDRESS__ 1300 + void __asan_on_error(void) 1301 + { 1302 + dump_crash_log(); 1303 + } 1304 + #endif 1279 1305 1280 1306 void hexdump(const char *prefix, const void *buf, size_t len) 1281 1307 { ··· 1813 1799 1814 1800 msg.subtest_done.num = i; 1815 1801 1816 - strncpy(msg.subtest_done.name, subtest_state->name, MAX_SUBTEST_NAME); 1802 + strscpy(msg.subtest_done.name, subtest_state->name, MAX_SUBTEST_NAME); 1817 1803 1818 1804 msg.subtest_done.error_cnt = subtest_state->error_cnt; 1819 1805 msg.subtest_done.skipped = subtest_state->skipped; ··· 1958 1944 .parser = parse_arg, 1959 1945 .doc = argp_program_doc, 1960 1946 }; 1947 + int err, i; 1948 + 1949 + #ifndef __SANITIZE_ADDRESS__ 1961 1950 struct sigaction sigact = { 1962 1951 .sa_handler = crash_handler, 1963 1952 .sa_flags = SA_RESETHAND, 1964 - }; 1965 - int err, i; 1966 - 1953 + }; 1967 1954 sigaction(SIGSEGV, &sigact, NULL); 1955 + #endif 1968 1956 1969 1957 env.stdout_saved = stdout; 1970 1958 env.stderr_saved = stderr;
+1 -1
tools/testing/selftests/bpf/test_verifier.c
··· 1320 1320 printf("FAIL\nTestcase bug\n"); 1321 1321 return false; 1322 1322 } 1323 - strncpy(needle, exp, len); 1323 + memcpy(needle, exp, len); 1324 1324 needle[len] = 0; 1325 1325 q = strstr(log, needle); 1326 1326 if (!q) {
+1
tools/testing/selftests/bpf/testing_helpers.c
··· 212 212 break; 213 213 } 214 214 215 + free(buf); 215 216 fclose(f); 216 217 return err; 217 218 }
+12 -11
tools/testing/selftests/bpf/trace_helpers.c
··· 24 24 #define TRACEFS_PIPE "/sys/kernel/tracing/trace_pipe" 25 25 #define DEBUGFS_PIPE "/sys/kernel/debug/tracing/trace_pipe" 26 26 27 - struct ksyms { 28 - struct ksym *syms; 29 - size_t sym_cap; 30 - size_t sym_cnt; 31 - }; 32 - 33 27 static struct ksyms *ksyms; 34 28 static pthread_mutex_t ksyms_mutex = PTHREAD_MUTEX_INITIALIZER; 35 29 ··· 47 53 48 54 if (!ksyms) 49 55 return; 56 + 57 + free(ksyms->filtered_syms); 50 58 51 59 if (!ksyms->syms) { 52 60 free(ksyms); ··· 606 610 return compare_name(p1, p2->name); 607 611 } 608 612 609 - int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel) 613 + int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel) 610 614 { 611 615 size_t cap = 0, cnt = 0; 612 616 char *name = NULL, *ksym_name, **syms = NULL; ··· 633 637 else 634 638 f = fopen("/sys/kernel/debug/tracing/available_filter_functions", "r"); 635 639 636 - if (!f) 640 + if (!f) { 641 + free_kallsyms_local(ksyms); 637 642 return -EINVAL; 643 + } 638 644 639 645 map = hashmap__new(symbol_hash, symbol_equal, NULL); 640 646 if (IS_ERR(map)) { ··· 677 679 syms[cnt++] = ksym_name; 678 680 } 679 681 680 - *symsp = syms; 681 - *cntp = cnt; 682 + ksyms->filtered_syms = syms; 683 + ksyms->filtered_cnt = cnt; 684 + *ksymsp = ksyms; 682 685 683 686 error: 684 687 free(name); 685 688 fclose(f); 686 689 hashmap__free(map); 687 - if (err) 690 + if (err) { 688 691 free(syms); 692 + free_kallsyms_local(ksyms); 693 + } 689 694 return err; 690 695 } 691 696
+9 -2
tools/testing/selftests/bpf/trace_helpers.h
··· 23 23 long addr; 24 24 char *name; 25 25 }; 26 - struct ksyms; 26 + 27 + struct ksyms { 28 + struct ksym *syms; 29 + size_t sym_cap; 30 + size_t sym_cnt; 31 + char **filtered_syms; 32 + size_t filtered_cnt; 33 + }; 27 34 28 35 typedef int (*ksym_cmp_t)(const void *p1, const void *p2); 29 36 typedef int (*ksym_search_cmp_t)(const void *p1, const struct ksym *p2); ··· 60 53 61 54 int read_build_id(const char *path, char *build_id, size_t size); 62 55 63 - int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel); 56 + int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel); 64 57 int bpf_get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel); 65 58 66 59 #endif
+2
tools/testing/selftests/bpf/veristat.c
··· 3378 3378 } 3379 3379 } 3380 3380 free(env.presets[i].atoms); 3381 + if (env.presets[i].value.type == ENUMERATOR) 3382 + free(env.presets[i].value.svalue); 3381 3383 } 3382 3384 free(env.presets); 3383 3385 return -err;
+2 -1
tools/testing/selftests/bpf/xdp_features.c
··· 16 16 17 17 #include <network_helpers.h> 18 18 19 + #include "bpf_util.h" 19 20 #include "xdp_features.skel.h" 20 21 #include "xdp_features.h" 21 22 ··· 213 212 env.feature.drv_feature = NETDEV_XDP_ACT_NDO_XMIT; 214 213 env.feature.action = -EINVAL; 215 214 env.ifindex = -ENODEV; 216 - strcpy(env.ifname, "unknown"); 215 + strscpy(env.ifname, "unknown"); 217 216 make_sockaddr(AF_INET6, "::ffff:127.0.0.1", DUT_CTRL_PORT, 218 217 &env.dut_ctrl_addr, NULL); 219 218 make_sockaddr(AF_INET6, "::ffff:127.0.0.1", DUT_ECHO_PORT,
+2 -2
tools/testing/selftests/bpf/xdp_hw_metadata.c
··· 550 550 struct ifreq ifr = { 551 551 .ifr_data = (void *)&ch, 552 552 }; 553 - strncpy(ifr.ifr_name, ifname, IF_NAMESIZE - 1); 553 + strscpy(ifr.ifr_name, ifname); 554 554 int fd, ret; 555 555 556 556 fd = socket(AF_UNIX, SOCK_DGRAM, 0); ··· 571 571 struct ifreq ifr = { 572 572 .ifr_data = (void *)cfg, 573 573 }; 574 - strncpy(ifr.ifr_name, ifname, IF_NAMESIZE - 1); 574 + strscpy(ifr.ifr_name, ifname); 575 575 int fd, ret; 576 576 577 577 fd = socket(AF_UNIX, SOCK_DGRAM, 0);