diff mbox series

[bpf-next,5/8] selftests/bpf: Add nested trust selftests suite

Message ID 20230119235833.2948341-6-void@manifault.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series Enable cpumasks to be used as kptrs | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-7 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-14 fail Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 fail Logs for test_progs on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-17 fail Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-19 fail Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 fail Logs for test_progs_no_alu32 on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 fail Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_progs_no_alu32_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-29 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for test_progs_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-32 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-34 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-35 success Logs for test_verifier on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-36 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-37 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-38 success Logs for test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-26 fail Logs for test_progs_no_alu32_parallel on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 fail Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for test_progs_parallel on s390x with gcc
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs on s390x with gcc
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 4 maintainers not CCed: linux-kselftest@vger.kernel.org shuah@kernel.org yhs@fb.com mykolal@fb.com
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

David Vernet Jan. 19, 2023, 11:58 p.m. UTC
Now that defining trusted fields in a struct is supported, we should add
selftests to verify the behavior. This patch adds a few such testcases.

Signed-off-by: David Vernet <void@manifault.com>
---
 tools/testing/selftests/bpf/DENYLIST.s390x    |  1 +
 .../selftests/bpf/prog_tests/nested_trust.c   | 64 +++++++++++++++++++
 .../selftests/bpf/progs/nested_trust_common.h | 12 ++++
 .../bpf/progs/nested_trust_failure.c          | 33 ++++++++++
 .../bpf/progs/nested_trust_success.c          | 29 +++++++++
 5 files changed, 139 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/nested_trust.c
 create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_common.h
 create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_failure.c
 create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_success.c

Comments

Alexei Starovoitov Jan. 20, 2023, 5:51 a.m. UTC | #1
On Thu, Jan 19, 2023 at 05:58:30PM -0600, David Vernet wrote:
> Now that defining trusted fields in a struct is supported, we should add
> selftests to verify the behavior. This patch adds a few such testcases.
> 
> Signed-off-by: David Vernet <void@manifault.com>
> ---
>  tools/testing/selftests/bpf/DENYLIST.s390x    |  1 +
>  .../selftests/bpf/prog_tests/nested_trust.c   | 64 +++++++++++++++++++
>  .../selftests/bpf/progs/nested_trust_common.h | 12 ++++
>  .../bpf/progs/nested_trust_failure.c          | 33 ++++++++++
>  .../bpf/progs/nested_trust_success.c          | 29 +++++++++
>  5 files changed, 139 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/nested_trust.c
>  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_common.h
>  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_failure.c
>  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_success.c
> 
> diff --git a/tools/testing/selftests/bpf/DENYLIST.s390x b/tools/testing/selftests/bpf/DENYLIST.s390x
> index 96e8371f5c2a..1cf5b94cda30 100644
> --- a/tools/testing/selftests/bpf/DENYLIST.s390x
> +++ b/tools/testing/selftests/bpf/DENYLIST.s390x
> @@ -44,6 +44,7 @@ map_kptr                                 # failed to open_and_load program: -524
>  modify_return                            # modify_return attach failed: -524                                           (trampoline)
>  module_attach                            # skel_attach skeleton attach failed: -524                                    (trampoline)
>  mptcp
> +nested_trust                             # JIT does not support calling kernel function
>  netcnt                                   # failed to load BPF skeleton 'netcnt_prog': -7                               (?)
>  probe_user                               # check_kprobe_res wrong kprobe res from probe read                           (?)
>  rcu_read_lock                            # failed to find kernel BTF type ID of '__x64_sys_getpgid': -3                (?)
> diff --git a/tools/testing/selftests/bpf/prog_tests/nested_trust.c b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
> new file mode 100644
> index 000000000000..4d13612f5001
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
> +
> +#include <test_progs.h>
> +#include "nested_trust_failure.skel.h"
> +#include "nested_trust_success.skel.h"
> +
> +static const char * const nested_trust_success_testcases[] = {
> +	"test_read_cpumask",
> +};
> +
> +static void verify_success(const char *prog_name)
> +{
> +	struct nested_trust_success *skel;
> +	struct bpf_program *prog;
> +	struct bpf_link *link = NULL;
> +	int status;
> +	pid_t child_pid;
> +
> +	skel = nested_trust_success__open();
> +	if (!ASSERT_OK_PTR(skel, "nested_trust_success__open"))
> +		return;
> +
> +	skel->bss->pid = getpid();
> +
> +	nested_trust_success__load(skel);
> +	if (!ASSERT_OK_PTR(skel, "nested_trust_success__load"))
> +		goto cleanup;
> +
> +	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
> +	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
> +		goto cleanup;
> +
> +	link = bpf_program__attach(prog);
> +	if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
> +		goto cleanup;
> +
> +	child_pid = fork();
> +	if (!ASSERT_GT(child_pid, -1, "child_pid"))
> +		goto cleanup;
> +	if (child_pid == 0)
> +		_exit(0);
> +	waitpid(child_pid, &status, 0);
> +	ASSERT_OK(skel->bss->err, "post_wait_err");
> +
> +	bpf_link__destroy(link);
> +
> +cleanup:
> +	nested_trust_success__destroy(skel);
> +}
> +
> +void test_nested_trust(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(nested_trust_success_testcases); i++) {
> +		if (!test__start_subtest(nested_trust_success_testcases[i]))
> +			continue;
> +
> +		verify_success(nested_trust_success_testcases[i]);
> +	}
> +
> +	RUN_TESTS(nested_trust_failure);
> +}

