From e1ef78dce9b7b0fa7f9d88bb3554441d74d33b34 Mon Sep 17 00:00:00 2001 From: Puranjay Mohan Date: Mon, 15 Jul 2024 17:33:27 +0000 Subject: [PATCH 01/34] selftests/bpf: fexit_sleep: Fix stack allocation for arm64 On ARM64 the stack pointer should be aligned at a 16 byte boundary or the SPAlignmentFault can occur. The fexit_sleep selftest allocates the stack for the child process as a character array, this is not guaranteed to be aligned at 16 bytes. Because of the SPAlignmentFault, the child process is killed before it can do the nanosleep call and hence fentry_cnt remains as 0. This causes the main thread to hang on the following line: while (READ_ONCE(fexit_skel->bss->fentry_cnt) != 2); Fix this by allocating the stack using mmap() as described in the example in the man page of clone(). Remove the fexit_sleep test from the DENYLIST of arm64. Fixes: eddbe8e65214 ("selftest/bpf: Add a test to check trampoline freeing logic.") Signed-off-by: Puranjay Mohan Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20240715173327.8657-1-puranjay@kernel.org --- tools/testing/selftests/bpf/DENYLIST.aarch64 | 1 - tools/testing/selftests/bpf/prog_tests/fexit_sleep.c | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/DENYLIST.aarch64 b/tools/testing/selftests/bpf/DENYLIST.aarch64 index 3c7c3e79aa93..901349da680f 100644 --- a/tools/testing/selftests/bpf/DENYLIST.aarch64 +++ b/tools/testing/selftests/bpf/DENYLIST.aarch64 @@ -1,6 +1,5 @@ bpf_cookie/multi_kprobe_attach_api # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3 bpf_cookie/multi_kprobe_link_api # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3 -fexit_sleep # The test never returns. The remaining tests cannot start. kprobe_multi_bench_attach # needs CONFIG_FPROBE kprobe_multi_test # needs CONFIG_FPROBE module_attach # prog 'kprobe_multi': failed to auto-attach: -95 diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_sleep.c b/tools/testing/selftests/bpf/prog_tests/fexit_sleep.c index f949647dbbc2..552a0875ca6d 100644 --- a/tools/testing/selftests/bpf/prog_tests/fexit_sleep.c +++ b/tools/testing/selftests/bpf/prog_tests/fexit_sleep.c @@ -21,13 +21,13 @@ static int do_sleep(void *skel) } #define STACK_SIZE (1024 * 1024) -static char child_stack[STACK_SIZE]; void test_fexit_sleep(void) { struct fexit_sleep_lskel *fexit_skel = NULL; int wstatus, duration = 0; pid_t cpid; + char *child_stack = NULL; int err, fexit_cnt; fexit_skel = fexit_sleep_lskel__open_and_load(); @@ -38,6 +38,11 @@ void test_fexit_sleep(void) if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err)) goto cleanup; + child_stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (!ASSERT_NEQ(child_stack, MAP_FAILED, "mmap")) + goto cleanup; + cpid = clone(do_sleep, child_stack + STACK_SIZE, CLONE_FILES | SIGCHLD, fexit_skel); if (CHECK(cpid == -1, "clone", "%s\n", strerror(errno))) goto cleanup; @@ -78,5 +83,6 @@ void test_fexit_sleep(void) goto cleanup; cleanup: + munmap(child_stack, STACK_SIZE); fexit_sleep_lskel__destroy(fexit_skel); } From afcc8e1ef7bb5c14100ba3e6ccfd4baebc80242e Mon Sep 17 00:00:00 2001 From: Naveen N Rao Date: Sun, 14 Jul 2024 14:04:23 +0530 Subject: [PATCH 02/34] MAINTAINERS: Update email address of Naveen I have switched to using my @kernel.org id for my contributions. Update MAINTAINERS and mailmap to reflect the same. Signed-off-by: Naveen N Rao Signed-off-by: Daniel Borkmann Reviewed-by: Masami Hiramatsu (Google) Link: https://lore.kernel.org/bpf/fb6ef126771c70538067709af69d960da3560ce7.1720944897.git.naveen@kernel.org --- .mailmap | 2 ++ MAINTAINERS | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.mailmap b/.mailmap index 38f8bed507a2..cbdf5d63c381 100644 --- a/.mailmap +++ b/.mailmap @@ -474,6 +474,8 @@ Nadia Yvette Chambers William Lee Irwin III Naoya Horiguchi Nathan Chancellor +Naveen N Rao +Naveen N Rao Neeraj Upadhyay Neeraj Upadhyay Neil Armstrong diff --git a/MAINTAINERS b/MAINTAINERS index 1928b8094443..cb94881d5d1e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3941,7 +3941,7 @@ S: Odd Fixes F: drivers/net/ethernet/netronome/nfp/bpf/ BPF JIT for POWERPC (32-BIT AND 64-BIT) -M: Naveen N. Rao +M: Naveen N Rao M: Michael Ellerman L: bpf@vger.kernel.org S: Supported @@ -12418,7 +12418,7 @@ F: mm/kmsan/ F: scripts/Makefile.kmsan KPROBES -M: Naveen N. Rao +M: Naveen N Rao M: Anil S Keshavamurthy M: "David S. Miller" M: Masami Hiramatsu @@ -12795,7 +12795,7 @@ LINUX FOR POWERPC (32-BIT AND 64-BIT) M: Michael Ellerman R: Nicholas Piggin R: Christophe Leroy -R: Naveen N. Rao +R: Naveen N Rao L: linuxppc-dev@lists.ozlabs.org S: Supported W: https://github.com/linuxppc/wiki/wiki From c638b130e83e4aa47031c0e51455ecc961dfdc3d Mon Sep 17 00:00:00 2001 From: Naveen N Rao Date: Sun, 14 Jul 2024 14:04:24 +0530 Subject: [PATCH 03/34] MAINTAINERS: Update powerpc BPF JIT maintainers Hari Bathini has been updating and maintaining the powerpc BPF JIT since a while now. Christophe Leroy has been doing the same for 32-bit powerpc. Add them as maintainers for the powerpc BPF JIT. I am no longer actively looking into the powerpc BPF JIT. Change my role to that of a reviewer so that I can help with the odd query. Signed-off-by: Naveen N Rao Signed-off-by: Daniel Borkmann Reviewed-by: Masami Hiramatsu (Google) Acked-by: Christophe Leroy Acked-by: Hari Bathini Link: https://lore.kernel.org/bpf/24fea21d9d4458973aadd6a02bb1bf558b8bd0b2.1720944897.git.naveen@kernel.org --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cb94881d5d1e..6feba67310fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3941,8 +3941,10 @@ S: Odd Fixes F: drivers/net/ethernet/netronome/nfp/bpf/ BPF JIT for POWERPC (32-BIT AND 64-BIT) -M: Naveen N Rao M: Michael Ellerman +M: Hari Bathini +M: Christophe Leroy +R: Naveen N Rao L: bpf@vger.kernel.org S: Supported F: arch/powerpc/net/ From 189f1a976e426011e6a5588f1d3ceedf71fe2965 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Fri, 12 Jul 2024 15:44:42 -0700 Subject: [PATCH 04/34] libbpf: Fix no-args func prototype BTF dumping syntax For all these years libbpf's BTF dumper has been emitting not strictly valid syntax for function prototypes that have no input arguments. Instead of `int (*blah)()` we should emit `int (*blah)(void)`. This is not normally a problem, but it manifests when we get kfuncs in vmlinux.h that have no input arguments. Due to compiler internal specifics, we get no BTF information for such kfuncs, if they are not declared with proper `(void)`. The fix is trivial. We also need to adjust a few ancient tests that happily assumed `()` is correct. Fixes: 351131b51c7a ("libbpf: add btf_dump API for BTF-to-C conversion") Reported-by: Tejun Heo Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Acked-by: Stanislav Fomichev Link: https://lore.kernel.org/bpf/20240712224442.282823-1-andrii@kernel.org --- tools/lib/bpf/btf_dump.c | 8 +++++--- .../selftests/bpf/progs/btf_dump_test_case_multidim.c | 4 ++-- .../selftests/bpf/progs/btf_dump_test_case_syntax.c | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index 5dbca76b953f..894860111ddb 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -1559,10 +1559,12 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, * Clang for BPF target generates func_proto with no * args as a func_proto with a single void arg (e.g., * `int (*f)(void)` vs just `int (*f)()`). We are - * going to pretend there are no args for such case. + * going to emit valid empty args (void) syntax for + * such case. Similarly and conveniently, valid + * no args case can be special-cased here as well. */ - if (vlen == 1 && p->type == 0) { - btf_dump_printf(d, ")"); + if (vlen == 0 || (vlen == 1 && p->type == 0)) { + btf_dump_printf(d, "void)"); return; } diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_multidim.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_multidim.c index ba97165bdb28..a657651eba52 100644 --- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_multidim.c +++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_multidim.c @@ -14,9 +14,9 @@ typedef int *ptr_arr_t[6]; typedef int *ptr_multiarr_t[7][8][9][10]; -typedef int * (*fn_ptr_arr_t[11])(); +typedef int * (*fn_ptr_arr_t[11])(void); -typedef int * (*fn_ptr_multiarr_t[12][13])(); +typedef int * (*fn_ptr_multiarr_t[12][13])(void); struct root_struct { arr_t _1; diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c index ad21ee8c7e23..29d01fff32bd 100644 --- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c +++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c @@ -100,7 +100,7 @@ typedef void (*printf_fn_t)(const char *, ...); * `int -> char *` function and returns pointer to a char. Equivalent: * typedef char * (*fn_input_t)(int); * typedef char * (*fn_output_outer_t)(fn_input_t); - * typedef const fn_output_outer_t (* fn_output_inner_t)(); + * typedef const fn_output_outer_t (* fn_output_inner_t)(void); * typedef const fn_output_inner_t fn_ptr_arr2_t[5]; */ /* ----- START-EXPECTED-OUTPUT ----- */ @@ -127,7 +127,7 @@ typedef void (* (*signal_t)(int, void (*)(int)))(int); typedef char * (*fn_ptr_arr1_t[10])(int **); -typedef char * (* (* const fn_ptr_arr2_t[5])())(char * (*)(int)); +typedef char * (* (* const fn_ptr_arr2_t[5])(void))(char * (*)(int)); struct struct_w_typedefs { int_t a; From 3c870059e9f8897c032f4256f90c41ee822218a8 Mon Sep 17 00:00:00 2001 From: Donald Hunter Date: Wed, 17 Jul 2024 14:45:08 +0100 Subject: [PATCH 05/34] bpftool: Fix typo in usage help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usage help for "bpftool prog help" contains a ° instead of the _ symbol for cgroup/sendmsg_unix. Fix the typo. Fixes: 8b3cba987e6d ("bpftool: Add support for cgroup unix socket address hooks") Signed-off-by: Donald Hunter Signed-off-by: Daniel Borkmann Acked-by: Quentin Monnet Link: https://lore.kernel.org/bpf/20240717134508.77488-1-donald.hunter@gmail.com --- tools/bpf/bpftool/prog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 40ea743d139f..2ff949ea82fa 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -2489,7 +2489,7 @@ static int do_help(int argc, char **argv) " cgroup/connect_unix | cgroup/getpeername4 | cgroup/getpeername6 |\n" " cgroup/getpeername_unix | cgroup/getsockname4 | cgroup/getsockname6 |\n" " cgroup/getsockname_unix | cgroup/sendmsg4 | cgroup/sendmsg6 |\n" - " cgroup/sendmsg°unix | cgroup/recvmsg4 | cgroup/recvmsg6 | cgroup/recvmsg_unix |\n" + " cgroup/sendmsg_unix | cgroup/recvmsg4 | cgroup/recvmsg6 | cgroup/recvmsg_unix |\n" " cgroup/getsockopt | cgroup/setsockopt | cgroup/sock_release |\n" " struct_ops | fentry | fexit | freplace | sk_lookup }\n" " ATTACH_TYPE := { sk_msg_verdict | sk_skb_verdict | sk_skb_stream_verdict |\n" From 638f32604385fd23059985da8de918e9c18f0b98 Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Sat, 13 Jul 2024 21:41:38 +0200 Subject: [PATCH 06/34] af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash AF_UNIX socket tracks the most recent OOB packet (in its receive queue) with an `oob_skb` pointer. BPF redirecting does not account for that: when an OOB packet is moved between sockets, `oob_skb` is left outdated. This results in a single skb that may be accessed from two different sockets. Take the easy way out: silently drop MSG_OOB data targeting any socket that is in a sockmap or a sockhash. Note that such silent drop is akin to the fate of redirected skb's scm_fp_list (SCM_RIGHTS, SCM_CREDENTIALS). For symmetry, forbid MSG_OOB in unix_bpf_recvmsg(). Fixes: 314001f0bf92 ("af_unix: Add OOB support") Suggested-by: Kuniyuki Iwashima Signed-off-by: Michal Luczaj Signed-off-by: Daniel Borkmann Tested-by: Jakub Sitnicki Reviewed-by: Kuniyuki Iwashima Reviewed-by: Jakub Sitnicki Link: https://lore.kernel.org/bpf/20240713200218.2140950-2-mhal@rbox.co --- net/unix/af_unix.c | 41 ++++++++++++++++++++++++++++++++++++++++- net/unix/unix_bpf.c | 3 +++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b0a4c6d08e0a..0be0dcb07f7b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2721,10 +2721,49 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) { + struct unix_sock *u = unix_sk(sk); + struct sk_buff *skb; + int err; + if (unlikely(READ_ONCE(sk->sk_state) != TCP_ESTABLISHED)) return -ENOTCONN; - return unix_read_skb(sk, recv_actor); + mutex_lock(&u->iolock); + skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); + mutex_unlock(&u->iolock); + if (!skb) + return err; + +#if IS_ENABLED(CONFIG_AF_UNIX_OOB) + if (unlikely(skb == READ_ONCE(u->oob_skb))) { + bool drop = false; + + unix_state_lock(sk); + + if (sock_flag(sk, SOCK_DEAD)) { + unix_state_unlock(sk); + kfree_skb(skb); + return -ECONNRESET; + } + + spin_lock(&sk->sk_receive_queue.lock); + if (likely(skb == u->oob_skb)) { + WRITE_ONCE(u->oob_skb, NULL); + drop = true; + } + spin_unlock(&sk->sk_receive_queue.lock); + + unix_state_unlock(sk); + + if (drop) { + WARN_ON_ONCE(skb_unref(skb)); + kfree_skb(skb); + return -EAGAIN; + } + } +#endif + + return recv_actor(sk, skb); } static int unix_stream_read_generic(struct unix_stream_read_state *state, diff --git a/net/unix/unix_bpf.c b/net/unix/unix_bpf.c index bd84785bf8d6..bca2d86ba97d 100644 --- a/net/unix/unix_bpf.c +++ b/net/unix/unix_bpf.c @@ -54,6 +54,9 @@ static int unix_bpf_recvmsg(struct sock *sk, struct msghdr *msg, struct sk_psock *psock; int copied; + if (flags & MSG_OOB) + return -EOPNOTSUPP; + if (!len) return 0; From 1b0ad43177c097d38b967b99c2b71d8be28b0223 Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Sat, 13 Jul 2024 21:41:39 +0200 Subject: [PATCH 07/34] selftests/bpf: Support SOCK_STREAM in unix_inet_redir_to_connected() Function ignores the AF_UNIX socket type argument, SOCK_DGRAM is hardcoded. Fix to respect the argument provided. Fixes: 75e0e27db6cf ("selftest/bpf: Change udp to inet in some function names") Suggested-by: Jakub Sitnicki Signed-off-by: Michal Luczaj Signed-off-by: Daniel Borkmann Tested-by: Jakub Sitnicki Reviewed-by: Jakub Sitnicki Link: https://lore.kernel.org/bpf/20240713200218.2140950-3-mhal@rbox.co --- tools/testing/selftests/bpf/prog_tests/sockmap_listen.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index e91b59366030..c075d376fcab 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -1828,7 +1828,7 @@ static void unix_inet_redir_to_connected(int family, int type, if (err) return; - if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, sfd)) + if (socketpair(AF_UNIX, type | SOCK_NONBLOCK, 0, sfd)) goto close_cli0; c1 = sfd[0], p1 = sfd[1]; @@ -1840,7 +1840,6 @@ static void unix_inet_redir_to_connected(int family, int type, close_cli0: xclose(c0); xclose(p0); - } static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, From 0befb349c4cdcc4e3c2f4aff81259a3a58c3b33e Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Sat, 13 Jul 2024 21:41:40 +0200 Subject: [PATCH 08/34] selftests/bpf: Parametrize AF_UNIX redir functions to accept send() flags Extend pairs_redir_to_connected() and unix_inet_redir_to_connected() with a send_flags parameter. Replace write() with send() allowing packets to be sent as MSG_OOB. Signed-off-by: Michal Luczaj Signed-off-by: Daniel Borkmann Tested-by: Jakub Sitnicki Reviewed-by: Jakub Sitnicki Link: https://lore.kernel.org/bpf/20240713200218.2140950-4-mhal@rbox.co --- .../selftests/bpf/prog_tests/sockmap_listen.c | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index c075d376fcab..3514a344bee6 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -29,6 +29,8 @@ #include "sockmap_helpers.h" +#define NO_FLAGS 0 + static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused, int family, int sotype, int mapfd) { @@ -1376,7 +1378,8 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map, static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, int sock_mapfd, int nop_mapfd, - int verd_mapfd, enum redir_mode mode) + int verd_mapfd, enum redir_mode mode, + int send_flags) { const char *log_prefix = redir_mode_str(mode); unsigned int pass; @@ -1396,11 +1399,9 @@ static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, return; } - n = write(cli1, "a", 1); - if (n < 0) - FAIL_ERRNO("%s: write", log_prefix); + n = xsend(cli1, "a", 1, send_flags); if (n == 0) - FAIL("%s: incomplete write", log_prefix); + FAIL("%s: incomplete send", log_prefix); if (n < 1) return; @@ -1432,7 +1433,8 @@ static void unix_redir_to_connected(int sotype, int sock_mapfd, goto close0; c1 = sfd[0], p1 = sfd[1]; - pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); + pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, + mode, NO_FLAGS); xclose(c1); xclose(p1); @@ -1722,7 +1724,8 @@ static void udp_redir_to_connected(int family, int sock_mapfd, int verd_mapfd, if (err) goto close_cli0; - pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); + pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, + mode, NO_FLAGS); xclose(c1); xclose(p1); @@ -1780,7 +1783,8 @@ static void inet_unix_redir_to_connected(int family, int type, int sock_mapfd, if (err) goto close; - pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); + pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, + mode, NO_FLAGS); xclose(c1); xclose(p1); @@ -1815,10 +1819,9 @@ static void inet_unix_skb_redir_to_connected(struct test_sockmap_listen *skel, xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); } -static void unix_inet_redir_to_connected(int family, int type, - int sock_mapfd, int nop_mapfd, - int verd_mapfd, - enum redir_mode mode) +static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd, + int nop_mapfd, int verd_mapfd, + enum redir_mode mode, int send_flags) { int c0, c1, p0, p1; int sfd[2]; @@ -1832,8 +1835,8 @@ static void unix_inet_redir_to_connected(int family, int type, goto close_cli0; c1 = sfd[0], p1 = sfd[1]; - pairs_redir_to_connected(c0, p0, c1, p1, - sock_mapfd, nop_mapfd, verd_mapfd, mode); + pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, nop_mapfd, + verd_mapfd, mode, send_flags); xclose(c1); xclose(p1); @@ -1858,31 +1861,32 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, skel->bss->test_ingress = false; unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, -1, verdict_map, - REDIR_EGRESS); + REDIR_EGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, -1, verdict_map, - REDIR_EGRESS); + REDIR_EGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, nop_map, verdict_map, - REDIR_EGRESS); + REDIR_EGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, nop_map, verdict_map, - REDIR_EGRESS); + REDIR_EGRESS, NO_FLAGS); + skel->bss->test_ingress = true; unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, -1, verdict_map, - REDIR_INGRESS); + REDIR_INGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, -1, verdict_map, - REDIR_INGRESS); + REDIR_INGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, nop_map, verdict_map, - REDIR_INGRESS); + REDIR_INGRESS, NO_FLAGS); unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, nop_map, verdict_map, - REDIR_INGRESS); + REDIR_INGRESS, NO_FLAGS); xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); } From 6caf9efaa169faea10a369dd6b36806ae6842584 Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Sat, 13 Jul 2024 21:41:41 +0200 Subject: [PATCH 09/34] selftests/bpf: Test sockmap redirect for AF_UNIX MSG_OOB Verify that out-of-band packets are silently dropped before they reach the redirection logic. The idea is to test with a 2 byte long send(). Should a MSG_OOB flag be in use, only the last byte will be treated as out-of-band. Test fails if verd_mapfd indicates a wrong number of packets processed (e.g. if OOB wasn't dropped at the source) or if it was possible to recv() MSG_OOB from the mapped socket, or if any stale OOB data have been left reachable from the unmapped socket. Signed-off-by: Michal Luczaj Signed-off-by: Daniel Borkmann Tested-by: Jakub Sitnicki Reviewed-by: Jakub Sitnicki Link: https://lore.kernel.org/bpf/20240713200218.2140950-5-mhal@rbox.co --- .../selftests/bpf/prog_tests/sockmap_listen.c | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index 3514a344bee6..9ce0e0e0b7da 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -1399,10 +1399,11 @@ static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, return; } - n = xsend(cli1, "a", 1, send_flags); - if (n == 0) + /* Last byte is OOB data when send_flags has MSG_OOB bit set */ + n = xsend(cli1, "ab", 2, send_flags); + if (n >= 0 && n < 2) FAIL("%s: incomplete send", log_prefix); - if (n < 1) + if (n < 2) return; key = SK_PASS; @@ -1417,6 +1418,25 @@ static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, FAIL_ERRNO("%s: recv_timeout", log_prefix); if (n == 0) FAIL("%s: incomplete recv", log_prefix); + + if (send_flags & MSG_OOB) { + /* Check that we can't read OOB while in sockmap */ + errno = 0; + n = recv(peer1, &b, 1, MSG_OOB | MSG_DONTWAIT); + if (n != -1 || errno != EOPNOTSUPP) + FAIL("%s: recv(MSG_OOB): expected EOPNOTSUPP: retval=%d errno=%d", + log_prefix, n, errno); + + /* Remove peer1 from sockmap */ + xbpf_map_delete_elem(sock_mapfd, &(int){ 1 }); + + /* Check that OOB was dropped on redirect */ + errno = 0; + n = recv(peer1, &b, 1, MSG_OOB | MSG_DONTWAIT); + if (n != -1 || errno != EINVAL) + FAIL("%s: recv(MSG_OOB): expected EINVAL: retval=%d errno=%d", + log_prefix, n, errno); + } } static void unix_redir_to_connected(int sotype, int sock_mapfd, @@ -1873,6 +1893,11 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, sock_map, nop_map, verdict_map, REDIR_EGRESS, NO_FLAGS); + /* MSG_OOB not supported by AF_UNIX SOCK_DGRAM */ + unix_inet_redir_to_connected(family, SOCK_STREAM, + sock_map, nop_map, verdict_map, + REDIR_EGRESS, MSG_OOB); + skel->bss->test_ingress = true; unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, -1, verdict_map, @@ -1888,6 +1913,11 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, sock_map, nop_map, verdict_map, REDIR_INGRESS, NO_FLAGS); + /* MSG_OOB not supported by AF_UNIX SOCK_DGRAM */ + unix_inet_redir_to_connected(family, SOCK_STREAM, + sock_map, nop_map, verdict_map, + REDIR_INGRESS, MSG_OOB); + xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); } From 0be9ae5486cd9e767138c13638820d240713f5f1 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Sun, 14 Jul 2024 14:55:33 +0800 Subject: [PATCH 10/34] bpf, events: Use prog to emit ksymbol event for main program Since commit 0108a4e9f358 ("bpf: ensure main program has an extable"), prog->aux->func[0]->kallsyms is left as uninitialized. For BPF programs with subprogs, the symbol for the main program is missing just as shown in the output of perf script below: ffffffff81284b69 qp_trie_lookup_elem+0xb9 ([kernel.kallsyms]) ffffffffc0011125 bpf_prog_a4a0eb0651e6af8b_lookup_qp_trie+0x5d (bpf...) ffffffff8127bc2b bpf_for_each_array_elem+0x7b ([kernel.kallsyms]) ffffffffc00110a1 +0x25 () ffffffff8121a89a trace_call_bpf+0xca ([kernel.kallsyms]) Fix it by always using prog instead prog->aux->func[0] to emit ksymbol event for the main program. After the fix, the output of perf script will be correct: ffffffff81284b96 qp_trie_lookup_elem+0xe6 ([kernel.kallsyms]) ffffffffc001382d bpf_prog_a4a0eb0651e6af8b_lookup_qp_trie+0x5d (bpf...) ffffffff8127bc2b bpf_for_each_array_elem+0x7b ([kernel.kallsyms]) ffffffffc0013779 bpf_prog_245c55ab25cfcf40_qp_trie_lookup+0x25 (bpf...) ffffffff8121a89a trace_call_bpf+0xca ([kernel.kallsyms]) Fixes: 0108a4e9f358 ("bpf: ensure main program has an extable") Signed-off-by: Hou Tao Signed-off-by: Daniel Borkmann Tested-by: Yonghong Song Reviewed-by: Krister Johansen Reviewed-by: Jiri Olsa Link: https://lore.kernel.org/bpf/20240714065533.1112616-1-houtao@huaweicloud.com --- kernel/events/core.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index ab6c4c942f79..eeb585404e11 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -9327,21 +9327,19 @@ static void perf_event_bpf_emit_ksymbols(struct bpf_prog *prog, bool unregister = type == PERF_BPF_EVENT_PROG_UNLOAD; int i; - if (prog->aux->func_cnt == 0) { - perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_BPF, - (u64)(unsigned long)prog->bpf_func, - prog->jited_len, unregister, - prog->aux->ksym.name); - } else { - for (i = 0; i < prog->aux->func_cnt; i++) { - struct bpf_prog *subprog = prog->aux->func[i]; + perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_BPF, + (u64)(unsigned long)prog->bpf_func, + prog->jited_len, unregister, + prog->aux->ksym.name); - perf_event_ksymbol( - PERF_RECORD_KSYMBOL_TYPE_BPF, - (u64)(unsigned long)subprog->bpf_func, - subprog->jited_len, unregister, - subprog->aux->ksym.name); - } + for (i = 1; i < prog->aux->func_cnt; i++) { + struct bpf_prog *subprog = prog->aux->func[i]; + + perf_event_ksymbol( + PERF_RECORD_KSYMBOL_TYPE_BPF, + (u64)(unsigned long)subprog->bpf_func, + subprog->jited_len, unregister, + subprog->aux->ksym.name); } } From 13c9b702e6cb8e406d5fa6b2dca422fa42d2f13e Mon Sep 17 00:00:00 2001 From: Liwei Song Date: Mon, 22 Jul 2024 16:32:59 +0800 Subject: [PATCH 11/34] tools/resolve_btfids: Fix comparison of distinct pointer types warning in resolve_btfids Add a type cast for set8->pairs to fix below compile warning: main.c: In function 'sets_patch': main.c:699:50: warning: comparison of distinct pointer types lacks a cast 699 | BUILD_BUG_ON(set8->pairs != &set8->pairs[0].id); | ^~ Fixes: 9707ac4fe2f5 ("tools/resolve_btfids: Refactor set sorting with types from btf_ids.h") Signed-off-by: Liwei Song Signed-off-by: Daniel Borkmann Acked-by: Jiri Olsa Link: https://lore.kernel.org/bpf/20240722083305.4009723-1-liwei.song.lsong@gmail.com --- tools/bpf/resolve_btfids/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c index 936ef95c3d32..d54aaa0619df 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -704,7 +704,7 @@ static int sets_patch(struct object *obj) * Make sure id is at the beginning of the pairs * struct, otherwise the below qsort would not work. */ - BUILD_BUG_ON(set8->pairs != &set8->pairs[0].id); + BUILD_BUG_ON((u32 *)set8->pairs != &set8->pairs[0].id); qsort(set8->pairs, set8->cnt, sizeof(set8->pairs[0]), cmp_id); /* From cc73bbab4b1fb8a4f53a24645871dafa5f81266a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 18 Jul 2024 15:34:07 +0300 Subject: [PATCH 12/34] ipv4: Fix incorrect source address in Record Route option The Record Route IP option records the addresses of the routers that routed the packet. In the case of forwarded packets, the kernel performs a route lookup via fib_lookup() and fills in the preferred source address of the matched route. The lookup is performed with the DS field of the forwarded packet, but using the RT_TOS() macro which only masks one of the two ECN bits. If the packet is ECT(0) or CE, the matched route might be different than the route via which the packet was forwarded as the input path masks both of the ECN bits, resulting in the wrong address being filled in the Record Route option. Fix by masking both of the ECN bits. Fixes: 8e36360ae876 ("ipv4: Remove route key identity dependencies in ip_rt_get_source().") Signed-off-by: Ido Schimmel Reviewed-by: Guillaume Nault Link: https://patch.msgid.link/20240718123407.434778-1-idosch@nvidia.com Signed-off-by: Paolo Abeni --- net/ipv4/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5090912533d6..1110f69bf9bc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1263,7 +1263,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt) struct flowi4 fl4 = { .daddr = iph->daddr, .saddr = iph->saddr, - .flowi4_tos = RT_TOS(iph->tos), + .flowi4_tos = iph->tos & IPTOS_RT_MASK, .flowi4_oif = rt->dst.dev->ifindex, .flowi4_iif = skb->dev->ifindex, .flowi4_mark = skb->mark, From d587d825424b6784ff7d7519efd1b827b09aa501 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 18 Jul 2024 14:43:48 +0100 Subject: [PATCH 13/34] l2tp: make session IDR and tunnel session list coherent Modify l2tp_session_register and l2tp_session_unhash so that the session IDR and tunnel session lists remain coherent. To do so, hold the session IDR lock and the tunnel's session list lock when making any changes to either list. Without this change, a rare race condition could hit the WARN_ON_ONCE in l2tp_session_unhash if a thread replaced the IDR entry while another thread was registering the same ID. [ 7126.151795][T17511] WARNING: CPU: 3 PID: 17511 at net/l2tp/l2tp_core.c:1282 l2tp_session_delete.part.0+0x87e/0xbc0 [ 7126.163754][T17511] ? show_regs+0x93/0xa0 [ 7126.164157][T17511] ? __warn+0xe5/0x3c0 [ 7126.164536][T17511] ? l2tp_session_delete.part.0+0x87e/0xbc0 [ 7126.165070][T17511] ? report_bug+0x2e1/0x500 [ 7126.165486][T17511] ? l2tp_session_delete.part.0+0x87e/0xbc0 [ 7126.166013][T17511] ? handle_bug+0x99/0x130 [ 7126.166428][T17511] ? exc_invalid_op+0x35/0x80 [ 7126.166890][T17511] ? asm_exc_invalid_op+0x1a/0x20 [ 7126.167372][T17511] ? l2tp_session_delete.part.0+0x87d/0xbc0 [ 7126.167900][T17511] ? l2tp_session_delete.part.0+0x87e/0xbc0 [ 7126.168429][T17511] ? __local_bh_enable_ip+0xa4/0x120 [ 7126.168917][T17511] l2tp_session_delete+0x40/0x50 [ 7126.169369][T17511] pppol2tp_release+0x1a1/0x3f0 [ 7126.169817][T17511] __sock_release+0xb3/0x270 [ 7126.170247][T17511] ? __pfx_sock_close+0x10/0x10 [ 7126.170697][T17511] sock_close+0x1c/0x30 [ 7126.171087][T17511] __fput+0x40b/0xb90 [ 7126.171470][T17511] task_work_run+0x16c/0x260 [ 7126.171897][T17511] ? __pfx_task_work_run+0x10/0x10 [ 7126.172362][T17511] ? srso_alias_return_thunk+0x5/0xfbef5 [ 7126.172863][T17511] ? do_raw_spin_unlock+0x174/0x230 [ 7126.173348][T17511] do_exit+0xaae/0x2b40 [ 7126.173730][T17511] ? srso_alias_return_thunk+0x5/0xfbef5 [ 7126.174235][T17511] ? __pfx_lock_release+0x10/0x10 [ 7126.174690][T17511] ? srso_alias_return_thunk+0x5/0xfbef5 [ 7126.175190][T17511] ? do_raw_spin_lock+0x12c/0x2b0 [ 7126.175650][T17511] ? __pfx_do_exit+0x10/0x10 [ 7126.176072][T17511] ? _raw_spin_unlock_irq+0x23/0x50 [ 7126.176543][T17511] do_group_exit+0xd3/0x2a0 [ 7126.176990][T17511] __x64_sys_exit_group+0x3e/0x50 [ 7126.177456][T17511] x64_sys_call+0x1821/0x1830 [ 7126.177895][T17511] do_syscall_64+0xcb/0x250 [ 7126.178317][T17511] entry_SYSCALL_64_after_hwframe+0x77/0x7f Fixes: aa5e17e1f5ec ("l2tp: store l2tpv3 sessions in per-net IDR") Signed-off-by: James Chapman Signed-off-by: Tom Parkin Reviewed-by: Simon Horman Link: https://patch.msgid.link/20240718134348.289865-1-jchapman@katalix.com Signed-off-by: Paolo Abeni --- net/l2tp/l2tp_core.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 1c1decce7f06..c80ab3f26084 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -441,14 +441,15 @@ int l2tp_session_register(struct l2tp_session *session, int err; spin_lock_bh(&tunnel->list_lock); + spin_lock_bh(&pn->l2tp_session_idr_lock); + if (!tunnel->acpt_newsess) { err = -ENODEV; - goto err_tlock; + goto out; } if (tunnel->version == L2TP_HDR_VER_3) { session_key = session->session_id; - spin_lock_bh(&pn->l2tp_session_idr_lock); err = idr_alloc_u32(&pn->l2tp_v3_session_idr, NULL, &session_key, session_key, GFP_ATOMIC); /* IP encap expects session IDs to be globally unique, while @@ -462,43 +463,36 @@ int l2tp_session_register(struct l2tp_session *session, err = l2tp_session_collision_add(pn, session, other_session); } - spin_unlock_bh(&pn->l2tp_session_idr_lock); } else { session_key = l2tp_v2_session_key(tunnel->tunnel_id, session->session_id); - spin_lock_bh(&pn->l2tp_session_idr_lock); err = idr_alloc_u32(&pn->l2tp_v2_session_idr, NULL, &session_key, session_key, GFP_ATOMIC); - spin_unlock_bh(&pn->l2tp_session_idr_lock); } if (err) { if (err == -ENOSPC) err = -EEXIST; - goto err_tlock; + goto out; } l2tp_tunnel_inc_refcount(tunnel); - list_add(&session->list, &tunnel->session_list); - spin_unlock_bh(&tunnel->list_lock); - spin_lock_bh(&pn->l2tp_session_idr_lock); if (tunnel->version == L2TP_HDR_VER_3) { if (!other_session) idr_replace(&pn->l2tp_v3_session_idr, session, session_key); } else { idr_replace(&pn->l2tp_v2_session_idr, session, session_key); } + +out: spin_unlock_bh(&pn->l2tp_session_idr_lock); - - trace_register_session(session); - - return 0; - -err_tlock: spin_unlock_bh(&tunnel->list_lock); + if (!err) + trace_register_session(session); + return err; } EXPORT_SYMBOL_GPL(l2tp_session_register); @@ -1260,13 +1254,13 @@ static void l2tp_session_unhash(struct l2tp_session *session) struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); struct l2tp_session *removed = session; - /* Remove from the per-tunnel list */ spin_lock_bh(&tunnel->list_lock); + spin_lock_bh(&pn->l2tp_session_idr_lock); + + /* Remove from the per-tunnel list */ list_del_init(&session->list); - spin_unlock_bh(&tunnel->list_lock); /* Remove from per-net IDR */ - spin_lock_bh(&pn->l2tp_session_idr_lock); if (tunnel->version == L2TP_HDR_VER_3) { if (hash_hashed(&session->hlist)) l2tp_session_collision_del(pn, session); @@ -1280,7 +1274,9 @@ static void l2tp_session_unhash(struct l2tp_session *session) session_key); } WARN_ON_ONCE(removed && removed != session); + spin_unlock_bh(&pn->l2tp_session_idr_lock); + spin_unlock_bh(&tunnel->list_lock); synchronize_rcu(); } From 39a9c25bcdfb5e88995841c47439b74cac74a527 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 19 Jul 2024 22:38:31 +0200 Subject: [PATCH 14/34] net: airoha: Fix MBI_RX_AGE_SEL_MASK definition Fix copy-paste error in MBI_RX_AGE_SEL_MASK macro definition Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Link: https://patch.msgid.link/d27d0465be1bff3369e886e5f10c4d37fefc4934.1721419930.git.lorenzo@kernel.org Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/airoha_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c index 16761fde6c6c..1c5b85a86df1 100644 --- a/drivers/net/ethernet/mediatek/airoha_eth.c +++ b/drivers/net/ethernet/mediatek/airoha_eth.c @@ -249,7 +249,7 @@ #define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) #define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) -#define MBI_RX_AGE_SEL_MASK GENMASK(18, 17) +#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) #define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) #define REG_GDM3_FWD_CFG GDM3_BASE From 3ba359c0cd6eb5ea772125a7aededb4a2d516684 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Jul 2024 09:41:18 -0700 Subject: [PATCH 15/34] net: bonding: correctly annotate RCU in bond_should_notify_peers() RCU use in bond_should_notify_peers() looks wrong, since it does rcu_dereference(), leaves the critical section, and uses the pointer after that. Luckily, it's called either inside a nested RCU critical section or with the RTNL held. Annotate it with rcu_dereference_rtnl() instead, and remove the inner RCU critical section. Fixes: 4cb4f97b7e36 ("bonding: rebuild the lock use for bond_mii_monitor()") Reviewed-by: Jiri Pirko Signed-off-by: Johannes Berg Acked-by: Jay Vosburgh Link: https://patch.msgid.link/20240719094119.35c62455087d.I68eb9c0f02545b364b79a59f2110f2cf5682a8e2@changeid Signed-off-by: Paolo Abeni --- drivers/net/bonding/bond_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index af9ddd3902cc..1cd92c12e782 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1121,13 +1121,10 @@ static struct slave *bond_find_best_slave(struct bonding *bond) return bestslave; } +/* must be called in RCU critical section or with RTNL held */ static bool bond_should_notify_peers(struct bonding *bond) { - struct slave *slave; - - rcu_read_lock(); - slave = rcu_dereference(bond->curr_active_slave); - rcu_read_unlock(); + struct slave *slave = rcu_dereference_rtnl(bond->curr_active_slave); if (!slave || !bond->send_peer_notif || bond->send_peer_notif % From 6ebbe97a488179f5dc85f2f1e0c89b486e99ee97 Mon Sep 17 00:00:00 2001 From: Ahmed Zaki Date: Fri, 14 Jun 2024 07:18:42 -0600 Subject: [PATCH 16/34] ice: Add a per-VF limit on number of FDIR filters While the iavf driver adds a s/w limit (128) on the number of FDIR filters that the VF can request, a malicious VF driver can request more than that and exhaust the resources for other VFs. Add a similar limit in ice. CC: stable@vger.kernel.org Fixes: 1f7ea1cd6a37 ("ice: Enable FDIR Configure for AVF") Reviewed-by: Przemek Kitszel Suggested-by: Sridhar Samudrala Signed-off-by: Ahmed Zaki Reviewed-by: Wojciech Drewek Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- .../net/ethernet/intel/ice/ice_ethtool_fdir.c | 2 +- drivers/net/ethernet/intel/ice/ice_fdir.h | 3 +++ .../net/ethernet/intel/ice/ice_virtchnl_fdir.c | 16 ++++++++++++++++ .../net/ethernet/intel/ice/ice_virtchnl_fdir.h | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c index e3cab8e98f52..5412eff8ef23 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c @@ -534,7 +534,7 @@ ice_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp, * * Returns the number of available flow director filters to this VSI */ -static int ice_fdir_num_avail_fltr(struct ice_hw *hw, struct ice_vsi *vsi) +int ice_fdir_num_avail_fltr(struct ice_hw *hw, struct ice_vsi *vsi) { u16 vsi_num = ice_get_hw_vsi_num(hw, vsi->idx); u16 num_guar; diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.h b/drivers/net/ethernet/intel/ice/ice_fdir.h index 021ecbac7848..ab5b118daa2d 100644 --- a/drivers/net/ethernet/intel/ice/ice_fdir.h +++ b/drivers/net/ethernet/intel/ice/ice_fdir.h @@ -207,6 +207,8 @@ struct ice_fdir_base_pkt { const u8 *tun_pkt; }; +struct ice_vsi; + int ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id); int ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id); int ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr); @@ -218,6 +220,7 @@ int ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input, u8 *pkt, bool frag, bool tun); int ice_get_fdir_cnt_all(struct ice_hw *hw); +int ice_fdir_num_avail_fltr(struct ice_hw *hw, struct ice_vsi *vsi); bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input); bool ice_fdir_has_frag(enum ice_fltr_ptype flow); struct ice_fdir_fltr * diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c index 8e4ff3af86c6..b4feb0927687 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c @@ -536,6 +536,8 @@ static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir) fdir->fdir_fltr_cnt[flow][0] = 0; fdir->fdir_fltr_cnt[flow][1] = 0; } + + fdir->fdir_fltr_cnt_total = 0; } /** @@ -1560,6 +1562,7 @@ ice_vc_add_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx, resp->status = status; resp->flow_id = conf->flow_id; vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]++; + vf->fdir.fdir_fltr_cnt_total++; ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, (u8 *)resp, len); @@ -1624,6 +1627,7 @@ ice_vc_del_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx, resp->status = status; ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]--; + vf->fdir.fdir_fltr_cnt_total--; ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, (u8 *)resp, len); @@ -1790,6 +1794,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) struct virtchnl_fdir_add *stat = NULL; struct virtchnl_fdir_fltr_conf *conf; enum virtchnl_status_code v_ret; + struct ice_vsi *vf_vsi; struct device *dev; struct ice_pf *pf; int is_tun = 0; @@ -1798,6 +1803,17 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) pf = vf->pf; dev = ice_pf_to_dev(pf); + vf_vsi = ice_get_vf_vsi(vf); + +#define ICE_VF_MAX_FDIR_FILTERS 128 + if (!ice_fdir_num_avail_fltr(&pf->hw, vf_vsi) || + vf->fdir.fdir_fltr_cnt_total >= ICE_VF_MAX_FDIR_FILTERS) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + dev_err(dev, "Max number of FDIR filters for VF %d is reached\n", + vf->vf_id); + goto err_exit; + } + ret = ice_vc_fdir_param_check(vf, fltr->vsi_id); if (ret) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.h index c5bcc8d7481c..ac6dcab454b4 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.h +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.h @@ -29,6 +29,7 @@ struct ice_vf_fdir_ctx { struct ice_vf_fdir { u16 fdir_fltr_cnt[ICE_FLTR_PTYPE_MAX][ICE_FD_HW_SEG_MAX]; int prof_entry_cnt[ICE_FLTR_PTYPE_MAX][ICE_FD_HW_SEG_MAX]; + u16 fdir_fltr_cnt_total; struct ice_fd_hw_prof **fdir_prof; struct idr fdir_rule_idr; From 19abb9c2b900bad59e0a9818d6c83bb4cc875437 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Mon, 1 Jul 2024 11:05:46 +0200 Subject: [PATCH 17/34] ice: Fix recipe read procedure When ice driver reads recipes from firmware information about need_pass_l2 and allow_pass_l2 flags is not stored correctly. Those flags are stored as one bit each in ice_sw_recipe structure. Because of that, the result of checking a flag has to be casted to bool. Note that the need_pass_l2 flag currently works correctly, because it's stored in the first bit. Fixes: bccd9bce29e0 ("ice: Add guard rule when creating FDB in switchdev") Reviewed-by: Marcin Szycik Reviewed-by: Przemek Kitszel Signed-off-by: Wojciech Drewek Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_switch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 3caafcdc301f..fe8847184cb1 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -2400,10 +2400,10 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid, /* Propagate some data to the recipe database */ recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; - recps[idx].need_pass_l2 = root_bufs.content.act_ctrl & - ICE_AQ_RECIPE_ACT_NEED_PASS_L2; - recps[idx].allow_pass_l2 = root_bufs.content.act_ctrl & - ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2; + recps[idx].need_pass_l2 = !!(root_bufs.content.act_ctrl & + ICE_AQ_RECIPE_ACT_NEED_PASS_L2); + recps[idx].allow_pass_l2 = !!(root_bufs.content.act_ctrl & + ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2); bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS); if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) { set_bit(root_bufs.content.result_indx & From a16909ae9982e931841c456061cb57fbaec9c59e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 19 Jul 2024 13:19:26 +0200 Subject: [PATCH 18/34] netfilter: nft_set_pipapo_avx2: disable softinterrupts We need to disable softinterrupts, else we get following problem: 1. pipapo_avx2 called from process context; fpu usable 2. preempt_disable() called, pcpu scratchmap in use 3. softirq handles rx or tx, we re-enter pipapo_avx2 4. fpu busy, fallback to generic non-avx version 5. fallback reuses scratch map and index, which are in use by the preempted process Handle this same way as generic version by first disabling softinterrupts while the scratchmap is in use. Fixes: f0b3d338064e ("netfilter: nft_set_pipapo_avx2: Add irq_fpu_usable() check, fallback to non-AVX2 version") Cc: Stefano Brivio Signed-off-by: Florian Westphal Reviewed-by: Stefano Brivio Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_set_pipapo_avx2.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c index 8910a5ac7ed1..b8d3c3213efe 100644 --- a/net/netfilter/nft_set_pipapo_avx2.c +++ b/net/netfilter/nft_set_pipapo_avx2.c @@ -1139,8 +1139,14 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, bool map_index; int i, ret = 0; - if (unlikely(!irq_fpu_usable())) - return nft_pipapo_lookup(net, set, key, ext); + local_bh_disable(); + + if (unlikely(!irq_fpu_usable())) { + bool fallback_res = nft_pipapo_lookup(net, set, key, ext); + + local_bh_enable(); + return fallback_res; + } m = rcu_dereference(priv->match); @@ -1155,6 +1161,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, scratch = *raw_cpu_ptr(m->scratch); if (unlikely(!scratch)) { kernel_fpu_end(); + local_bh_enable(); return false; } @@ -1235,6 +1242,7 @@ out: if (i % 2) scratch->map_index = !map_index; kernel_fpu_end(); + local_bh_enable(); return ret >= 0; } From fa96c6baef1b5385e2f0c0677b32b3839e716076 Mon Sep 17 00:00:00 2001 From: Shigeru Yoshida Date: Tue, 16 Jul 2024 11:09:05 +0900 Subject: [PATCH 19/34] tipc: Return non-zero value from tipc_udp_addr2str() on error tipc_udp_addr2str() should return non-zero value if the UDP media address is invalid. Otherwise, a buffer overflow access can occur in tipc_media_addr_printf(). Fix this by returning 1 on an invalid UDP media address. Fixes: d0f91938bede ("tipc: add ip/udp media type") Signed-off-by: Shigeru Yoshida Reviewed-by: Tung Nguyen Signed-off-by: David S. Miller --- net/tipc/udp_media.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index b849a3d133a0..439f75539977 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -135,8 +135,11 @@ static int tipc_udp_addr2str(struct tipc_media_addr *a, char *buf, int size) snprintf(buf, size, "%pI4:%u", &ua->ipv4, ntohs(ua->port)); else if (ntohs(ua->proto) == ETH_P_IPV6) snprintf(buf, size, "%pI6:%u", &ua->ipv6, ntohs(ua->port)); - else + else { pr_err("Invalid UDP media address\n"); + return 1; + } + return 0; } From 863ff546fb62a8fa75757a30794ab6ec6cc4bab7 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Tue, 23 Jul 2024 16:22:52 +0800 Subject: [PATCH 20/34] selftests: forwarding: skip if kernel not support setting bridge fdb learning limit If the testing kernel doesn't support setting fdb_max_learned or show fdb_n_learned, just skip it. Or we will get errors like ./bridge_fdb_learning_limit.sh: line 218: [: null: integer expression expected ./bridge_fdb_learning_limit.sh: line 225: [: null: integer expression expected Fixes: 6f84090333bb ("selftests: forwarding: bridge_fdb_learning_limit: Add a new selftest") Signed-off-by: Hangbin Liu Acked-by: Nikolay Aleksandrov Reviewed-by: Johannes Nixdorf Signed-off-by: David S. Miller --- .../forwarding/bridge_fdb_learning_limit.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/testing/selftests/net/forwarding/bridge_fdb_learning_limit.sh b/tools/testing/selftests/net/forwarding/bridge_fdb_learning_limit.sh index 0760a34b7114..a21b7085da2e 100755 --- a/tools/testing/selftests/net/forwarding/bridge_fdb_learning_limit.sh +++ b/tools/testing/selftests/net/forwarding/bridge_fdb_learning_limit.sh @@ -178,6 +178,22 @@ fdb_del() check_err $? "Failed to remove a FDB entry of type ${type}" } +check_fdb_n_learned_support() +{ + if ! ip link help bridge 2>&1 | grep -q "fdb_max_learned"; then + echo "SKIP: iproute2 too old, missing bridge max learned support" + exit $ksft_skip + fi + + ip link add dev br0 type bridge + local learned=$(fdb_get_n_learned) + ip link del dev br0 + if [ "$learned" == "null" ]; then + echo "SKIP: kernel too old; bridge fdb_n_learned feature not supported." + exit $ksft_skip + fi +} + check_accounting_one_type() { local type=$1 is_counted=$2 overrides_learned=$3 @@ -274,6 +290,8 @@ check_limit() done } +check_fdb_n_learned_support + trap cleanup EXIT setup_prepare From e9dbebae2e3c338122716914fe105458f41e3a4a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 23 Jul 2024 14:29:27 +0100 Subject: [PATCH 21/34] net: stmmac: Correct byte order of perfect_match The perfect_match parameter of the update_vlan_hash operation is __le16, and is correctly converted from host byte-order in the lone caller, stmmac_vlan_update(). However, the implementations of this caller, dwxgmac2_update_vlan_hash() and dwxgmac2_update_vlan_hash(), both treat this parameter as host byte order, using the following pattern: u32 value = ... ... writel(value | perfect_match, ...); This is not correct because both: 1) value is host byte order; and 2) writel expects a host byte order value as it's first argument I believe that this will break on big endian systems. And I expect it has gone unnoticed by only being exercised on little endian systems. The approach taken by this patch is to update the callback, and it's caller to simply use a host byte order value. Flagged by Sparse. Compile tested only. Fixes: c7ab0b8088d7 ("net: stmmac: Fallback to VLAN Perfect filtering if HASH is not available") Signed-off-by: Simon Horman Reviewed-by: Maxime Chevallier Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index dbd9f93b2460..f98741d2607e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -977,7 +977,7 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable) } static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash, - __le16 perfect_match, bool is_double) + u16 perfect_match, bool is_double) { void __iomem *ioaddr = hw->pcsr; u32 value; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 6a987cf598e4..f196cd99d510 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -615,7 +615,7 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw, } static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, - __le16 perfect_match, bool is_double) + u16 perfect_match, bool is_double) { void __iomem *ioaddr = hw->pcsr; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 97934ccba5b1..e53c32362774 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -393,7 +393,7 @@ struct stmmac_ops { struct stmmac_rss *cfg, u32 num_rxq); /* VLAN */ void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, - __le16 perfect_match, bool is_double); + u16 perfect_match, bool is_double); void (*enable_vlan)(struct mac_device_info *hw, u32 type); void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc, struct sk_buff *skb); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4b6a359e5a94..12689774d755 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6641,7 +6641,7 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le) static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) { u32 crc, hash = 0; - __le16 pmatch = 0; + u16 pmatch = 0; int count = 0; u16 vid = 0; @@ -6656,7 +6656,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) if (count > 2) /* VID = 0 always passes filter */ return -EOPNOTSUPP; - pmatch = cpu_to_le16(vid); + pmatch = vid; hash = 0; } From 6d745cd0e9720282cd291d36b9db528aea18add2 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 23 Jul 2024 18:04:16 +0200 Subject: [PATCH 22/34] net: nexthop: Initialize all fields in dumped nexthops struct nexthop_grp contains two reserved fields that are not initialized by nla_put_nh_group(), and carry garbage. This can be observed e.g. with strace (edited for clarity): # ip nexthop add id 1 dev lo # ip nexthop add id 101 group 1 # strace -e recvmsg ip nexthop get id 101 ... recvmsg(... [{nla_len=12, nla_type=NHA_GROUP}, [{id=1, weight=0, resvd1=0x69, resvd2=0x67}]] ...) = 52 The fields are reserved and therefore not currently used. But as they are, they leak kernel memory, and the fact they are not just zero complicates repurposing of the fields for new ends. Initialize the full structure. Fixes: 430a049190de ("nexthop: Add support for nexthop groups") Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/nexthop.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 535856b0f0ed..6b9787ee8601 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -888,9 +888,10 @@ static int nla_put_nh_group(struct sk_buff *skb, struct nexthop *nh, p = nla_data(nla); for (i = 0; i < nhg->num_nh; ++i) { - p->id = nhg->nh_entries[i].nh->id; - p->weight = nhg->nh_entries[i].weight - 1; - p += 1; + *p++ = (struct nexthop_grp) { + .id = nhg->nh_entries[i].nh->id, + .weight = nhg->nh_entries[i].weight - 1, + }; } if (nhg->resilient && nla_put_nh_group_res(skb, nhg)) From 0fa9af961102cf3a4cbf591a50f376c8ab1cf443 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Tue, 23 Jul 2024 15:22:36 -0700 Subject: [PATCH 23/34] MAINTAINERS: Update bonding entry Update my email address, clarify support status, and delete the web site that hasn't been used in a long time. Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4a096207f8b4..005d4c30175d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3879,11 +3879,10 @@ F: include/net/bluetooth/ F: net/bluetooth/ BONDING DRIVER -M: Jay Vosburgh +M: Jay Vosburgh M: Andy Gospodarek L: netdev@vger.kernel.org -S: Supported -W: http://sourceforge.net/projects/bonding/ +S: Maintained F: Documentation/networking/bonding.rst F: drivers/net/bonding/ F: include/net/bond* From 7c938e438c56dbbe1aceb128c46cebb340a3c06b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 23 Jul 2024 15:34:05 -0700 Subject: [PATCH 24/34] MAINTAINERS: make Breno the netconsole maintainer netconsole has no maintainer, and Breno has been working on improving it consistently for some time. So I think we found the maintainer :) Acked-by: Paolo Abeni Reviewed-by: Eric Dumazet Signed-off-by: Jakub Kicinski Acked-by: Breno Leitao Signed-off-by: David S. Miller --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 005d4c30175d..7b6220f12ab1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15702,6 +15702,12 @@ S: Maintained F: Documentation/devicetree/bindings/hwmon/nuvoton,nct6775.yaml F: drivers/hwmon/nct6775-i2c.c +NETCONSOLE +M: Breno Leitao +S: Maintained +F: Documentation/networking/netconsole.rst +F: drivers/net/netconsole.c + NETDEVSIM M: Jakub Kicinski S: Maintained From 16f3a28cf5f876a7f3550d8f4c870a7b41bcfaef Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 24 Jul 2024 01:05:23 -0700 Subject: [PATCH 25/34] net: mediatek: Fix potential NULL pointer dereference in dummy net_device handling Move the freeing of the dummy net_device from mtk_free_dev() to mtk_remove(). Previously, if alloc_netdev_dummy() failed in mtk_probe(), eth->dummy_dev would be NULL. The error path would then call mtk_free_dev(), which in turn called free_netdev() assuming dummy_dev was allocated (but it was not), potentially causing a NULL pointer dereference. By moving free_netdev() to mtk_remove(), we ensure it's only called when mtk_probe() has succeeded and dummy_dev is fully allocated. This addresses a potential NULL pointer dereference detected by Smatch[1]. Fixes: b209bd6d0bff ("net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/4160f4e0-cbef-4a22-8b5d-42c4d399e1f7@stanley.mountain/ [1] Suggested-by: Dan Carpenter Reviewed-by: Dan Carpenter Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://patch.msgid.link/20240724080524.2734499-1-leitao@debian.org Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 0cc2dd85652f..16ca427cf4c3 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -4223,8 +4223,6 @@ static int mtk_free_dev(struct mtk_eth *eth) metadata_dst_free(eth->dsa_meta[i]); } - free_netdev(eth->dummy_dev); - return 0; } @@ -5090,6 +5088,7 @@ static void mtk_remove(struct platform_device *pdev) netif_napi_del(ð->tx_napi); netif_napi_del(ð->rx_napi); mtk_cleanup(eth); + free_netdev(eth->dummy_dev); mtk_mdio_cleanup(eth); } From fa5ef655615a01533035c6139248c5b33aa27028 Mon Sep 17 00:00:00 2001 From: Fred Li Date: Fri, 19 Jul 2024 10:46:53 +0800 Subject: [PATCH 26/34] bpf: Fix a segment issue when downgrading gso_size Linearize the skb when downgrading gso_size because it may trigger a BUG_ON() later when the skb is segmented as described in [1,2]. Fixes: 2be7e212d5419 ("bpf: add bpf_skb_adjust_room helper") Signed-off-by: Fred Li Signed-off-by: Daniel Borkmann Reviewed-by: Willem de Bruijn Acked-by: Daniel Borkmann Link: https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com [1] Link: https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch [2] Link: https://lore.kernel.org/bpf/20240719024653.77006-1-dracodingfly@gmail.com --- net/core/filter.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 4cf1d34f7617..f3c72cf86099 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3548,13 +3548,20 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, if (skb_is_gso(skb)) { struct skb_shared_info *shinfo = skb_shinfo(skb); - /* Due to header grow, MSS needs to be downgraded. */ - if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) - skb_decrease_gso_size(shinfo, len_diff); - /* Header must be checked, and gso_segs recomputed. */ shinfo->gso_type |= gso_type; shinfo->gso_segs = 0; + + /* Due to header growth, MSS needs to be downgraded. + * There is a BUG_ON() when segmenting the frag_list with + * head_frag true, so linearize the skb after downgrading + * the MSS. + */ + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) { + skb_decrease_gso_size(shinfo, len_diff); + if (shinfo->frag_list) + return skb_linearize(skb); + } } return 0; From d5e726d9143c5624135f5dc9e4069799adeef734 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Fri, 12 Jul 2024 18:52:51 -0700 Subject: [PATCH 27/34] xsk: Require XDP_UMEM_TX_METADATA_LEN to actuate tx_metadata_len Julian reports that commit 341ac980eab9 ("xsk: Support tx_metadata_len") can break existing use cases which don't zero-initialize xdp_umem_reg padding. Introduce new XDP_UMEM_TX_METADATA_LEN to make sure we interpret the padding as tx_metadata_len only when being explicitly asked. Fixes: 341ac980eab9 ("xsk: Support tx_metadata_len") Reported-by: Julian Schindel Signed-off-by: Stanislav Fomichev Signed-off-by: Daniel Borkmann Reviewed-by: Maciej Fijalkowski Link: https://lore.kernel.org/bpf/20240713015253.121248-2-sdf@fomichev.me --- Documentation/networking/xsk-tx-metadata.rst | 16 ++++++++++------ include/uapi/linux/if_xdp.h | 4 ++++ net/xdp/xdp_umem.c | 9 ++++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Documentation/networking/xsk-tx-metadata.rst b/Documentation/networking/xsk-tx-metadata.rst index bd033fe95cca..e76b0cfc32f7 100644 --- a/Documentation/networking/xsk-tx-metadata.rst +++ b/Documentation/networking/xsk-tx-metadata.rst @@ -11,12 +11,16 @@ metadata on the receive side. General Design ============== -The headroom for the metadata is reserved via ``tx_metadata_len`` in -``struct xdp_umem_reg``. The metadata length is therefore the same for -every socket that shares the same umem. The metadata layout is a fixed UAPI, -refer to ``union xsk_tx_metadata`` in ``include/uapi/linux/if_xdp.h``. -Thus, generally, the ``tx_metadata_len`` field above should contain -``sizeof(union xsk_tx_metadata)``. +The headroom for the metadata is reserved via ``tx_metadata_len`` and +``XDP_UMEM_TX_METADATA_LEN`` flag in ``struct xdp_umem_reg``. The metadata +length is therefore the same for every socket that shares the same umem. +The metadata layout is a fixed UAPI, refer to ``union xsk_tx_metadata`` in +``include/uapi/linux/if_xdp.h``. Thus, generally, the ``tx_metadata_len`` +field above should contain ``sizeof(union xsk_tx_metadata)``. + +Note that in the original implementation the ``XDP_UMEM_TX_METADATA_LEN`` +flag was not required. Applications might attempt to create a umem +with a flag first and if it fails, do another attempt without a flag. The headroom and the metadata itself should be located right before ``xdp_desc->addr`` in the umem frame. Within a frame, the metadata diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h index d31698410410..42ec5ddaab8d 100644 --- a/include/uapi/linux/if_xdp.h +++ b/include/uapi/linux/if_xdp.h @@ -41,6 +41,10 @@ */ #define XDP_UMEM_TX_SW_CSUM (1 << 1) +/* Request to reserve tx_metadata_len bytes of per-chunk metadata. + */ +#define XDP_UMEM_TX_METADATA_LEN (1 << 2) + struct sockaddr_xdp { __u16 sxdp_family; __u16 sxdp_flags; diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index caa340134b0e..9f76ca591d54 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -151,6 +151,7 @@ static int xdp_umem_account_pages(struct xdp_umem *umem) #define XDP_UMEM_FLAGS_VALID ( \ XDP_UMEM_UNALIGNED_CHUNK_FLAG | \ XDP_UMEM_TX_SW_CSUM | \ + XDP_UMEM_TX_METADATA_LEN | \ 0) static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) @@ -204,8 +205,11 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) if (headroom >= chunk_size - XDP_PACKET_HEADROOM) return -EINVAL; - if (mr->tx_metadata_len >= 256 || mr->tx_metadata_len % 8) - return -EINVAL; + if (mr->flags & XDP_UMEM_TX_METADATA_LEN) { + if (mr->tx_metadata_len >= 256 || mr->tx_metadata_len % 8) + return -EINVAL; + umem->tx_metadata_len = mr->tx_metadata_len; + } umem->size = size; umem->headroom = headroom; @@ -215,7 +219,6 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) umem->pgs = NULL; umem->user = NULL; umem->flags = mr->flags; - umem->tx_metadata_len = mr->tx_metadata_len; INIT_LIST_HEAD(&umem->xsk_dma_list); refcount_set(&umem->users, 1); From 9b9969c40b0d63a8fca434d4ea01c60a39699aa3 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Fri, 12 Jul 2024 18:52:52 -0700 Subject: [PATCH 28/34] selftests/bpf: Add XDP_UMEM_TX_METADATA_LEN to XSK TX metadata test This flag is now required to use tx_metadata_len. Fixes: 40808a237d9c ("selftests/bpf: Add TX side to xdp_metadata") Reported-by: Julian Schindel Signed-off-by: Stanislav Fomichev Signed-off-by: Daniel Borkmann Reviewed-by: Maciej Fijalkowski Link: https://lore.kernel.org/bpf/20240713015253.121248-3-sdf@fomichev.me --- tools/include/uapi/linux/if_xdp.h | 4 ++++ tools/testing/selftests/bpf/prog_tests/xdp_metadata.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/if_xdp.h b/tools/include/uapi/linux/if_xdp.h index 638c606dfa74..2f082b01ff22 100644 --- a/tools/include/uapi/linux/if_xdp.h +++ b/tools/include/uapi/linux/if_xdp.h @@ -41,6 +41,10 @@ */ #define XDP_UMEM_TX_SW_CSUM (1 << 1) +/* Request to reserve tx_metadata_len bytes of per-chunk metadata. + */ +#define XDP_UMEM_TX_METADATA_LEN (1 << 2) + struct sockaddr_xdp { __u16 sxdp_family; __u16 sxdp_flags; diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c index f76b5d67a3ee..c87ee2bf558c 100644 --- a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c +++ b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c @@ -68,7 +68,8 @@ static int open_xsk(int ifindex, struct xsk *xsk) .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS, .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS, .frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE, - .flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG | XDP_UMEM_TX_SW_CSUM, + .flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG | XDP_UMEM_TX_SW_CSUM | + XDP_UMEM_TX_METADATA_LEN, .tx_metadata_len = sizeof(struct xsk_tx_metadata), }; __u32 idx; From c1668292689ad2ee16c9c1750a8044b0b0aad663 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Wed, 24 Jul 2024 12:25:16 +0200 Subject: [PATCH 29/34] tcp: process the 3rd ACK with sk_socket for TFO/MPTCP The 'Fixes' commit recently changed the behaviour of TCP by skipping the processing of the 3rd ACK when a sk->sk_socket is set. The goal was to skip tcp_ack_snd_check() in tcp_rcv_state_process() not to send an unnecessary ACK in case of simultaneous connect(). Unfortunately, that had an impact on TFO and MPTCP. I started to look at the impact on MPTCP, because the MPTCP CI found some issues with the MPTCP Packetdrill tests [1]. Then Paolo Abeni suggested me to look at the impact on TFO with "plain" TCP. For MPTCP, when receiving the 3rd ACK of a request adding a new path (MP_JOIN), sk->sk_socket will be set, and point to the MPTCP sock that has been created when the MPTCP connection got established before with the first path. The newly added 'goto' will then skip the processing of the segment text (step 7) and not go through tcp_data_queue() where the MPTCP options are validated, and some actions are triggered, e.g. sending the MPJ 4th ACK [2] as demonstrated by the new errors when running a packetdrill test [3] establishing a second subflow. This doesn't fully break MPTCP, mainly the 4th MPJ ACK that will be delayed. Still, we don't want to have this behaviour as it delays the switch to the fully established mode, and invalid MPTCP options in this 3rd ACK will not be caught any more. This modification also affects the MPTCP + TFO feature as well, and being the reason why the selftests started to be unstable the last few days [4]. For TFO, the existing 'basic-cookie-not-reqd' test [5] was no longer passing: if the 3rd ACK contains data, and the connection is accept()ed before receiving them, these data would no longer be processed, and thus not ACKed. One last thing about MPTCP, in case of simultaneous connect(), a fallback to TCP will be done, which seems fine: `../common/defaults.sh` 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_MPTCP) = 3 +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) +0 > S 0:0(0) +0 < S 0:0(0) win 1000 +0 > S. 0:0(0) ack 1 +0 < S. 0:0(0) ack 1 win 65535 +0 > . 1:1(0) ack 1 Simultaneous SYN-data crossing is also not supported by TFO, see [6]. Kuniyuki Iwashima suggested to restrict the processing to SYN+ACK only: that's a more generic solution than the one initially proposed, and also enough to fix the issues described above. Later on, Eric Dumazet mentioned that an ACK should still be sent in reaction to the second SYN+ACK that is received: not sending a DUPACK here seems wrong and could hurt: 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) +0 > S 0:0(0) +0 < S 0:0(0) win 1000 +0 > S. 0:0(0) ack 1 +0 < S. 0:0(0) ack 1 win 1000 +0 > . 1:1(0) ack 1 // <== Here So in this version, the 'goto consume' is dropped, to always send an ACK when switching from TCP_SYN_RECV to TCP_ESTABLISHED. This ACK will be seen as a DUPACK -- with DSACK if SACK has been negotiated -- in case of simultaneous SYN crossing: that's what is expected here. Link: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/9936227696 [1] Link: https://datatracker.ietf.org/doc/html/rfc8684#fig_tokens [2] Link: https://github.com/multipath-tcp/packetdrill/blob/mptcp-net-next/gtests/net/mptcp/syscalls/accept.pkt#L28 [3] Link: https://netdev.bots.linux.dev/contest.html?executor=vmksft-mptcp-dbg&test=mptcp-connect-sh [4] Link: https://github.com/google/packetdrill/blob/master/gtests/net/tcp/fastopen/server/basic-cookie-not-reqd.pkt#L21 [5] Link: https://github.com/google/packetdrill/blob/master/gtests/net/tcp/fastopen/client/simultaneous-fast-open.pkt [6] Fixes: 23e89e8ee7be ("tcp: Don't drop SYN+ACK for simultaneous connect().") Suggested-by: Paolo Abeni Suggested-by: Kuniyuki Iwashima Suggested-by: Eric Dumazet Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20240724-upstream-net-next-20240716-tcp-3rd-ack-consume-sk_socket-v3-1-d48339764ce9@kernel.org Signed-off-by: Paolo Abeni --- net/ipv4/tcp_input.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ff9ab3d01ced..454362e359da 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6819,9 +6819,6 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tcp_fast_path_on(tp); if (sk->sk_shutdown & SEND_SHUTDOWN) tcp_shutdown(sk, SEND_SHUTDOWN); - - if (sk->sk_socket) - goto consume; break; case TCP_FIN_WAIT1: { From b537633ce57b29f4c9687fea6f2d92e1ca7853fc Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 21 Jul 2024 05:35:54 +0000 Subject: [PATCH 30/34] bnxt_en: update xdp_rxq_info in queue restart logic When the netdev_rx_queue_restart() restarts queues, the bnxt_en driver updates(creates and deletes) a page_pool. But it doesn't update xdp_rxq_info, so the xdp_rxq_info is still connected to an old page_pool. So, bnxt_rx_ring_info->page_pool indicates a new page_pool, but bnxt_rx_ring_info->xdp_rxq is still connected to an old page_pool. An old page_pool is no longer used so it is supposed to be deleted by page_pool_destroy() but it isn't. Because the xdp_rxq_info is holding the reference count for it and the xdp_rxq_info is not updated, an old page_pool will not be deleted in the queue restart logic. Before restarting 1 queue: ./tools/net/ynl/samples/page-pool enp10s0f1np1[6] page pools: 4 (zombies: 0) refs: 8192 bytes: 33554432 (refs: 0 bytes: 0) recycling: 0.0% (alloc: 128:8048 recycle: 0:0) After restarting 1 queue: ./tools/net/ynl/samples/page-pool enp10s0f1np1[6] page pools: 5 (zombies: 0) refs: 10240 bytes: 41943040 (refs: 0 bytes: 0) recycling: 20.0% (alloc: 160:10080 recycle: 1920:128) Before restarting queues, an interface has 4 page_pools. After restarting one queue, an interface has 5 page_pools, but it should be 4, not 5. The reason is that queue restarting logic creates a new page_pool and an old page_pool is not deleted due to the absence of an update of xdp_rxq_info logic. Fixes: 2d694c27d32e ("bnxt_en: implement netdev_queue_mgmt_ops") Signed-off-by: Taehee Yoo Reviewed-by: David Wei Reviewed-by: Somnath Kotur Link: https://patch.msgid.link/20240721053554.1233549-1-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index bb3be33c1bbd..ffa74c26ee53 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4052,6 +4052,7 @@ static void bnxt_reset_rx_ring_struct(struct bnxt *bp, rxr->page_pool->p.napi = NULL; rxr->page_pool = NULL; + memset(&rxr->xdp_rxq, 0, sizeof(struct xdp_rxq_info)); ring = &rxr->rx_ring_struct; rmem = &ring->ring_mem; @@ -15018,6 +15019,16 @@ static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx) if (rc) return rc; + rc = xdp_rxq_info_reg(&clone->xdp_rxq, bp->dev, idx, 0); + if (rc < 0) + goto err_page_pool_destroy; + + rc = xdp_rxq_info_reg_mem_model(&clone->xdp_rxq, + MEM_TYPE_PAGE_POOL, + clone->page_pool); + if (rc) + goto err_rxq_info_unreg; + ring = &clone->rx_ring_struct; rc = bnxt_alloc_ring(bp, &ring->ring_mem); if (rc) @@ -15047,6 +15058,9 @@ err_free_rx_agg_ring: bnxt_free_ring(bp, &clone->rx_agg_ring_struct.ring_mem); err_free_rx_ring: bnxt_free_ring(bp, &clone->rx_ring_struct.ring_mem); +err_rxq_info_unreg: + xdp_rxq_info_unreg(&clone->xdp_rxq); +err_page_pool_destroy: clone->page_pool->p.napi = NULL; page_pool_destroy(clone->page_pool); clone->page_pool = NULL; @@ -15062,6 +15076,8 @@ static void bnxt_queue_mem_free(struct net_device *dev, void *qmem) bnxt_free_one_rx_ring(bp, rxr); bnxt_free_one_rx_agg_ring(bp, rxr); + xdp_rxq_info_unreg(&rxr->xdp_rxq); + page_pool_destroy(rxr->page_pool); rxr->page_pool = NULL; @@ -15145,6 +15161,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) rxr->rx_sw_agg_prod = clone->rx_sw_agg_prod; rxr->rx_next_cons = clone->rx_next_cons; rxr->page_pool = clone->page_pool; + rxr->xdp_rxq = clone->xdp_rxq; bnxt_copy_rx_ring(bp, rxr, clone); From 36e3b949e35964e22b9a57f960660fc599038dd4 Mon Sep 17 00:00:00 2001 From: Bailey Forrest Date: Wed, 24 Jul 2024 07:34:31 -0700 Subject: [PATCH 31/34] gve: Fix an edge case for TSO skb validity check The NIC requires each TSO segment to not span more than 10 descriptors. NIC further requires each descriptor to not exceed 16KB - 1 (GVE_TX_MAX_BUF_SIZE_DQO). The descriptors for an skb are generated by gve_tx_add_skb_no_copy_dqo() for DQO RDA queue format. gve_tx_add_skb_no_copy_dqo() loops through each skb frag and generates a descriptor for the entire frag if the frag size is not greater than GVE_TX_MAX_BUF_SIZE_DQO. If the frag size is greater than GVE_TX_MAX_BUF_SIZE_DQO, it is split into descriptor(s) of size GVE_TX_MAX_BUF_SIZE_DQO and a descriptor is generated for the remainder (frag size % GVE_TX_MAX_BUF_SIZE_DQO). gve_can_send_tso() checks if the descriptors thus generated for an skb would meet the requirement that each TSO-segment not span more than 10 descriptors. However, the current code misses an edge case when a TSO segment spans multiple descriptors within a large frag. This change fixes the edge case. gve_can_send_tso() relies on the assumption that max gso size (9728) is less than GVE_TX_MAX_BUF_SIZE_DQO and therefore within an skb fragment a TSO segment can never span more than 2 descriptors. Fixes: a57e5de476be ("gve: DQO: Add TX path") Signed-off-by: Praveen Kaligineedi Signed-off-by: Bailey Forrest Reviewed-by: Jeroen de Borst Cc: stable@vger.kernel.org Reviewed-by: Willem de Bruijn Link: https://patch.msgid.link/20240724143431.3343722-1-pkaligineedi@google.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/google/gve/gve_tx_dqo.c | 22 +++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c index 0b3cca3fc792..f879426cb552 100644 --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c @@ -866,22 +866,42 @@ static bool gve_can_send_tso(const struct sk_buff *skb) const int header_len = skb_tcp_all_headers(skb); const int gso_size = shinfo->gso_size; int cur_seg_num_bufs; + int prev_frag_size; int cur_seg_size; int i; cur_seg_size = skb_headlen(skb) - header_len; + prev_frag_size = skb_headlen(skb); cur_seg_num_bufs = cur_seg_size > 0; for (i = 0; i < shinfo->nr_frags; i++) { if (cur_seg_size >= gso_size) { cur_seg_size %= gso_size; cur_seg_num_bufs = cur_seg_size > 0; + + if (prev_frag_size > GVE_TX_MAX_BUF_SIZE_DQO) { + int prev_frag_remain = prev_frag_size % + GVE_TX_MAX_BUF_SIZE_DQO; + + /* If the last descriptor of the previous frag + * is less than cur_seg_size, the segment will + * span two descriptors in the previous frag. + * Since max gso size (9728) is less than + * GVE_TX_MAX_BUF_SIZE_DQO, it is impossible + * for the segment to span more than two + * descriptors. + */ + if (prev_frag_remain && + cur_seg_size > prev_frag_remain) + cur_seg_num_bufs++; + } } if (unlikely(++cur_seg_num_bufs > max_bufs_per_seg)) return false; - cur_seg_size += skb_frag_size(&shinfo->frags[i]); + prev_frag_size = skb_frag_size(&shinfo->frags[i]); + cur_seg_size += prev_frag_size; } return true; From 61ab751451f5ebd0b98e02276a44e23a10110402 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 24 Jul 2024 11:08:18 -0500 Subject: [PATCH 32/34] mISDN: Fix a use after free in hfcmulti_tx() Don't dereference *sp after calling dev_kfree_skb(*sp). Fixes: af69fb3a8ffa ("Add mISDN HFC multiport driver") Signed-off-by: Dan Carpenter Reviewed-by: Simon Horman Link: https://patch.msgid.link/8be65f5a-c2dd-4ba0-8a10-bfe5980b8cfb@stanley.mountain Signed-off-by: Jakub Kicinski --- drivers/isdn/hardware/mISDN/hfcmulti.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 0d2928d8aeae..e5a483fd9ad8 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -1901,7 +1901,7 @@ hfcmulti_dtmf(struct hfc_multi *hc) static void hfcmulti_tx(struct hfc_multi *hc, int ch) { - int i, ii, temp, len = 0; + int i, ii, temp, tmp_len, len = 0; int Zspace, z1, z2; /* must be int for calculation */ int Fspace, f1, f2; u_char *d; @@ -2122,14 +2122,15 @@ next_frame: HFC_wait_nodebug(hc); } + tmp_len = (*sp)->len; dev_kfree_skb(*sp); /* check for next frame */ if (bch && get_next_bframe(bch)) { - len = (*sp)->len; + len = tmp_len; goto next_frame; } if (dch && get_next_dframe(dch)) { - len = (*sp)->len; + len = tmp_len; goto next_frame; } From ed7f2afdd0e043a397677e597ced0830b83ba0b3 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Wed, 24 Jul 2024 10:04:51 -0700 Subject: [PATCH 33/34] tap: add missing verification for short frame The cited commit missed to check against the validity of the frame length in the tap_get_user_xdp() path, which could cause a corrupted skb to be sent downstack. Even before the skb is transmitted, the tap_get_user_xdp()-->skb_set_network_header() may assume the size is more than ETH_HLEN. Once transmitted, this could either cause out-of-bound access beyond the actual length, or confuse the underlayer with incorrect or inconsistent header length in the skb metadata. In the alternative path, tap_get_user() already prohibits short frame which has the length less than Ethernet header size from being transmitted. This is to drop any frame shorter than the Ethernet header size just like how tap_get_user() does. CVE: CVE-2024-41090 Link: https://lore.kernel.org/netdev/1717026141-25716-1-git-send-email-si-wei.liu@oracle.com/ Fixes: 0efac27791ee ("tap: accept an array of XDP buffs through sendmsg()") Cc: stable@vger.kernel.org Signed-off-by: Si-Wei Liu Signed-off-by: Dongli Zhang Reviewed-by: Willem de Bruijn Reviewed-by: Paolo Abeni Reviewed-by: Jason Wang Link: https://patch.msgid.link/20240724170452.16837-2-dongli.zhang@oracle.com Signed-off-by: Jakub Kicinski --- drivers/net/tap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/tap.c b/drivers/net/tap.c index bfdd3875fe86..77574f7a3bd4 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1177,6 +1177,11 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) struct sk_buff *skb; int err, depth; + if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) { + err = -EINVAL; + goto err; + } + if (q->flags & IFF_VNET_HDR) vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); From 049584807f1d797fc3078b68035450a9769eb5c3 Mon Sep 17 00:00:00 2001 From: Dongli Zhang Date: Wed, 24 Jul 2024 10:04:52 -0700 Subject: [PATCH 34/34] tun: add missing verification for short frame The cited commit missed to check against the validity of the frame length in the tun_xdp_one() path, which could cause a corrupted skb to be sent downstack. Even before the skb is transmitted, the tun_xdp_one-->eth_type_trans() may access the Ethernet header although it can be less than ETH_HLEN. Once transmitted, this could either cause out-of-bound access beyond the actual length, or confuse the underlayer with incorrect or inconsistent header length in the skb metadata. In the alternative path, tun_get_user() already prohibits short frame which has the length less than Ethernet header size from being transmitted for IFF_TAP. This is to drop any frame shorter than the Ethernet header size just like how tun_get_user() does. CVE: CVE-2024-41091 Inspired-by: https://lore.kernel.org/netdev/1717026141-25716-1-git-send-email-si-wei.liu@oracle.com/ Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()") Cc: stable@vger.kernel.org Signed-off-by: Dongli Zhang Reviewed-by: Si-Wei Liu Reviewed-by: Willem de Bruijn Reviewed-by: Paolo Abeni Reviewed-by: Jason Wang Link: https://patch.msgid.link/20240724170452.16837-3-dongli.zhang@oracle.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9b24861464bc..1d06c560c5e6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2455,6 +2455,9 @@ static int tun_xdp_one(struct tun_struct *tun, bool skb_xdp = false; struct page *page; + if (unlikely(datasize < ETH_HLEN)) + return -EINVAL; + xdp_prog = rcu_dereference(tun->xdp_prog); if (xdp_prog) { if (gso->gso_type) {