All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luis Gerhorst <gerhorst@amazon.de>
To: <alexei.starovoitov@gmail.com>
Cc: <andrii@kernel.org>, <ast@kernel.org>, <bpf@vger.kernel.org>,
	<daniel@iogearbox.net>, <haoluo@google.com>,
	<john.fastabend@gmail.com>, <jolsa@kernel.org>,
	<kpsingh@kernel.org>, <laoar.shao@gmail.com>,
	<martin.lau@linux.dev>, <sdf@google.com>, <song@kernel.org>,
	<yonghong.song@linux.dev>, <mykolal@fb.com>, <shuah@kernel.org>,
	<gerhorst@amazon.de>, <iii@linux.ibm.com>,
	<linux-kselftest@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	Luis Gerhorst <gerhorst@cs.fau.de>
Subject: [PATCH 3/3] selftests/bpf: Add selftest for packet-pointer Spectre v1 gadget
Date: Wed, 13 Sep 2023 12:31:54 +0000	[thread overview]
Message-ID: <20230913123154.94264-1-gerhorst@amazon.de> (raw)
In-Reply-To: <CAADnVQLid7QvukhnqRoY2VVFi1tCfkPFsMGUUeHDtCgf0SAJCg@mail.gmail.com>

When allowing speculative leaks by enabling packet pointer accesses
without CAP_PERFMON (i.e., without having [1] reverted):

  $ tools/testing/selftests/bpf/test_progs --name=tc_bpf
  tc_bpf_non_root:PASS:set_cap_bpf_cap_net_admin 0 nsec
  tc_bpf_non_root:PASS:disable_cap_sys_admin 0 nsec
  tc_bpf_non_root:FAIL:test_tc_bpf__open_and_load unexpected pointer: 0x55bbd81969a0
  Summary: 0/1 PASSED, 0 SKIPPED, 1 FAILED

With [1] reverted:

  $ tools/testing/selftests/bpf/test_progs --name=tc_bpf
  #238/1   tc_bpf/tc_bpf_root:OK
  #238/2   tc_bpf/tc_bpf_non_root:OK
  #238     tc_bpf:OK
  Summary: 1/2 PASSED, 0 SKIPPED, 0 FAILED

[1] d75e30dddf73449bc2d10bb8e2f1a2c446bc67a2 ("bpf: Fix issue in verifying allow_ptr_leaks")

Signed-off-by: Luis Gerhorst <gerhorst@amazon.de>
Signed-off-by: Luis Gerhorst <gerhorst@cs.fau.de>
Based-on-patch-by: Yafang Shao <laoar.shao@gmail.com>
---
 .../testing/selftests/bpf/prog_tests/tc_bpf.c | 37 +++++++-
 .../testing/selftests/bpf/progs/test_tc_bpf.c | 95 +++++++++++++++++++
 2 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/tc_bpf.c b/tools/testing/selftests/bpf/prog_tests/tc_bpf.c
index e873766276d1..5319cb94a0ae 100644
--- a/tools/testing/selftests/bpf/prog_tests/tc_bpf.c
+++ b/tools/testing/selftests/bpf/prog_tests/tc_bpf.c
@@ -3,6 +3,7 @@
 #include <test_progs.h>
 #include <linux/pkt_cls.h>
 
+#include "cap_helpers.h"
 #include "test_tc_bpf.skel.h"
 
 #define LO_IFINDEX 1
@@ -327,7 +328,7 @@ static int test_tc_bpf_api(struct bpf_tc_hook *hook, int fd)
 	return 0;
 }
 
-void test_tc_bpf(void)
+void tc_bpf_root(void)
 {
 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = LO_IFINDEX,
 			    .attach_point = BPF_TC_INGRESS);
@@ -393,3 +394,37 @@ void test_tc_bpf(void)
 	}
 	test_tc_bpf__destroy(skel);
 }