Hmm. I thought RUN_TESTS() works for successes too.
Looking at test_loader.c:run_subtest() that should be the case.
Could you please double check?
verify_success() above shouldn't be needed.
David Vernet Jan. 20, 2023, 5:56 a.m. UTC | #2
On Thu, Jan 19, 2023 at 09:51:49PM -0800, Alexei Starovoitov wrote:
> On Thu, Jan 19, 2023 at 05:58:30PM -0600, David Vernet wrote:
> > Now that defining trusted fields in a struct is supported, we should add
> > selftests to verify the behavior. This patch adds a few such testcases.
> > 
> > Signed-off-by: David Vernet <void@manifault.com>
> > ---
> >  tools/testing/selftests/bpf/DENYLIST.s390x    |  1 +
> >  .../selftests/bpf/prog_tests/nested_trust.c   | 64 +++++++++++++++++++
> >  .../selftests/bpf/progs/nested_trust_common.h | 12 ++++
> >  .../bpf/progs/nested_trust_failure.c          | 33 ++++++++++
> >  .../bpf/progs/nested_trust_success.c          | 29 +++++++++
> >  5 files changed, 139 insertions(+)
> >  create mode 100644 tools/testing/selftests/bpf/prog_tests/nested_trust.c
> >  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_common.h
> >  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_failure.c
> >  create mode 100644 tools/testing/selftests/bpf/progs/nested_trust_success.c
> > 
> > diff --git a/tools/testing/selftests/bpf/DENYLIST.s390x b/tools/testing/selftests/bpf/DENYLIST.s390x
> > index 96e8371f5c2a..1cf5b94cda30 100644
> > --- a/tools/testing/selftests/bpf/DENYLIST.s390x
> > +++ b/tools/testing/selftests/bpf/DENYLIST.s390x
> > @@ -44,6 +44,7 @@ map_kptr                                 # failed to open_and_load program: -524
> >  modify_return                            # modify_return attach failed: -524                                           (trampoline)
> >  module_attach                            # skel_attach skeleton attach failed: -524                                    (trampoline)
> >  mptcp
> > +nested_trust                             # JIT does not support calling kernel function
> >  netcnt                                   # failed to load BPF skeleton 'netcnt_prog': -7                               (?)
> >  probe_user                               # check_kprobe_res wrong kprobe res from probe read                           (?)
> >  rcu_read_lock                            # failed to find kernel BTF type ID of '__x64_sys_getpgid': -3                (?)
> > diff --git a/tools/testing/selftests/bpf/prog_tests/nested_trust.c b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
> > new file mode 100644
> > index 000000000000..4d13612f5001
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
> > @@ -0,0 +1,64 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
> > +
> > +#include <test_progs.h>
> > +#include "nested_trust_failure.skel.h"
> > +#include "nested_trust_success.skel.h"
> > +
> > +static const char * const nested_trust_success_testcases[] = {
> > +	"test_read_cpumask",
> > +};
> > +
> > +static void verify_success(const char *prog_name)
> > +{
> > +	struct nested_trust_success *skel;
> > +	struct bpf_program *prog;
> > +	struct bpf_link *link = NULL;
> > +	int status;
> > +	pid_t child_pid;
> > +
> > +	skel = nested_trust_success__open();
> > +	if (!ASSERT_OK_PTR(skel, "nested_trust_success__open"))
> > +		return;
> > +
> > +	skel->bss->pid = getpid();
> > +
> > +	nested_trust_success__load(skel);
> > +	if (!ASSERT_OK_PTR(skel, "nested_trust_success__load"))
> > +		goto cleanup;
> > +
> > +	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
> > +	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
> > +		goto cleanup;
> > +
> > +	link = bpf_program__attach(prog);
> > +	if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
> > +		goto cleanup;
> > +
> > +	child_pid = fork();
> > +	if (!ASSERT_GT(child_pid, -1, "child_pid"))
> > +		goto cleanup;
> > +	if (child_pid == 0)
> > +		_exit(0);
> > +	waitpid(child_pid, &status, 0);
> > +	ASSERT_OK(skel->bss->err, "post_wait_err");
> > +
> > +	bpf_link__destroy(link);
> > +
> > +cleanup:
> > +	nested_trust_success__destroy(skel);
> > +}
> > +
> > +void test_nested_trust(void)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(nested_trust_success_testcases); i++) {
> > +		if (!test__start_subtest(nested_trust_success_testcases[i]))
> > +			continue;
> > +
> > +		verify_success(nested_trust_success_testcases[i]);
> > +	}
> > +
> > +	RUN_TESTS(nested_trust_failure);
> > +}
> 
> Hmm. I thought RUN_TESTS() works for successes too.
> Looking at test_loader.c:run_subtest() that should be the case.
> Could you please double check?
> verify_success() above shouldn't be needed.

