diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index feb5bd54d840..b1c3227ae4ab 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -197,9 +197,9 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) { struct xdp_umem *umem = rx_ring->xsk_umem; int err, result = I40E_XDP_PASS; - u64 offset = umem->headroom; struct i40e_ring *xdp_ring; struct bpf_prog *xdp_prog; + u64 offset; u32 act; rcu_read_lock(); @@ -208,7 +208,7 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) */ xdp_prog = READ_ONCE(rx_ring->xdp_prog); act = bpf_prog_run_xdp(xdp_prog, xdp); - offset += xdp->data - xdp->data_hard_start; + offset = xdp->data - xdp->data_hard_start; xdp->handle = xsk_umem_adjust_offset(umem, xdp->handle, offset); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c index a37dcd140f63..100ac89b345d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c @@ -145,15 +145,15 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter, { struct xdp_umem *umem = rx_ring->xsk_umem; int err, result = IXGBE_XDP_PASS; - u64 offset = umem->headroom; struct bpf_prog *xdp_prog; struct xdp_frame *xdpf; + u64 offset; u32 act; rcu_read_lock(); xdp_prog = READ_ONCE(rx_ring->xdp_prog); act = bpf_prog_run_xdp(xdp_prog, xdp); - offset += xdp->data - xdp->data_hard_start; + offset = xdp->data - xdp->data_hard_start; xdp->handle = xsk_umem_adjust_offset(umem, xdp->handle, offset); diff --git a/include/linux/filter.h b/include/linux/filter.h index 92c6e31fb008..2ce57645f3cd 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -749,14 +749,14 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default) } static inline u8 -bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default) +bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) { - u8 load_off = off & (size_default - 1); + u8 access_off = off & (size_default - 1); #ifdef __LITTLE_ENDIAN - return load_off * 8; + return access_off; #else - return (size_default - (load_off + size)) * 8; + return size_default - (access_off + size); #endif } diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 6a6a154cfa7b..ddd8addcdb5c 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -1334,6 +1334,7 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, struct bpf_prog *prog, u32 *target_size) { struct bpf_insn *insn = insn_buf; + u32 read_size; switch (si->off) { case offsetof(struct bpf_sysctl, write): @@ -1365,7 +1366,9 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, treg, si->dst_reg, offsetof(struct bpf_sysctl_kern, ppos)); *insn++ = BPF_STX_MEM( - BPF_SIZEOF(u32), treg, si->src_reg, 0); + BPF_SIZEOF(u32), treg, si->src_reg, + bpf_ctx_narrow_access_offset( + 0, sizeof(u32), sizeof(loff_t))); *insn++ = BPF_LDX_MEM( BPF_DW, treg, si->dst_reg, offsetof(struct bpf_sysctl_kern, tmp_reg)); @@ -1374,8 +1377,11 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, BPF_FIELD_SIZEOF(struct bpf_sysctl_kern, ppos), si->dst_reg, si->src_reg, offsetof(struct bpf_sysctl_kern, ppos)); + read_size = bpf_size_to_bytes(BPF_SIZE(si->code)); *insn++ = BPF_LDX_MEM( - BPF_SIZE(si->code), si->dst_reg, si->dst_reg, 0); + BPF_SIZE(si->code), si->dst_reg, si->dst_reg, + bpf_ctx_narrow_access_offset( + 0, read_size, sizeof(loff_t))); } *target_size = sizeof(u32); break; diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index 9af048a932b5..d27f3b60ff6d 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -650,19 +650,22 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, u32 ifindex = *(u32 *)value; u32 idx = *(u32 *)key; unsigned long flags; + int err = -EEXIST; if (unlikely(map_flags > BPF_EXIST || !ifindex)) return -EINVAL; + spin_lock_irqsave(&dtab->index_lock, flags); + old_dev = __dev_map_hash_lookup_elem(map, idx); if (old_dev && (map_flags & BPF_NOEXIST)) - return -EEXIST; + goto out_err; dev = __dev_map_alloc_node(net, dtab, ifindex, idx); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - spin_lock_irqsave(&dtab->index_lock, flags); + if (IS_ERR(dev)) { + err = PTR_ERR(dev); + goto out_err; + } if (old_dev) { hlist_del_rcu(&old_dev->index_hlist); @@ -683,6 +686,10 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, call_rcu(&old_dev->rcu, __dev_map_entry_free); return 0; + +out_err: + spin_unlock_irqrestore(&dtab->index_lock, flags); + return err; } static int dev_map_hash_update_elem(struct bpf_map *map, void *key, void *value, diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 315798037d6c..ffc3e53f5300 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -8624,8 +8624,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) } if (is_narrower_load && size < target_size) { - u8 shift = bpf_ctx_narrow_load_shift(off, size, - size_default); + u8 shift = bpf_ctx_narrow_access_offset( + off, size, size_default) * 8; if (ctx_field_size <= 4) { if (shift) insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH, diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index 4ff75c3a8d6e..8f12f5c6ab87 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -379,7 +379,7 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb) struct kcm_psock *psock = container_of(strp, struct kcm_psock, strp); struct bpf_prog *prog = psock->bpf_prog; - return (*prog->bpf_func)(skb, prog->insnsi); + return BPF_PROG_RUN(prog, skb); } static int kcm_read_sock_done(struct strparser *strp, int err) diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c index 102eace22956..df011ac33402 100644 --- a/samples/bpf/xdpsock_user.c +++ b/samples/bpf/xdpsock_user.c @@ -685,7 +685,7 @@ static void l2fwd(struct xsk_socket_info *xsk, struct pollfd *fds) for (i = 0; i < rcvd; i++) { u64 addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr; u32 len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len; - u64 orig = xsk_umem__extract_addr(addr); + u64 orig = addr; addr = xsk_umem__add_offset_to_addr(addr); char *pkt = xsk_umem__get_data(xsk->umem->buffer, addr); diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 0d8f41db8cd6..8c59970a09dc 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -57,12 +57,16 @@ modpost_link() # Link of vmlinux # ${1} - output file -# ${@:2} - optional extra .o files +# ${2}, ${3}, ... - optional extra .o files vmlinux_link() { local lds="${objtree}/${KBUILD_LDS}" + local output=${1} local objects + # skip output file argument + shift + if [ "${SRCARCH}" != "um" ]; then objects="--whole-archive \ ${KBUILD_VMLINUX_OBJS} \ @@ -70,9 +74,10 @@ vmlinux_link() --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group \ - ${@:2}" + ${@}" - ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${1} \ + ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \ + -o ${output} \ -T ${lds} ${objects} else objects="-Wl,--whole-archive \ @@ -81,9 +86,10 @@ vmlinux_link() -Wl,--start-group \ ${KBUILD_VMLINUX_LIBS} \ -Wl,--end-group \ - ${@:2}" + ${@}" - ${CC} ${CFLAGS_vmlinux} -o ${1} \ + ${CC} ${CFLAGS_vmlinux} \ + -o ${output} \ -Wl,-T,${lds} \ ${objects} \ -lutil -lrt -lpthread diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 60c9338cd9b4..7470327edcfe 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -39,8 +39,3 @@ libbpf.so.* test_hashmap test_btf_dump xdping -test_sockopt -test_sockopt_sk -test_sockopt_multi -test_sockopt_inherit -test_tcp_rtt diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 9eef5edf17be..6889c19a628c 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -17,6 +17,7 @@ LLC ?= llc LLVM_OBJCOPY ?= llvm-objcopy LLVM_READELF ?= llvm-readelf BTF_PAHOLE ?= pahole +BPF_GCC ?= $(shell command -v bpf-gcc;) CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \ -Dbpf_prog_load=bpf_prog_test_load \ -Dbpf_load_program=bpf_test_load_program @@ -28,8 +29,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \ test_cgroup_storage test_select_reuseport test_section_names \ test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \ - test_btf_dump test_cgroup_attach xdping test_sockopt test_sockopt_sk \ - test_sockopt_multi test_sockopt_inherit test_tcp_rtt + test_btf_dump test_cgroup_attach xdping BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c))) TEST_GEN_FILES = $(BPF_OBJ_FILES) @@ -47,6 +47,10 @@ ifneq ($(SUBREG_CODEGEN),) TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES)) endif +ifneq ($(BPF_GCC),) +TEST_GEN_FILES += $(patsubst %.o,bpf_gcc/%.o, $(BPF_OBJ_FILES)) +endif + # Order correspond to 'make run_tests' order TEST_PROGS := test_kmod.sh \ test_libbpf.sh \ @@ -106,18 +110,13 @@ $(OUTPUT)/test_socket_cookie: cgroup_helpers.c $(OUTPUT)/test_sockmap: cgroup_helpers.c $(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c $(OUTPUT)/test_tcpnotify_user: cgroup_helpers.c trace_helpers.c -$(OUTPUT)/test_progs: trace_helpers.c +$(OUTPUT)/test_progs: cgroup_helpers.c trace_helpers.c $(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c $(OUTPUT)/test_cgroup_storage: cgroup_helpers.c $(OUTPUT)/test_netcnt: cgroup_helpers.c $(OUTPUT)/test_sock_fields: cgroup_helpers.c $(OUTPUT)/test_sysctl: cgroup_helpers.c $(OUTPUT)/test_cgroup_attach: cgroup_helpers.c -$(OUTPUT)/test_sockopt: cgroup_helpers.c -$(OUTPUT)/test_sockopt_sk: cgroup_helpers.c -$(OUTPUT)/test_sockopt_multi: cgroup_helpers.c -$(OUTPUT)/test_sockopt_inherit: cgroup_helpers.c -$(OUTPUT)/test_tcp_rtt: cgroup_helpers.c .PHONY: force @@ -143,16 +142,19 @@ endif # # Use '-idirafter': Don't interfere with include mechanics except where the # build would have failed anyways. -CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - &1 \ +define get_sys_includes +$(shell $(1) -v -E - &1 \ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') +endef +CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG)) +BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \ + -I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH) -CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \ - $(CLANG_SYS_INCLUDES) \ - -Wno-compare-distinct-pointer-types \ - -D__TARGET_ARCH_$(SRCARCH) +CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \ + -Wno-compare-distinct-pointer-types -$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline -$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline +$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline +$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline $(OUTPUT)/test_queue_map.o: test_queue_stack_map.h $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h @@ -169,12 +171,12 @@ BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ /bin/rm -f ./llvm_btf_verify.o) ifneq ($(BTF_LLVM_PROBE),) - CLANG_FLAGS += -g + BPF_CFLAGS += -g else ifneq ($(BTF_LLC_PROBE),) ifneq ($(BTF_PAHOLE_PROBE),) ifneq ($(BTF_OBJCOPY_PROBE),) - CLANG_FLAGS += -g + BPF_CFLAGS += -g LLC_FLAGS += -mattr=dwarfris DWARF2BTF = y endif @@ -200,7 +202,7 @@ $(ALU32_BUILD_DIR)/test_progs_32: test_progs.c $(OUTPUT)/libbpf.a\ | $(ALU32_BUILD_DIR) $(CC) $(TEST_PROGS_CFLAGS) $(CFLAGS) \ -o $(ALU32_BUILD_DIR)/test_progs_32 \ - test_progs.c test_stub.c trace_helpers.c prog_tests/*.c \ + test_progs.c test_stub.c cgroup_helpers.c trace_helpers.c prog_tests/*.c \ $(OUTPUT)/libbpf.a $(LDLIBS) $(ALU32_BUILD_DIR)/test_progs_32: $(PROG_TESTS_H) @@ -208,8 +210,8 @@ $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c $(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \ | $(ALU32_BUILD_DIR) - ($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \ - echo "clang failed") | \ + ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \ + -c $< -o - || echo "clang failed") | \ $(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \ -filetype=obj -o $@ ifeq ($(DWARF2BTF),y) @@ -217,10 +219,37 @@ ifeq ($(DWARF2BTF),y) endif endif +ifneq ($(BPF_GCC),) +GCC_SYS_INCLUDES = $(call get_sys_includes,gcc) +IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - $(VERIFIER_TESTS_H)) -EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \ +EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) $(BPF_GCC_BUILD_DIR) \ $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \ feature diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 6c4930bc6e2e..54a50699bbfd 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -1,12 +1,6 @@ /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ -#ifndef __BPF_HELPERS_H -#define __BPF_HELPERS_H - -/* helper macro to place programs, maps, license in - * different sections in elf_bpf file. Section names - * are interpreted by elf_bpf loader - */ -#define SEC(NAME) __attribute__((section(NAME), used)) +#ifndef __BPF_HELPERS__ +#define __BPF_HELPERS__ #define __uint(name, val) int (*name)[val] #define __type(name, val) val *name @@ -19,6 +13,14 @@ ##__VA_ARGS__); \ }) +#ifdef __clang__ + +/* helper macro to place programs, maps, license in + * different sections in elf_bpf file. Section names + * are interpreted by elf_bpf loader + */ +#define SEC(NAME) __attribute__((section(NAME), used)) + /* helper functions called from eBPF programs written in C */ static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *) BPF_FUNC_map_lookup_elem; @@ -256,6 +258,12 @@ struct bpf_map_def { unsigned int numa_node; }; +#else + +#include + +#endif + #define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ struct ____btf_map_##name { \ type_key key; \ diff --git a/tools/testing/selftests/bpf/test_sockopt.c b/tools/testing/selftests/bpf/prog_tests/sockopt.c similarity index 96% rename from tools/testing/selftests/bpf/test_sockopt.c rename to tools/testing/selftests/bpf/prog_tests/sockopt.c index 23bd0819382d..3e8517a8395a 100644 --- a/tools/testing/selftests/bpf/test_sockopt.c +++ b/tools/testing/selftests/bpf/prog_tests/sockopt.c @@ -1,22 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" +#include #include "cgroup_helpers.h" -#define CG_PATH "/sockopt" - static char bpf_log_buf[4096]; static bool verbose; @@ -983,39 +968,18 @@ static int run_test(int cgroup_fd, struct sockopt_test *test) return ret; } -int main(int args, char **argv) +void test_sockopt(void) { - int err = EXIT_FAILURE, error_cnt = 0; int cgroup_fd, i; - if (setup_cgroup_environment()) - goto cleanup_obj; - - cgroup_fd = create_and_get_cgroup(CG_PATH); - if (cgroup_fd < 0) - goto cleanup_cgroup_env; - - if (join_cgroup(CG_PATH)) - goto cleanup_cgroup; + cgroup_fd = test__join_cgroup("/sockopt"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; for (i = 0; i < ARRAY_SIZE(tests); i++) { - int err = run_test(cgroup_fd, &tests[i]); - - if (err) - error_cnt++; - - printf("#%d %s: %s\n", i, err ? "FAIL" : "PASS", - tests[i].descr); + test__start_subtest(tests[i].descr); + CHECK_FAIL(run_test(cgroup_fd, &tests[i])); } - printf("Summary: %ld PASSED, %d FAILED\n", - ARRAY_SIZE(tests) - error_cnt, error_cnt); - err = error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; - -cleanup_cgroup: close(cgroup_fd); -cleanup_cgroup_env: - cleanup_cgroup_environment(); -cleanup_obj: - return err; } diff --git a/tools/testing/selftests/bpf/test_sockopt_inherit.c b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c similarity index 72% rename from tools/testing/selftests/bpf/test_sockopt_inherit.c rename to tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c index 1bf699815b9b..6cbeea7b4bf1 100644 --- a/tools/testing/selftests/bpf/test_sockopt_inherit.c +++ b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c @@ -1,22 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" +#include #include "cgroup_helpers.h" -#define CG_PATH "/sockopt_inherit" #define SOL_CUSTOM 0xdeadbeef #define CUSTOM_INHERIT1 0 #define CUSTOM_INHERIT2 1 @@ -74,6 +59,9 @@ static int verify_sockopt(int fd, int optname, const char *msg, char expected) return 0; } +static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER; + static void *server_thread(void *arg) { struct sockaddr_storage addr; @@ -82,16 +70,26 @@ static void *server_thread(void *arg) int client_fd; int err = 0; - if (listen(fd, 1) < 0) - error(1, errno, "Failed to listed on socket"); + err = listen(fd, 1); + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_signal(&server_started); + pthread_mutex_unlock(&server_started_mtx); + + if (CHECK_FAIL(err < 0)) { + perror("Failed to listed on socket"); + return NULL; + } err += verify_sockopt(fd, CUSTOM_INHERIT1, "listen", 1); err += verify_sockopt(fd, CUSTOM_INHERIT2, "listen", 1); err += verify_sockopt(fd, CUSTOM_LISTENER, "listen", 1); client_fd = accept(fd, (struct sockaddr *)&addr, &len); - if (client_fd < 0) - error(1, errno, "Failed to accept client"); + if (CHECK_FAIL(client_fd < 0)) { + perror("Failed to accept client"); + return NULL; + } err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "accept", 1); err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "accept", 1); @@ -167,7 +165,7 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) return 0; } -static int run_test(int cgroup_fd) +static void run_test(int cgroup_fd) { struct bpf_prog_load_attr attr = { .file = "./sockopt_inherit.o", @@ -180,40 +178,41 @@ static int run_test(int cgroup_fd) int err; err = bpf_prog_load_xattr(&attr, &obj, &ignored); - if (err) { - log_err("Failed to load BPF object"); - return -1; - } + if (CHECK_FAIL(err)) + return; err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); - if (err) + if (CHECK_FAIL(err)) goto close_bpf_object; err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); - if (err) + if (CHECK_FAIL(err)) goto close_bpf_object; server_fd = start_server(); - if (server_fd < 0) { - err = -1; + if (CHECK_FAIL(server_fd < 0)) goto close_bpf_object; - } - pthread_create(&tid, NULL, server_thread, (void *)&server_fd); + if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, + (void *)&server_fd))) + goto close_bpf_object; + + pthread_mutex_lock(&server_started_mtx); + pthread_cond_wait(&server_started, &server_started_mtx); + pthread_mutex_unlock(&server_started_mtx); client_fd = connect_to_server(server_fd); - if (client_fd < 0) { - err = -1; + if (CHECK_FAIL(client_fd < 0)) goto close_server_fd; - } - err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0); - err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0); - err += verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0); + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0)); + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0)); + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0)); pthread_join(tid, &server_err); - err += (int)(long)server_err; + err = (int)(long)server_err; + CHECK_FAIL(err); close(client_fd); @@ -221,33 +220,16 @@ static int run_test(int cgroup_fd) close(server_fd); close_bpf_object: bpf_object__close(obj); - return err; } -int main(int args, char **argv) +void test_sockopt_inherit(void) { int cgroup_fd; - int err = EXIT_SUCCESS; - if (setup_cgroup_environment()) - return err; + cgroup_fd = test__join_cgroup("/sockopt_inherit"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; - cgroup_fd = create_and_get_cgroup(CG_PATH); - if (cgroup_fd < 0) - goto cleanup_cgroup_env; - - if (join_cgroup(CG_PATH)) - goto cleanup_cgroup; - - if (run_test(cgroup_fd)) - err = EXIT_FAILURE; - - printf("test_sockopt_inherit: %s\n", - err == EXIT_SUCCESS ? "PASSED" : "FAILED"); - -cleanup_cgroup: + run_test(cgroup_fd); close(cgroup_fd); -cleanup_cgroup_env: - cleanup_cgroup_environment(); - return err; } diff --git a/tools/testing/selftests/bpf/test_sockopt_multi.c b/tools/testing/selftests/bpf/prog_tests/sockopt_multi.c similarity index 83% rename from tools/testing/selftests/bpf/test_sockopt_multi.c rename to tools/testing/selftests/bpf/prog_tests/sockopt_multi.c index 4be3441db867..29188d6f5c8d 100644 --- a/tools/testing/selftests/bpf/test_sockopt_multi.c +++ b/tools/testing/selftests/bpf/prog_tests/sockopt_multi.c @@ -1,19 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" +#include #include "cgroup_helpers.h" static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) @@ -308,7 +294,7 @@ static int run_setsockopt_test(struct bpf_object *obj, int cg_parent, return err; } -int main(int argc, char **argv) +void test_sockopt_multi(void) { struct bpf_prog_load_attr attr = { .file = "./sockopt_multi.o", @@ -319,56 +305,28 @@ int main(int argc, char **argv) int err = -1; int ignored; - if (setup_cgroup_environment()) { - log_err("Failed to setup cgroup environment\n"); + cg_parent = test__join_cgroup("/parent"); + if (CHECK_FAIL(cg_parent < 0)) goto out; - } - cg_parent = create_and_get_cgroup("/parent"); - if (cg_parent < 0) { - log_err("Failed to create cgroup /parent\n"); + cg_child = test__join_cgroup("/parent/child"); + if (CHECK_FAIL(cg_child < 0)) goto out; - } - - cg_child = create_and_get_cgroup("/parent/child"); - if (cg_child < 0) { - log_err("Failed to create cgroup /parent/child\n"); - goto out; - } - - if (join_cgroup("/parent/child")) { - log_err("Failed to join cgroup /parent/child\n"); - goto out; - } err = bpf_prog_load_xattr(&attr, &obj, &ignored); - if (err) { - log_err("Failed to load BPF object"); + if (CHECK_FAIL(err)) goto out; - } sock_fd = socket(AF_INET, SOCK_STREAM, 0); - if (sock_fd < 0) { - log_err("Failed to create socket"); + if (CHECK_FAIL(sock_fd < 0)) goto out; - } - if (run_getsockopt_test(obj, cg_parent, cg_child, sock_fd)) - err = -1; - printf("test_sockopt_multi: getsockopt %s\n", - err ? "FAILED" : "PASSED"); - - if (run_setsockopt_test(obj, cg_parent, cg_child, sock_fd)) - err = -1; - printf("test_sockopt_multi: setsockopt %s\n", - err ? "FAILED" : "PASSED"); + CHECK_FAIL(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd)); + CHECK_FAIL(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd)); out: close(sock_fd); bpf_object__close(obj); close(cg_child); close(cg_parent); - - printf("test_sockopt_multi: %s\n", err ? "FAILED" : "PASSED"); - return err ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tools/testing/selftests/bpf/test_sockopt_sk.c b/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c similarity index 79% rename from tools/testing/selftests/bpf/test_sockopt_sk.c rename to tools/testing/selftests/bpf/prog_tests/sockopt_sk.c index e4f6055d92e9..2061a6beac0f 100644 --- a/tools/testing/selftests/bpf/test_sockopt_sk.c +++ b/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c @@ -1,23 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" +#include #include "cgroup_helpers.h" -#define CG_PATH "/sockopt" - #define SOL_CUSTOM 0xdeadbeef static int getsetsockopt(void) @@ -176,7 +160,7 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) return 0; } -static int run_test(int cgroup_fd) +static void run_test(int cgroup_fd) { struct bpf_prog_load_attr attr = { .file = "./sockopt_sk.o", @@ -186,51 +170,31 @@ static int run_test(int cgroup_fd) int err; err = bpf_prog_load_xattr(&attr, &obj, &ignored); - if (err) { - log_err("Failed to load BPF object"); - return -1; - } + if (CHECK_FAIL(err)) + return; err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); - if (err) + if (CHECK_FAIL(err)) goto close_bpf_object; err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); - if (err) + if (CHECK_FAIL(err)) goto close_bpf_object; - err = getsetsockopt(); + CHECK_FAIL(getsetsockopt()); close_bpf_object: bpf_object__close(obj); - return err; } -int main(int args, char **argv) +void test_sockopt_sk(void) { int cgroup_fd; - int err = EXIT_SUCCESS; - if (setup_cgroup_environment()) - goto cleanup_obj; + cgroup_fd = test__join_cgroup("/sockopt_sk"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; - cgroup_fd = create_and_get_cgroup(CG_PATH); - if (cgroup_fd < 0) - goto cleanup_cgroup_env; - - if (join_cgroup(CG_PATH)) - goto cleanup_cgroup; - - if (run_test(cgroup_fd)) - err = EXIT_FAILURE; - - printf("test_sockopt_sk: %s\n", - err == EXIT_SUCCESS ? "PASSED" : "FAILED"); - -cleanup_cgroup: + run_test(cgroup_fd); close(cgroup_fd); -cleanup_cgroup_env: - cleanup_cgroup_environment(); -cleanup_obj: - return err; } diff --git a/tools/testing/selftests/bpf/test_tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c similarity index 76% rename from tools/testing/selftests/bpf/test_tcp_rtt.c rename to tools/testing/selftests/bpf/prog_tests/tcp_rtt.c index 93916a69823e..fdc0b3614a9e 100644 --- a/tools/testing/selftests/bpf/test_tcp_rtt.c +++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c @@ -1,24 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "bpf_rlimit.h" -#include "bpf_util.h" +#include #include "cgroup_helpers.h" -#define CG_PATH "/tcp_rtt" - struct tcp_rtt_storage { __u32 invoked; __u32 dsack_dups; @@ -31,8 +14,8 @@ static void send_byte(int fd) { char b = 0x55; - if (write(fd, &b, sizeof(b)) != 1) - error(1, errno, "Failed to send single byte"); + if (CHECK_FAIL(write(fd, &b, sizeof(b)) != 1)) + perror("Failed to send single byte"); } static int wait_for_ack(int fd, int retries) @@ -66,8 +49,10 @@ static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked, int err = 0; struct tcp_rtt_storage val; - if (bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0) - error(1, errno, "Failed to read socket storage"); + if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0)) { + perror("Failed to read socket storage"); + return -1; + } if (val.invoked != invoked) { log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d", @@ -225,61 +210,47 @@ static void *server_thread(void *arg) int fd = *(int *)arg; int client_fd; - if (listen(fd, 1) < 0) - error(1, errno, "Failed to listed on socket"); + if (CHECK_FAIL(listen(fd, 1)) < 0) { + perror("Failed to listed on socket"); + return NULL; + } client_fd = accept(fd, (struct sockaddr *)&addr, &len); - if (client_fd < 0) - error(1, errno, "Failed to accept client"); + if (CHECK_FAIL(client_fd < 0)) { + perror("Failed to accept client"); + return NULL; + } /* Wait for the next connection (that never arrives) * to keep this thread alive to prevent calling * close() on client_fd. */ - if (accept(fd, (struct sockaddr *)&addr, &len) >= 0) - error(1, errno, "Unexpected success in second accept"); + if (CHECK_FAIL(accept(fd, (struct sockaddr *)&addr, &len) >= 0)) { + perror("Unexpected success in second accept"); + return NULL; + } close(client_fd); return NULL; } -int main(int args, char **argv) +void test_tcp_rtt(void) { int server_fd, cgroup_fd; - int err = EXIT_SUCCESS; pthread_t tid; - if (setup_cgroup_environment()) - goto cleanup_obj; - - cgroup_fd = create_and_get_cgroup(CG_PATH); - if (cgroup_fd < 0) - goto cleanup_cgroup_env; - - if (join_cgroup(CG_PATH)) - goto cleanup_cgroup; + cgroup_fd = test__join_cgroup("/tcp_rtt"); + if (CHECK_FAIL(cgroup_fd < 0)) + return; server_fd = start_server(); - if (server_fd < 0) { - err = EXIT_FAILURE; - goto cleanup_cgroup; - } + if (CHECK_FAIL(server_fd < 0)) + goto close_cgroup_fd; pthread_create(&tid, NULL, server_thread, (void *)&server_fd); - - if (run_test(cgroup_fd, server_fd)) - err = EXIT_FAILURE; - + CHECK_FAIL(run_test(cgroup_fd, server_fd)); close(server_fd); - - printf("test_sockopt_sk: %s\n", - err == EXIT_SUCCESS ? "PASSED" : "FAILED"); - -cleanup_cgroup: +close_cgroup_fd: close(cgroup_fd); -cleanup_cgroup_env: - cleanup_cgroup_environment(); -cleanup_obj: - return err; } diff --git a/tools/testing/selftests/bpf/progs/test_tc_edt.c b/tools/testing/selftests/bpf/progs/test_tc_edt.c index 3af64c470d64..0961415ba477 100644 --- a/tools/testing/selftests/bpf/progs/test_tc_edt.c +++ b/tools/testing/selftests/bpf/progs/test_tc_edt.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index e8616e778cb5..af75a1c7a458 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -2,6 +2,7 @@ /* Copyright (c) 2017 Facebook */ #include "test_progs.h" +#include "cgroup_helpers.h" #include "bpf_rlimit.h" #include #include @@ -17,6 +18,7 @@ struct prog_test_def { int error_cnt; int skip_cnt; bool tested; + bool need_cgroup_cleanup; const char *subtest_name; int subtest_num; @@ -122,6 +124,39 @@ void test__fail(void) env.test->error_cnt++; } +int test__join_cgroup(const char *path) +{ + int fd; + + if (!env.test->need_cgroup_cleanup) { + if (setup_cgroup_environment()) { + fprintf(stderr, + "#%d %s: Failed to setup cgroup environment\n", + env.test->test_num, env.test->test_name); + return -1; + } + + env.test->need_cgroup_cleanup = true; + } + + fd = create_and_get_cgroup(path); + if (fd < 0) { + fprintf(stderr, + "#%d %s: Failed to create cgroup '%s' (errno=%d)\n", + env.test->test_num, env.test->test_name, path, errno); + return fd; + } + + if (join_cgroup(path)) { + fprintf(stderr, + "#%d %s: Failed to join cgroup '%s' (errno=%d)\n", + env.test->test_num, env.test->test_name, path, errno); + return -1; + } + + return fd; +} + struct ipv4_packet pkt_v4 = { .eth.h_proto = __bpf_constant_htons(ETH_P_IP), .iph.ihl = 5, @@ -530,6 +565,9 @@ int main(int argc, char **argv) fprintf(env.stdout, "#%d %s:%s\n", test->test_num, test->test_name, test->error_cnt ? "FAIL" : "OK"); + + if (test->need_cgroup_cleanup) + cleanup_cgroup_environment(); } stdio_restore(); printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index c8edb9464ba6..0c48f64f732b 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -16,9 +16,10 @@ typedef __u16 __sum16; #include #include #include -#include +#include #include #include +#include #include #include @@ -71,6 +72,7 @@ extern void test__force_log(); extern bool test__start_subtest(const char *name); extern void test__skip(void); extern void test__fail(void); +extern int test__join_cgroup(const char *path); #define MAGIC_BYTES 123 diff --git a/tools/testing/selftests/bpf/test_sysctl.c b/tools/testing/selftests/bpf/test_sysctl.c index fc33ae36b760..4f8ec1f10a80 100644 --- a/tools/testing/selftests/bpf/test_sysctl.c +++ b/tools/testing/selftests/bpf/test_sysctl.c @@ -32,6 +32,7 @@ struct sysctl_test { enum bpf_attach_type attach_type; const char *sysctl; int open_flags; + int seek; const char *newval; const char *oldval; enum { @@ -140,7 +141,7 @@ static struct sysctl_test tests[] = { /* If (file_pos == X) */ BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, offsetof(struct bpf_sysctl, file_pos)), - BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2), + BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2), /* return ALLOW; */ BPF_MOV64_IMM(BPF_REG_0, 1), @@ -153,6 +154,7 @@ static struct sysctl_test tests[] = { .attach_type = BPF_CGROUP_SYSCTL, .sysctl = "kernel/ostype", .open_flags = O_RDONLY, + .seek = 3, .result = SUCCESS, }, { @@ -1481,6 +1483,11 @@ static int access_sysctl(const char *sysctl_path, if (fd < 0) return fd; + if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) { + log_err("lseek(%d) failed", test->seek); + goto err; + } + if (test->open_flags == O_RDONLY) { char buf[128];