+
+void tc_bpf_non_root(void)
+{
+	struct test_tc_bpf *skel = NULL;
+	__u64 caps = 0;
+	int ret;
+
+	/* In case CAP_BPF and CAP_PERFMON is not set */
+	ret = cap_enable_effective(1ULL << CAP_BPF | 1ULL << CAP_NET_ADMIN, &caps);
+	if (!ASSERT_OK(ret, "set_cap_bpf_cap_net_admin"))
+		return;
+	ret = cap_disable_effective(1ULL << CAP_SYS_ADMIN | 1ULL << CAP_PERFMON, NULL);
+	if (!ASSERT_OK(ret, "disable_cap_sys_admin"))
+		goto restore_cap;
+
+	skel = test_tc_bpf__open_and_load();
+	if (!ASSERT_ERR_PTR(skel, "test_tc_bpf__open_and_load"))
+		goto destroy;
+
+	goto restore_cap;
+destroy:
+	test_tc_bpf__destroy(skel);
+restore_cap:
+	if (caps)
+		cap_enable_effective(caps, NULL);
+}
+
+void test_tc_bpf(void)
+{
+	if (test__start_subtest("tc_bpf_root"))
+		tc_bpf_root();
+	if (test__start_subtest("tc_bpf_non_root"))
+		tc_bpf_non_root();
+}
diff --git a/tools/testing/selftests/bpf/progs/test_tc_bpf.c b/tools/testing/selftests/bpf/progs/test_tc_bpf.c
index d28ca8d1f3d0..3b3f9ce6b9d4 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_bpf.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_bpf.c
@@ -2,6 +2,8 @@
 
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
 
 /* Dummy prog to test TC-BPF API */
 
@@ -10,3 +12,96 @@ int cls(struct __sk_buff *skb)
 {
 	return 0;
 }