Yes, looks like RUN_TESTS() works for success cases too, it just isn't
used anywhere yet. I expect it won't be super commonly used given that
it only loads the program and tests the verifier rather than doing any
runtime validation, but that's exactly what we want for this so I'll
update that in v2. I'll plan on leaving the cpumask success cases as
they are unless you object so that we can get runtime coverage as well.
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/DENYLIST.s390x b/tools/testing/selftests/bpf/DENYLIST.s390x
index 96e8371f5c2a..1cf5b94cda30 100644
--- a/tools/testing/selftests/bpf/DENYLIST.s390x
+++ b/tools/testing/selftests/bpf/DENYLIST.s390x
@@ -44,6 +44,7 @@  map_kptr                                 # failed to open_and_load program: -524
 modify_return                            # modify_return attach failed: -524                                           (trampoline)
 module_attach                            # skel_attach skeleton attach failed: -524                                    (trampoline)
 mptcp
+nested_trust                             # JIT does not support calling kernel function
 netcnt                                   # failed to load BPF skeleton 'netcnt_prog': -7                               (?)
 probe_user                               # check_kprobe_res wrong kprobe res from probe read                           (?)
 rcu_read_lock                            # failed to find kernel BTF type ID of '__x64_sys_getpgid': -3                (?)
diff --git a/tools/testing/selftests/bpf/prog_tests/nested_trust.c b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
new file mode 100644
index 000000000000..4d13612f5001
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/nested_trust.c
@@ -0,0 +1,64 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
+
+#include <test_progs.h>
+#include "nested_trust_failure.skel.h"
+#include "nested_trust_success.skel.h"
+
+static const char * const nested_trust_success_testcases[] = {
+	"test_read_cpumask",
+};
+
+static void verify_success(const char *prog_name)
+{
+	struct nested_trust_success *skel;
+	struct bpf_program *prog;
+	struct bpf_link *link = NULL;
+	int status;
+	pid_t child_pid;
+
+	skel = nested_trust_success__open();
+	if (!ASSERT_OK_PTR(skel, "nested_trust_success__open"))
+		return;
+
+	skel->bss->pid = getpid();
+
+	nested_trust_success__load(skel);
+	if (!ASSERT_OK_PTR(skel, "nested_trust_success__load"))
+		goto cleanup;
+
+	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
+	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
+		goto cleanup;
+
+	link = bpf_program__attach(prog);
+	if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
+		goto cleanup;
+
+	child_pid = fork();
+	if (!ASSERT_GT(child_pid, -1, "child_pid"))
+		goto cleanup;
+	if (child_pid == 0)
+		_exit(0);
+	waitpid(child_pid, &status, 0);
+	ASSERT_OK(skel->bss->err, "post_wait_err");
+
+	bpf_link__destroy(link);
+
+cleanup:
+	nested_trust_success__destroy(skel);
+}
+
+void test_nested_trust(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nested_trust_success_testcases); i++) {
+		if (!test__start_subtest(nested_trust_success_testcases[i]))
+			continue;
+
+		verify_success(nested_trust_success_testcases[i]);
+	}
+
+	RUN_TESTS(nested_trust_failure);
+}
diff --git a/tools/testing/selftests/bpf/progs/nested_trust_common.h b/tools/testing/selftests/bpf/progs/nested_trust_common.h
new file mode 100644
index 000000000000..83d33931136e
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/nested_trust_common.h
@@ -0,0 +1,12 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
+
+#ifndef _NESTED_TRUST_COMMON_H
+#define _NESTED_TRUST_COMMON_H
+
+#include <stdbool.h>
+
+bool bpf_cpumask_test_cpu(unsigned int cpu, const struct cpumask *cpumask) __ksym;
+bool bpf_cpumask_first_zero(const struct cpumask *cpumask) __ksym;
+
+#endif /* _NESTED_TRUST_COMMON_H */
diff --git a/tools/testing/selftests/bpf/progs/nested_trust_failure.c b/tools/testing/selftests/bpf/progs/nested_trust_failure.c
new file mode 100644
index 000000000000..14aff7676436
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/nested_trust_failure.c
@@ -0,0 +1,33 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
+
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+#include "nested_trust_common.h"
+
+char _license[] SEC("license") = "GPL";
+
+/* Prototype for all of the program trace events below:
+ *
+ * TRACE_EVENT(task_newtask,
+ *         TP_PROTO(struct task_struct *p, u64 clone_flags)
+ */
+
+SEC("tp_btf/task_newtask")
+__failure __msg("R2 must be referenced or trusted")
+int BPF_PROG(test_invalid_nested_user_cpus, struct task_struct *task, u64 clone_flags)
+{
+	bpf_cpumask_test_cpu(0, task->user_cpus_ptr);
+	return 0;
+}
+
+SEC("tp_btf/task_newtask")
+__failure __msg("R1 must have zero offset when passed to release func or trusted arg to kfunc")
+int BPF_PROG(test_invalid_nested_offset, struct task_struct *task, u64 clone_flags)
+{
+	bpf_cpumask_first_zero(&task->cpus_mask);
+	return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/nested_trust_success.c b/tools/testing/selftests/bpf/progs/nested_trust_success.c
new file mode 100644
index 000000000000..04079f120bea
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/nested_trust_success.c
@@ -0,0 +1,29 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
+
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+
+#include "nested_trust_common.h"
+
+char _license[] SEC("license") = "GPL";
+
+int pid, err;
+
+static bool is_test_task(void)
+{
+	int cur_pid = bpf_get_current_pid_tgid() >> 32;
+
+	return pid == cur_pid;
+}
+
+SEC("tp_btf/task_newtask")
+int BPF_PROG(test_read_cpumask, struct task_struct *task, u64 clone_flags)
+{
+	if (!is_test_task())
+		return 0;
+
+	bpf_cpumask_test_cpu(0, task->cpus_ptr);
+	return 0;
+}