diff options
-rw-r--r-- | include/linux/bpf-cgroup.h | 2 | ||||
-rw-r--r-- | include/linux/skbuff.h | 4 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 10 | ||||
-rw-r--r-- | kernel/sysctl.c | 2 | ||||
-rw-r--r-- | net/bpf/test_run.c | 2 | ||||
-rw-r--r-- | net/core/filter.c | 8 | ||||
-rw-r--r-- | net/core/lwt_bpf.c | 2 | ||||
-rw-r--r-- | net/core/skmsg.c | 1 | ||||
-rw-r--r-- | net/xdp/xsk.c | 5 | ||||
-rw-r--r-- | net/xdp/xsk_diag.c | 4 | ||||
-rw-r--r-- | net/xdp/xsk_queue.h | 4 | ||||
-rw-r--r-- | samples/bpf/hbm.c | 4 | ||||
-rw-r--r-- | tools/lib/bpf/Makefile | 3 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/Makefile | 33 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/prog_tests/signal_pending.c | 2 | ||||
-rwxr-xr-x | tools/testing/selftests/bpf/test_lwt_ip_encap.sh | 54 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/verifier/ld_imm64.c | 15 |
18 files changed, 121 insertions, 36 deletions
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index 695b2a880d9a..a4c644c1c091 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -292,7 +292,7 @@ static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog, static inline void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map) {} static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc( - struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return 0; } + struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return NULL; } static inline void bpf_cgroup_storage_free( struct bpf_cgroup_storage *storage) {} static inline int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 730b333be591..de56fdbecfc5 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -4286,10 +4286,10 @@ static inline bool skb_is_gso_sctp(const struct sk_buff *skb) return skb_shinfo(skb)->gso_type & SKB_GSO_SCTP; } +/* Note: Should be called only if skb_is_gso(skb) is true */ static inline bool skb_is_gso_tcp(const struct sk_buff *skb) { - return skb_is_gso(skb) && - skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6); + return skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6); } static inline void skb_gso_reset(struct sk_buff *skb) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a7b96bf0e654..ce166a002d16 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6678,17 +6678,17 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env) /* valid generic load 64-bit imm */ goto next_insn; - if (insn->src_reg != BPF_PSEUDO_MAP_FD) { - verbose(env, - "unrecognized bpf_ld_imm64 insn\n"); + if (insn[0].src_reg != BPF_PSEUDO_MAP_FD || + insn[1].imm != 0) { + verbose(env, "unrecognized bpf_ld_imm64 insn\n"); return -EINVAL; } - f = fdget(insn->imm); + f = fdget(insn[0].imm); map = __bpf_map_get(f); if (IS_ERR(map)) { verbose(env, "fd %d is not pointing to valid bpf_map\n", - insn->imm); + insn[0].imm); return PTR_ERR(map); } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 7578e21a711b..2322b12cb4cf 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -3274,7 +3274,7 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, #endif /* CONFIG_PROC_SYSCTL */ -#ifdef CONFIG_BPF_SYSCALL +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL) static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index da7051d62727..fab142b796ef 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -16,7 +16,7 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *retval, u32 *time) { - struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { 0 }; + struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { NULL }; enum bpf_cgroup_storage_type stype; u64 time_start, time_spent = 0; int ret = 0; diff --git a/net/core/filter.c b/net/core/filter.c index 5ceba98069d4..f274620945ff 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2804,7 +2804,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) u32 off = skb_mac_header_len(skb); int ret; - if (!skb_is_gso_tcp(skb)) + if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) return -ENOTSUPP; ret = skb_cow(skb, len_diff); @@ -2845,7 +2845,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) u32 off = skb_mac_header_len(skb); int ret; - if (!skb_is_gso_tcp(skb)) + if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) return -ENOTSUPP; ret = skb_unclone(skb, GFP_ATOMIC); @@ -2970,7 +2970,7 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff) u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb); int ret; - if (!skb_is_gso_tcp(skb)) + if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) return -ENOTSUPP; ret = skb_cow(skb, len_diff); @@ -2999,7 +2999,7 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff) u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb); int ret; - if (!skb_is_gso_tcp(skb)) + if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) return -ENOTSUPP; ret = skb_unclone(skb, GFP_ATOMIC); diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index cf2f8897ca19..126d31ff5ee3 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -625,6 +625,8 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress) /* push the encap headers and fix pointers */ skb_reset_inner_headers(skb); + skb_reset_inner_mac_header(skb); /* mac header is not yet set */ + skb_set_inner_protocol(skb, skb->protocol); skb->encapsulation = 1; skb_push(skb, len); if (ingress) diff --git a/net/core/skmsg.c b/net/core/skmsg.c index ae6f06e45737..cc94d921476c 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -554,6 +554,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc) struct sk_psock *psock = container_of(gc, struct sk_psock, gc); /* No sk_callback_lock since already detached. */ + strp_stop(&psock->parser.strp); strp_done(&psock->parser.strp); cancel_work_sync(&psock->work); diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 6697084e3fdf..a14e8864e4fa 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -407,6 +407,10 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) if (sxdp->sxdp_family != AF_XDP) return -EINVAL; + flags = sxdp->sxdp_flags; + if (flags & ~(XDP_SHARED_UMEM | XDP_COPY | XDP_ZEROCOPY)) + return -EINVAL; + mutex_lock(&xs->mutex); if (xs->dev) { err = -EBUSY; @@ -425,7 +429,6 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) } qid = sxdp->sxdp_queue_id; - flags = sxdp->sxdp_flags; if (flags & XDP_SHARED_UMEM) { struct xdp_sock *umem_xs; diff --git a/net/xdp/xsk_diag.c b/net/xdp/xsk_diag.c index 661d007c3b28..d5e06c8e0cbf 100644 --- a/net/xdp/xsk_diag.c +++ b/net/xdp/xsk_diag.c @@ -68,9 +68,9 @@ static int xsk_diag_put_umem(const struct xdp_sock *xs, struct sk_buff *nlskb) err = nla_put(nlskb, XDP_DIAG_UMEM, sizeof(du), &du); if (!err && umem->fq) - err = xsk_diag_put_ring(xs->tx, XDP_DIAG_UMEM_FILL_RING, nlskb); + err = xsk_diag_put_ring(umem->fq, XDP_DIAG_UMEM_FILL_RING, nlskb); if (!err && umem->cq) { - err = xsk_diag_put_ring(xs->tx, XDP_DIAG_UMEM_COMPLETION_RING, + err = xsk_diag_put_ring(umem->cq, XDP_DIAG_UMEM_COMPLETION_RING, nlskb); } return err; diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index bcb5cbb40419..610c0bdc0c2b 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h @@ -174,8 +174,8 @@ static inline bool xskq_is_valid_desc(struct xsk_queue *q, struct xdp_desc *d) if (!xskq_is_valid_addr(q, d->addr)) return false; - if (((d->addr + d->len) & q->chunk_mask) != - (d->addr & q->chunk_mask)) { + if (((d->addr + d->len) & q->chunk_mask) != (d->addr & q->chunk_mask) || + d->options) { q->invalid_descs++; return false; } diff --git a/samples/bpf/hbm.c b/samples/bpf/hbm.c index 8408ccb7409f..a79828ab273f 100644 --- a/samples/bpf/hbm.c +++ b/samples/bpf/hbm.c @@ -18,7 +18,7 @@ * Default is /hbm1 * -r <rate> Rate limit in Mbps * -s Get HBM stats (marked, dropped, etc.) - * -t <time> Exit after specified seconds (deault is 0) + * -t <time> Exit after specified seconds (default is 0) * -w Work conserving flag. cgroup can increase its bandwidth * beyond the rate limit specified while there is available * bandwidth. Current implementation assumes there is only @@ -376,7 +376,7 @@ static void Usage(void) " Default is /hbm1\n" " -r <rate> Rate in Mbps\n" " -s Update HBM stats\n" - " -t <time> Exit after specified seconds (deault is 0)\n" + " -t <time> Exit after specified seconds (default is 0)\n" " -w Work conserving flag. cgroup can increase\n" " bandwidth beyond the rate limit specified\n" " while there is available bandwidth. Current\n" diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index a05c43468bd0..61aaacf0cfa1 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -147,7 +147,8 @@ endif TARGETS = $(CMD_TARGETS) -all: fixdep all_cmd +all: fixdep + $(Q)$(MAKE) all_cmd all_cmd: $(CMD_TARGETS) check diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index f5eb60379c8d..d5b830d60601 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -838,6 +838,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) if (IS_ERR(obj->btf) || btf__load(obj->btf)) { pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", BTF_ELF_SEC, PTR_ERR(obj->btf)); + if (!IS_ERR(obj->btf)) + btf__free(obj->btf); obj->btf = NULL; } } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 518cd587cd63..2aed37ea61a4 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -153,6 +153,9 @@ endif endif endif +TEST_PROGS_CFLAGS := -I. -I$(OUTPUT) +TEST_VERIFIER_CFLAGS := -I. -I$(OUTPUT) -Iverifier + ifneq ($(SUBREG_CODEGEN),) ALU32_BUILD_DIR = $(OUTPUT)/alu32 TEST_CUSTOM_PROGS += $(ALU32_BUILD_DIR)/test_progs_32 @@ -162,13 +165,15 @@ $(ALU32_BUILD_DIR): $(ALU32_BUILD_DIR)/urandom_read: $(OUTPUT)/urandom_read cp $< $@ -$(ALU32_BUILD_DIR)/test_progs_32: test_progs.c $(ALU32_BUILD_DIR) \ +$(ALU32_BUILD_DIR)/test_progs_32: test_progs.c $(OUTPUT)/libbpf.a\ + $(ALU32_BUILD_DIR) \ $(ALU32_BUILD_DIR)/urandom_read - $(CC) $(CFLAGS) -o $(ALU32_BUILD_DIR)/test_progs_32 $< \ - trace_helpers.c prog_tests/*.c $(OUTPUT)/libbpf.a $(LDLIBS) + $(CC) $(TEST_PROGS_CFLAGS) $(CFLAGS) \ + -o $(ALU32_BUILD_DIR)/test_progs_32 \ + test_progs.c trace_helpers.c prog_tests/*.c \ + $(OUTPUT)/libbpf.a $(LDLIBS) $(ALU32_BUILD_DIR)/test_progs_32: $(PROG_TESTS_H) -$(ALU32_BUILD_DIR)/test_progs_32: CFLAGS += -I$(OUTPUT) $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c $(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR) \ @@ -202,12 +207,16 @@ endif PROG_TESTS_H := $(OUTPUT)/prog_tests/tests.h $(OUTPUT)/test_progs: $(PROG_TESTS_H) -$(OUTPUT)/test_progs: CFLAGS += -I$(OUTPUT) +$(OUTPUT)/test_progs: CFLAGS += $(TEST_PROGS_CFLAGS) $(OUTPUT)/test_progs: prog_tests/*.c +PROG_TESTS_DIR = $(OUTPUT)/prog_tests +$(PROG_TESTS_DIR): + mkdir -p $@ + PROG_TESTS_FILES := $(wildcard prog_tests/*.c) -$(PROG_TESTS_H): $(PROG_TESTS_FILES) - $(shell ( cd prog_tests/ +$(PROG_TESTS_H): $(PROG_TESTS_DIR) $(PROG_TESTS_FILES) + $(shell ( cd prog_tests/; \ echo '/* Generated header, do not edit */'; \ echo '#ifdef DECLARE'; \ ls *.c 2> /dev/null | \ @@ -221,11 +230,15 @@ $(PROG_TESTS_H): $(PROG_TESTS_FILES) VERIFIER_TESTS_H := $(OUTPUT)/verifier/tests.h $(OUTPUT)/test_verifier: $(VERIFIER_TESTS_H) -$(OUTPUT)/test_verifier: CFLAGS += -I$(OUTPUT) +$(OUTPUT)/test_verifier: CFLAGS += $(TEST_VERIFIER_CFLAGS) + +VERIFIER_TESTS_DIR = $(OUTPUT)/verifier +$(VERIFIER_TESTS_DIR): + mkdir -p $@ VERIFIER_TEST_FILES := $(wildcard verifier/*.c) -$(OUTPUT)/verifier/tests.h: $(VERIFIER_TEST_FILES) - $(shell ( cd verifier/ +$(OUTPUT)/verifier/tests.h: $(VERIFIER_TESTS_DIR) $(VERIFIER_TEST_FILES) + $(shell ( cd verifier/; \ echo '/* Generated header, do not edit */'; \ echo '#ifdef FILL_ARRAY'; \ ls *.c 2> /dev/null | \ diff --git a/tools/testing/selftests/bpf/prog_tests/signal_pending.c b/tools/testing/selftests/bpf/prog_tests/signal_pending.c index f2a37bbf91ab..996e808f43a2 100644 --- a/tools/testing/selftests/bpf/prog_tests/signal_pending.c +++ b/tools/testing/selftests/bpf/prog_tests/signal_pending.c @@ -12,7 +12,7 @@ static void test_signal_pending_by_type(enum bpf_prog_type prog_type) struct itimerval timeo = { .it_value.tv_usec = 100000, /* 100ms */ }; - __u32 duration, retval; + __u32 duration = 0, retval; int prog_fd; int err; int i; diff --git a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh index 612632c1425f..d4d3391cc13a 100755 --- a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh +++ b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh @@ -78,6 +78,8 @@ TEST_STATUS=0 TESTS_SUCCEEDED=0 TESTS_FAILED=0 +TMPFILE="" + process_test_results() { if [[ "${TEST_STATUS}" -eq 0 ]] ; then @@ -147,7 +149,6 @@ setup() ip -netns ${NS2} -6 addr add ${IPv6_7}/128 nodad dev veth7 ip -netns ${NS3} -6 addr add ${IPv6_8}/128 nodad dev veth8 - ip -netns ${NS1} link set dev veth1 up ip -netns ${NS2} link set dev veth2 up ip -netns ${NS2} link set dev veth3 up @@ -205,7 +206,7 @@ setup() # configure IPv4 GRE device in NS3, and a route to it via the "bottom" route ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_1} local ${IPv4_GRE} ttl 255 ip -netns ${NS3} link set gre_dev up - ip -netns ${NS3} addr add ${IPv4_GRE} nodad dev gre_dev + ip -netns ${NS3} addr add ${IPv4_GRE} dev gre_dev ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6} ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8} @@ -222,12 +223,18 @@ setup() ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0 ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0 + TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX) + sleep 1 # reduce flakiness set +e } cleanup() { + if [ -f ${TMPFILE} ] ; then + rm ${TMPFILE} + fi + ip netns del ${NS1} 2> /dev/null ip netns del ${NS2} 2> /dev/null ip netns del ${NS3} 2> /dev/null @@ -278,6 +285,46 @@ test_ping() fi } +test_gso() +{ + local readonly PROTO=$1 + local readonly PKT_SZ=5000 + local IP_DST="" + : > ${TMPFILE} # trim the capture file + + # check that nc is present + command -v nc >/dev/null 2>&1 || \ + { echo >&2 "nc is not available: skipping TSO tests"; return; } + + # listen on IPv*_DST, capture TCP into $TMPFILE + if [ "${PROTO}" == "IPv4" ] ; then + IP_DST=${IPv4_DST} + ip netns exec ${NS3} bash -c \ + "nc -4 -l -s ${IPv4_DST} -p 9000 > ${TMPFILE} &" + elif [ "${PROTO}" == "IPv6" ] ; then + IP_DST=${IPv6_DST} + ip netns exec ${NS3} bash -c \ + "nc -6 -l -s ${IPv6_DST} -p 9000 > ${TMPFILE} &" + RET=$? + else + echo " test_gso: unknown PROTO: ${PROTO}" + TEST_STATUS=1 + fi + sleep 1 # let nc start listening + + # send a packet larger than MTU + ip netns exec ${NS1} bash -c \ + "dd if=/dev/zero bs=$PKT_SZ count=1 > /dev/tcp/${IP_DST}/9000 2>/dev/null" + sleep 2 # let the packet get delivered + + # verify we received all expected bytes + SZ=$(stat -c %s ${TMPFILE}) + if [ "$SZ" != "$PKT_SZ" ] ; then + echo " test_gso failed: ${PROTO}" + TEST_STATUS=1 + fi +} + test_egress() { local readonly ENCAP=$1 @@ -307,6 +354,8 @@ test_egress() fi test_ping IPv4 0 test_ping IPv6 0 + test_gso IPv4 + test_gso IPv6 # a negative test: remove routes to GRE devices: ping fails remove_routes_to_gredev @@ -350,6 +399,7 @@ test_ingress() ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj test_lwt_ip_encap.o sec encap_gre6 dev veth2 else echo "FAIL: unknown encap ${ENCAP}" + TEST_STATUS=1 fi test_ping IPv4 0 test_ping IPv6 0 diff --git a/tools/testing/selftests/bpf/verifier/ld_imm64.c b/tools/testing/selftests/bpf/verifier/ld_imm64.c index 28b8c805a293..3856dba733e9 100644 --- a/tools/testing/selftests/bpf/verifier/ld_imm64.c +++ b/tools/testing/selftests/bpf/verifier/ld_imm64.c @@ -122,7 +122,7 @@ .insns = { BPF_MOV64_IMM(BPF_REG_1, 0), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, BPF_REG_1, 0, 1), - BPF_RAW_INSN(0, 0, 0, 0, 1), + BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_EXIT_INSN(), }, .errstr = "not pointing to valid bpf_map", @@ -139,3 +139,16 @@ .errstr = "invalid bpf_ld_imm64 insn", .result = REJECT, }, +{ + "test14 ld_imm64: reject 2nd imm != 0", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_1, + BPF_PSEUDO_MAP_FD, 0, 0), + BPF_RAW_INSN(0, 0, 0, 0, 0xfefefe), + BPF_EXIT_INSN(), + }, + .fixup_map_hash_48b = { 1 }, + .errstr = "unrecognized bpf_ld_imm64 insn", + .result = REJECT, +}, |