]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Aug 2022 12:03:07 +0000 (14:03 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Aug 2022 12:03:07 +0000 (14:03 +0200)
added patches:
selftests-bpf-check-dst_port-only-on-the-client-socket.patch
selftests-bpf-extend-verifier-and-bpf_sock-tests-for-dst_port-loads.patch

queue-5.10/selftests-bpf-check-dst_port-only-on-the-client-socket.patch [new file with mode: 0644]
queue-5.10/selftests-bpf-extend-verifier-and-bpf_sock-tests-for-dst_port-loads.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/selftests-bpf-check-dst_port-only-on-the-client-socket.patch b/queue-5.10/selftests-bpf-check-dst_port-only-on-the-client-socket.patch
new file mode 100644 (file)
index 0000000..e3721bc
--- /dev/null
@@ -0,0 +1,48 @@
+From foo@baz Wed Aug  3 02:02:41 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Mon,  1 Aug 2022 17:57:03 +0300
+Subject: selftests/bpf: Check dst_port only on the client socket
+To: stable@vger.kernel.org
+Cc: Jakub Sitnicki <jakub@cloudflare.com>, Daniel Borkmann <daniel@iogearbox.net>, Martin KaFai Lau <kafai@fb.com>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220801145703.1929060-2-ovidiu.panait@windriver.com>
+
+From: Jakub Sitnicki <jakub@cloudflare.com>
+
+commit 2d2202ba858c112b03f84d546e260c61425831a1 upstream.
+
+cgroup_skb/egress programs which sock_fields test installs process packets
+flying in both directions, from the client to the server, and in reverse
+direction.
+
+Recently added dst_port check relies on the fact that destination
+port (remote peer port) of the socket which sends the packet is known ahead
+of time. This holds true only for the client socket, which connects to the
+known server port.
+
+Filter out any traffic that is not egressing from the client socket in the
+BPF program that tests reading the dst_port.
+
+Fixes: 8f50f16ff39d ("selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads")
+Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Martin KaFai Lau <kafai@fb.com>
+Link: https://lore.kernel.org/bpf/20220317113920.1068535-3-jakub@cloudflare.com
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/test_sock_fields.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/tools/testing/selftests/bpf/progs/test_sock_fields.c
++++ b/tools/testing/selftests/bpf/progs/test_sock_fields.c
+@@ -281,6 +281,10 @@ int read_sk_dst_port(struct __sk_buff *s
+       if (!sk)
+               RET_LOG();
++      /* Ignore everything but the SYN from the client socket */
++      if (sk->state != BPF_TCP_SYN_SENT)
++              return CG_OK;
++
+       if (!sk_dst_port__load_word(sk))
+               RET_LOG();
+       if (!sk_dst_port__load_half(sk))
diff --git a/queue-5.10/selftests-bpf-extend-verifier-and-bpf_sock-tests-for-dst_port-loads.patch b/queue-5.10/selftests-bpf-extend-verifier-and-bpf_sock-tests-for-dst_port-loads.patch
new file mode 100644 (file)
index 0000000..a0c5dab
--- /dev/null
@@ -0,0 +1,344 @@
+From foo@baz Wed Aug  3 02:02:41 PM CEST 2022
+From: Ovidiu Panait <ovidiu.panait@windriver.com>
+Date: Mon,  1 Aug 2022 17:57:02 +0300
+Subject: selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads
+To: stable@vger.kernel.org
+Cc: Jakub Sitnicki <jakub@cloudflare.com>, Alexei Starovoitov <ast@kernel.org>, Ovidiu Panait <ovidiu.panait@windriver.com>
+Message-ID: <20220801145703.1929060-1-ovidiu.panait@windriver.com>
+
+From: Jakub Sitnicki <jakub@cloudflare.com>
+
+commit 8f50f16ff39dd4e2d43d1548ca66925652f8aff7 upstream.
+
+Add coverage to the verifier tests and tests for reading bpf_sock fields to
+ensure that 32-bit, 16-bit, and 8-bit loads from dst_port field are allowed
+only at intended offsets and produce expected values.
+
+While 16-bit and 8-bit access to dst_port field is straight-forward, 32-bit
+wide loads need be allowed and produce a zero-padded 16-bit value for
+backward compatibility.
+
+Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/r/20220130115518.213259-3-jakub@cloudflare.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[OP: backport to 5.10: adjusted context in sock_fields.c]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+This series fixes the following bpf verfier selftest failures:
+root@intel-x86-64:~# ./test_verifier
+...
+#908/u sk_fullsock(skb->sk): sk->dst_port [load 2nd byte] FAIL
+#908/p sk_fullsock(skb->sk): sk->dst_port [load 2nd byte] FAIL
+
+ tools/include/uapi/linux/bpf.h                       |    3 
+ tools/testing/selftests/bpf/prog_tests/sock_fields.c |   60 +++++++++-----
+ tools/testing/selftests/bpf/progs/test_sock_fields.c |   41 +++++++++
+ tools/testing/selftests/bpf/verifier/sock.c          |   81 ++++++++++++++++++-
+ 4 files changed, 162 insertions(+), 23 deletions(-)
+
+--- a/tools/include/uapi/linux/bpf.h
++++ b/tools/include/uapi/linux/bpf.h
+@@ -4180,7 +4180,8 @@ struct bpf_sock {
+       __u32 src_ip4;
+       __u32 src_ip6[4];
+       __u32 src_port;         /* host byte order */
+-      __u32 dst_port;         /* network byte order */
++      __be16 dst_port;        /* network byte order */
++      __u16 :16;              /* zero padding */
+       __u32 dst_ip4;
+       __u32 dst_ip6[4];
+       __u32 state;
+--- a/tools/testing/selftests/bpf/prog_tests/sock_fields.c
++++ b/tools/testing/selftests/bpf/prog_tests/sock_fields.c
+@@ -1,9 +1,11 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright (c) 2019 Facebook */
++#define _GNU_SOURCE
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <unistd.h>
++#include <sched.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
+@@ -21,6 +23,7 @@
+ enum bpf_linum_array_idx {
+       EGRESS_LINUM_IDX,
+       INGRESS_LINUM_IDX,
++      READ_SK_DST_PORT_LINUM_IDX,
+       __NR_BPF_LINUM_ARRAY_IDX,
+ };
+@@ -43,8 +46,16 @@ static __u64 child_cg_id;
+ static int linum_map_fd;
+ static __u32 duration;
+-static __u32 egress_linum_idx = EGRESS_LINUM_IDX;
+-static __u32 ingress_linum_idx = INGRESS_LINUM_IDX;
++static bool create_netns(void)
++{
++      if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
++              return false;
++
++      if (!ASSERT_OK(system("ip link set dev lo up"), "bring up lo"))
++              return false;
++
++      return true;
++}
+ static void print_sk(const struct bpf_sock *sk, const char *prefix)
+ {
+@@ -92,19 +103,24 @@ static void check_result(void)
+ {
+       struct bpf_tcp_sock srv_tp, cli_tp, listen_tp;
+       struct bpf_sock srv_sk, cli_sk, listen_sk;
+-      __u32 ingress_linum, egress_linum;
++      __u32 idx, ingress_linum, egress_linum, linum;
+       int err;
+-      err = bpf_map_lookup_elem(linum_map_fd, &egress_linum_idx,
+-                                &egress_linum);
++      idx = EGRESS_LINUM_IDX;
++      err = bpf_map_lookup_elem(linum_map_fd, &idx, &egress_linum);
+       CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)",
+             "err:%d errno:%d\n", err, errno);
+-      err = bpf_map_lookup_elem(linum_map_fd, &ingress_linum_idx,
+-                                &ingress_linum);
++      idx = INGRESS_LINUM_IDX;
++      err = bpf_map_lookup_elem(linum_map_fd, &idx, &ingress_linum);
+       CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)",
+             "err:%d errno:%d\n", err, errno);
++      idx = READ_SK_DST_PORT_LINUM_IDX;
++      err = bpf_map_lookup_elem(linum_map_fd, &idx, &linum);
++      ASSERT_OK(err, "bpf_map_lookup_elem(linum_map_fd, READ_SK_DST_PORT_IDX)");
++      ASSERT_EQ(linum, 0, "failure in read_sk_dst_port on line");
++
+       memcpy(&srv_sk, &skel->bss->srv_sk, sizeof(srv_sk));
+       memcpy(&srv_tp, &skel->bss->srv_tp, sizeof(srv_tp));
+       memcpy(&cli_sk, &skel->bss->cli_sk, sizeof(cli_sk));
+@@ -263,7 +279,7 @@ static void test(void)
+       char buf[DATA_LEN];
+       /* Prepare listen_fd */
+-      listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
++      listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0xcafe, 0);
+       /* start_server() has logged the error details */
+       if (CHECK_FAIL(listen_fd == -1))
+               goto done;
+@@ -331,8 +347,12 @@ done:
+ void test_sock_fields(void)
+ {
+-      struct bpf_link *egress_link = NULL, *ingress_link = NULL;
+       int parent_cg_fd = -1, child_cg_fd = -1;
++      struct bpf_link *link;
++
++      /* Use a dedicated netns to have a fixed listen port */
++      if (!create_netns())
++              return;
+       /* Create a cgroup, get fd, and join it */
+       parent_cg_fd = test__join_cgroup(PARENT_CGROUP);
+@@ -353,17 +373,20 @@ void test_sock_fields(void)
+       if (CHECK(!skel, "test_sock_fields__open_and_load", "failed\n"))
+               goto done;
+-      egress_link = bpf_program__attach_cgroup(skel->progs.egress_read_sock_fields,
+-                                               child_cg_fd);
+-      if (CHECK(IS_ERR(egress_link), "attach_cgroup(egress)", "err:%ld\n",
+-                PTR_ERR(egress_link)))
++      link = bpf_program__attach_cgroup(skel->progs.egress_read_sock_fields, child_cg_fd);
++      if (!ASSERT_OK_PTR(link, "attach_cgroup(egress_read_sock_fields)"))
++              goto done;
++      skel->links.egress_read_sock_fields = link;
++
++      link = bpf_program__attach_cgroup(skel->progs.ingress_read_sock_fields, child_cg_fd);
++      if (!ASSERT_OK_PTR(link, "attach_cgroup(ingress_read_sock_fields)"))
+               goto done;
++      skel->links.ingress_read_sock_fields = link;
+-      ingress_link = bpf_program__attach_cgroup(skel->progs.ingress_read_sock_fields,
+-                                                child_cg_fd);
+-      if (CHECK(IS_ERR(ingress_link), "attach_cgroup(ingress)", "err:%ld\n",
+-                PTR_ERR(ingress_link)))
++      link = bpf_program__attach_cgroup(skel->progs.read_sk_dst_port, child_cg_fd);
++      if (!ASSERT_OK_PTR(link, "attach_cgroup(read_sk_dst_port"))
+               goto done;
++      skel->links.read_sk_dst_port = link;
+       linum_map_fd = bpf_map__fd(skel->maps.linum_map);
+       sk_pkt_out_cnt_fd = bpf_map__fd(skel->maps.sk_pkt_out_cnt);
+@@ -372,8 +395,7 @@ void test_sock_fields(void)
+       test();
+ done:
+-      bpf_link__destroy(egress_link);
+-      bpf_link__destroy(ingress_link);
++      test_sock_fields__detach(skel);
+       test_sock_fields__destroy(skel);
+       if (child_cg_fd != -1)
+               close(child_cg_fd);
+--- a/tools/testing/selftests/bpf/progs/test_sock_fields.c
++++ b/tools/testing/selftests/bpf/progs/test_sock_fields.c
+@@ -12,6 +12,7 @@
+ enum bpf_linum_array_idx {
+       EGRESS_LINUM_IDX,
+       INGRESS_LINUM_IDX,
++      READ_SK_DST_PORT_LINUM_IDX,
+       __NR_BPF_LINUM_ARRAY_IDX,
+ };
+@@ -249,5 +250,45 @@ int ingress_read_sock_fields(struct __sk
+       return CG_OK;
+ }
++
++static __noinline bool sk_dst_port__load_word(struct bpf_sock *sk)
++{
++      __u32 *word = (__u32 *)&sk->dst_port;
++      return word[0] == bpf_htonl(0xcafe0000);
++}
++
++static __noinline bool sk_dst_port__load_half(struct bpf_sock *sk)
++{
++      __u16 *half = (__u16 *)&sk->dst_port;
++      return half[0] == bpf_htons(0xcafe);
++}
++
++static __noinline bool sk_dst_port__load_byte(struct bpf_sock *sk)
++{
++      __u8 *byte = (__u8 *)&sk->dst_port;
++      return byte[0] == 0xca && byte[1] == 0xfe;
++}
++
++SEC("cgroup_skb/egress")
++int read_sk_dst_port(struct __sk_buff *skb)
++{
++      __u32 linum, linum_idx;
++      struct bpf_sock *sk;
++
++      linum_idx = READ_SK_DST_PORT_LINUM_IDX;
++
++      sk = skb->sk;
++      if (!sk)
++              RET_LOG();
++
++      if (!sk_dst_port__load_word(sk))
++              RET_LOG();
++      if (!sk_dst_port__load_half(sk))
++              RET_LOG();
++      if (!sk_dst_port__load_byte(sk))
++              RET_LOG();
++
++      return CG_OK;
++}
+ char _license[] SEC("license") = "GPL";
+--- a/tools/testing/selftests/bpf/verifier/sock.c
++++ b/tools/testing/selftests/bpf/verifier/sock.c
+@@ -121,7 +121,25 @@
+       .result = ACCEPT,
+ },
+ {
+-      "sk_fullsock(skb->sk): sk->dst_port [narrow load]",
++      "sk_fullsock(skb->sk): sk->dst_port [word load] (backward compatibility)",
++      .insns = {
++      BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct bpf_sock, dst_port)),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      },
++      .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
++      .result = ACCEPT,
++},
++{
++      "sk_fullsock(skb->sk): sk->dst_port [half load]",
+       .insns = {
+       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
+@@ -139,7 +157,64 @@
+       .result = ACCEPT,
+ },
+ {
+-      "sk_fullsock(skb->sk): sk->dst_port [load 2nd byte]",
++      "sk_fullsock(skb->sk): sk->dst_port [half load] (invalid)",
++      .insns = {
++      BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_0, offsetof(struct bpf_sock, dst_port) + 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      },
++      .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
++      .result = REJECT,
++      .errstr = "invalid sock access",
++},
++{
++      "sk_fullsock(skb->sk): sk->dst_port [byte load]",
++      .insns = {
++      BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_0, offsetof(struct bpf_sock, dst_port)),
++      BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_0, offsetof(struct bpf_sock, dst_port) + 1),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      },
++      .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
++      .result = ACCEPT,
++},
++{
++      "sk_fullsock(skb->sk): sk->dst_port [byte load] (invalid)",
++      .insns = {
++      BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
++      BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, offsetof(struct bpf_sock, dst_port) + 2),
++      BPF_MOV64_IMM(BPF_REG_0, 0),
++      BPF_EXIT_INSN(),
++      },
++      .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
++      .result = REJECT,
++      .errstr = "invalid sock access",
++},
++{
++      "sk_fullsock(skb->sk): past sk->dst_port [half load] (invalid)",
+       .insns = {
+       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
+@@ -149,7 +224,7 @@
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+-      BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, offsetof(struct bpf_sock, dst_port) + 1),
++      BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_0, offsetofend(struct bpf_sock, dst_port)),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
index 196c6b731c80c27622c27bbddbd159a50d1f5e76..5b51a3a3e45e9ce149705614d124a33158e68ecf 100644 (file)
@@ -1,3 +1,5 @@
 x86-speculation-make-all-retbleed-mitigations-64-bit-only.patch
 ath9k_htc-fix-null-pointer-dereference-at-ath9k_htc_rxep.patch
 ath9k_htc-fix-null-pointer-dereference-at-ath9k_htc_tx_get_packet.patch
+selftests-bpf-extend-verifier-and-bpf_sock-tests-for-dst_port-loads.patch
+selftests-bpf-check-dst_port-only-on-the-client-socket.patch