+
+/* Prog to verify tc-bpf without cap_sys_admin and cap_perfmon is rejected as
+ * required to prevent Spectre v1 using CPU multiplication port contention
+ * side-channel. This is not a full exploit but rather a PoC for x86_64. With
+ * extensions to the verifier's mitigations this may become obsolete.
+ *
+ * This should compile to the following bytecode if the kernel would allow
+ * unprivileged packet pointer accesses:
+ *
+
+0000000000000000 <pkt_ptr>:
+       0:	b4 00 00 00 00 00 00 00	w0 = 0
+       1:	61 12 50 00 00 00 00 00	r2 = *(u32 *)(r1 + 80)
+       2:	61 11 4c 00 00 00 00 00	r1 = *(u32 *)(r1 + 76)
+       3:	bf 13 00 00 00 00 00 00	r3 = r1
+       4:	07 03 00 00 22 00 00 00	r3 += 34
+       5:	bd 23 07 00 00 00 00 00	if r3 <= r2 goto +7 <LBB1_3>
+       6:	71 10 0e 00 00 00 00 00	r0 = *(u8 *)(r1 + 14)
+       7:	64 00 00 00 18 00 00 00	w0 <<= 24
+       8:	c4 00 00 00 18 00 00 00	w0 s>>= 24
+       9:	bc 01 00 00 00 00 00 00	w1 = w0
+      10:	54 01 00 00 01 00 00 00	w1 &= 1
+      11:	16 01 01 00 00 00 00 00	if w1 == 0 goto +1 <LBB1_3>
+      12:	24 00 00 00 61 00 00 00	w0 *= 97
+
+0000000000000068 <LBB1_3>:
+      13:	95 00 00 00 00 00 00 00	exit
+
+ *
+ * Which should in turn translate to this x86_64 assembly with !allow_ptr_leaks
+ * and !bypass_spec_v1:
+ *
+
+int pkt_ptr(struct __sk_buff * skb):
+bpf_prog_7c3834bad32f2b0f_pkt_ptr:
+; int pkt_ptr(struct __sk_buff *skb)
+   0:   endbr64
+   4:   nopl   0x0(%rax,%rax,1)
+   9:   xchg   %ax,%ax
+   b:   push   %rbp
+   c:   mov    %rsp,%rbp
+   f:   endbr64
+  13:   xor    %eax,%eax
+; if ((long)(iph + 1) > (long)skb->data_end)
+  15:   mov    0x50(%rdi),%rsi
+; struct iphdr *iph = (void *)(long)skb->data + sizeof(struct ethhdr);
+  19:   mov    0xc8(%rdi),%rdi
+; if ((long)(iph + 1) > (long)skb->data_end)
+  20:   mov    %rdi,%rdx
+  23:   add    $0x22,%rdx
+; if ((long)(iph + 1) > (long)skb->data_end)
+  27:   cmp    %rsi,%rdx
+  2a:   ja     0x0000000000000043
+; char secret = *((char *) iph);
+  2c:   movzbq 0xe(%rdi),%rax
+  31:   shl    $0x18,%eax
+  34:   sar    $0x18,%eax
+; if (secret & 1) {
+  37:   mov    %eax,%edi
+  39:   and    $0x1,%edi
+; if (secret & 1) {
+  3c:   test   %edi,%edi
+  3e:   je     0x0000000000000043
+  40:   imul   $0x61,%eax,%eax
+; }
+  43:   leaveq
+  44:   retq
+
+ *
+ */
+SEC("tcx/ingress")
+int pkt_ptr(struct __sk_buff *skb)
+{
+	struct iphdr *iph = (void *)(long)skb->data + sizeof(struct ethhdr);
+
+	/* Branch to be speculatively bypassed. */
+	if ((long)(iph + 1) > (long)skb->data_end)
+		return 0;
+
+	/* Speculative access to be prevented. */
+	char secret = *((char *) iph);
+
+	/* Leak the first bit of the secret value that lies behind data_end to a
+	 * SMP silbling thread that also executes imul instructions. If the bit
+	 * is 1, the silbling will experience a slowdown. */
+	long long x = secret;
+	if (secret & 1) {
+		x *= 97;
+	}
+
+	/* To prevent optimization. */
+	return x;
+}
-- 
2.40.1




Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879




  parent reply	other threads:[~2023-09-13 12:32 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-14 14:33 [RFC PATCH bpf-next 0/2] bpf: Add a new kfunc bpf_current_capable Yafang Shao
2023-08-14 14:33 ` [RFC PATCH bpf-next 1/2] bpf: Add bpf_current_capable kfunc Yafang Shao
2023-08-15  0:28   ` Yonghong Song
2023-08-15  2:45     ` Yafang Shao
2023-08-15  3:40       ` Yonghong Song
2023-08-15  5:49         ` Yafang Shao
2023-08-15 15:19           ` Yonghong Song
2023-08-17  1:53       ` Alexei Starovoitov
2023-08-17  2:30         ` Yafang Shao
2023-08-17  3:30           ` Alexei Starovoitov
2023-08-17  7:09             ` Yafang Shao
2023-08-17 15:30               ` Daniel Borkmann
2023-08-17 17:45                 ` Alexei Starovoitov
2023-09-13 12:25                   ` [PATCH 1/3] Revert "selftests/bpf: Add selftest for allow_ptr_leaks" Luis Gerhorst
2023-09-14 12:50                     ` patchwork-bot+netdevbpf
2023-09-13 12:28                   ` [PATCH 2/3] Revert "bpf: Fix issue in verifying allow_ptr_leaks" Luis Gerhorst
2023-09-14 16:20                     ` Alexei Starovoitov
2023-09-14 17:24                       ` Daniel Borkmann
2023-09-14 19:47                         ` Alexei Starovoitov
2023-09-18 11:25                           ` Luis Gerhorst
2023-09-19  8:57                             ` Alexei Starovoitov
2023-09-28 11:09                               ` Luis Gerhorst
2023-09-15  2:26                     ` Yafang Shao
2023-09-18 11:52                       ` Luis Gerhorst
2023-09-19  3:43                         ` Yafang Shao
2023-09-19  6:43                           ` Daniel Borkmann
2023-09-13 12:31                   ` Luis Gerhorst [this message]
2023-08-21  5:56                 ` [RFC PATCH bpf-next 1/2] bpf: Add bpf_current_capable kfunc Yafang Shao
2023-08-17 17:48               ` Alexei Starovoitov
2023-08-14 14:33 ` [RFC PATCH bpf-next 2/2] selftests/bpf: Add selftest for bpf_current_capable Yafang Shao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230913123154.94264-1-gerhorst@amazon.de \
    --to=gerhorst@amazon.de \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=gerhorst@cs.fau.de \
    --cc=haoluo@google.com \
    --cc=iii@linux.ibm.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=laoar.shao@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=mykolal@fb.com \
    --cc=sdf@google.com \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.