selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
|
2023-07-11 07:20:42 +00:00
|
|
|
#include <linux/capability.h>
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
#include <stdlib.h>
|
2024-11-26 08:58:32 +00:00
|
|
|
#include <regex.h>
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
#include <test_progs.h>
|
|
|
|
#include <bpf/btf.h>
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
#include "autoconf_helper.h"
|
2024-12-06 13:53:16 +00:00
|
|
|
#include "disasm_helpers.h"
|
2023-07-11 07:20:42 +00:00
|
|
|
#include "unpriv_helpers.h"
|
|
|
|
#include "cap_helpers.h"
|
2024-12-18 11:28:17 +00:00
|
|
|
#include "jit_disasm_helpers.h"
|
2023-07-11 07:20:42 +00:00
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
#define str_has_pfx(str, pfx) \
|
|
|
|
(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
|
|
|
|
|
2024-04-15 12:29:34 +00:00
|
|
|
#define TEST_LOADER_LOG_BUF_SZ 2097152
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
#define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure"
|
|
|
|
#define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success"
|
|
|
|
#define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg="
|
2024-12-06 13:53:16 +00:00
|
|
|
#define TEST_TAG_EXPECT_XLATED_PFX "comment:test_expect_xlated="
|
2023-07-11 07:20:42 +00:00
|
|
|
#define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv"
|
|
|
|
#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv"
|
|
|
|
#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv="
|
2024-12-06 13:53:16 +00:00
|
|
|
#define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "comment:test_expect_xlated_unpriv="
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
#define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level="
|
2023-07-10 12:46:35 +00:00
|
|
|
#define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags="
|
2023-07-11 07:20:42 +00:00
|
|
|
#define TEST_TAG_DESCRIPTION_PFX "comment:test_description="
|
2023-07-11 07:20:42 +00:00
|
|
|
#define TEST_TAG_RETVAL_PFX "comment:test_retval="
|
|
|
|
#define TEST_TAG_RETVAL_PFX_UNPRIV "comment:test_retval_unpriv="
|
2023-07-11 08:07:22 +00:00
|
|
|
#define TEST_TAG_AUXILIARY "comment:test_auxiliary"
|
|
|
|
#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
|
2024-04-15 12:19:55 +00:00
|
|
|
#define TEST_BTF_PATH "comment:test_btf_path="
|
2024-12-06 13:53:16 +00:00
|
|
|
#define TEST_TAG_ARCH "comment:test_arch="
|
2024-12-18 11:28:17 +00:00
|
|
|
#define TEST_TAG_JITED_PFX "comment:test_jited="
|
|
|
|
#define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv="
|
2023-07-11 07:20:42 +00:00
|
|
|
|
|
|
|
/* Warning: duplicated in bpf_misc.h */
|
|
|
|
#define POINTER_VALUE 0xcafe4all
|
|
|
|
#define TEST_DATA_LEN 64
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
|
|
|
#define EFFICIENT_UNALIGNED_ACCESS 1
|
|
|
|
#else
|
|
|
|
#define EFFICIENT_UNALIGNED_ACCESS 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int sysctl_unpriv_disabled = -1;
|
|
|
|
|
|
|
|
enum mode {
|
|
|
|
PRIV = 1,
|
|
|
|
UNPRIV = 2
|
|
|
|
};
|
|
|
|
|
2024-11-26 08:58:32 +00:00
|
|
|
struct expect_msg {
|
|
|
|
const char *substr; /* substring match */
|
|
|
|
regex_t regex;
|
2024-12-18 11:21:43 +00:00
|
|
|
bool is_regex;
|
|
|
|
bool on_next_line;
|
2024-11-26 08:58:32 +00:00
|
|
|
};
|
|
|
|
|
2024-12-06 13:53:15 +00:00
|
|
|
struct expected_msgs {
|
|
|
|
struct expect_msg *patterns;
|
|
|
|
size_t cnt;
|
|
|
|
};
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
struct test_subspec {
|
|
|
|
char *name;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
bool expect_failure;
|
2024-12-06 13:53:15 +00:00
|
|
|
struct expected_msgs expect_msgs;
|
2024-12-06 13:53:16 +00:00
|
|
|
struct expected_msgs expect_xlated;
|
2024-12-18 11:28:17 +00:00
|
|
|
struct expected_msgs jited;
|
2023-07-11 07:20:42 +00:00
|
|
|
int retval;
|
|
|
|
bool execute;
|
2023-07-11 07:20:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct test_spec {
|
|
|
|
const char *prog_name;
|
|
|
|
struct test_subspec priv;
|
|
|
|
struct test_subspec unpriv;
|
2024-04-15 12:19:55 +00:00
|
|
|
const char *btf_custom_path;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
int log_level;
|
2023-07-10 12:46:35 +00:00
|
|
|
int prog_flags;
|
2023-07-11 07:20:42 +00:00
|
|
|
int mode_mask;
|
2024-12-06 13:53:16 +00:00
|
|
|
int arch_mask;
|
2023-07-11 08:07:22 +00:00
|
|
|
bool auxiliary;
|
|
|
|
bool valid;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int tester_init(struct test_loader *tester)
|
|
|
|
{
|
|
|
|
if (!tester->log_buf) {
|
|
|
|
tester->log_buf_sz = TEST_LOADER_LOG_BUF_SZ;
|
2024-03-06 12:21:05 +00:00
|
|
|
tester->log_buf = calloc(tester->log_buf_sz, 1);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
if (!ASSERT_OK_PTR(tester->log_buf, "tester_log_buf"))
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_loader_fini(struct test_loader *tester)
|
|
|
|
{
|
|
|
|
if (!tester)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free(tester->log_buf);
|
|
|
|
}
|
|
|
|
|
2024-12-06 13:53:15 +00:00
|
|
|
static void free_msgs(struct expected_msgs *msgs)
|
2023-07-11 07:20:42 +00:00
|
|
|
{
|
2024-11-26 08:58:32 +00:00
|
|
|
int i;
|
|
|
|
|
2024-12-06 13:53:15 +00:00
|
|
|
for (i = 0; i < msgs->cnt; i++)
|
2024-12-18 11:21:43 +00:00
|
|
|
if (msgs->patterns[i].is_regex)
|
2024-12-06 13:53:15 +00:00
|
|
|
regfree(&msgs->patterns[i].regex);
|
|
|
|
free(msgs->patterns);
|
|
|
|
msgs->patterns = NULL;
|
|
|
|
msgs->cnt = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_test_spec(struct test_spec *spec)
|
|
|
|
{
|
2024-11-26 08:58:32 +00:00
|
|
|
/* Deallocate expect_msgs arrays. */
|
2024-12-06 13:53:15 +00:00
|
|
|
free_msgs(&spec->priv.expect_msgs);
|
|
|
|
free_msgs(&spec->unpriv.expect_msgs);
|
2024-12-06 13:53:16 +00:00
|
|
|
free_msgs(&spec->priv.expect_xlated);
|
|
|
|
free_msgs(&spec->unpriv.expect_xlated);
|
2024-12-18 11:28:17 +00:00
|
|
|
free_msgs(&spec->priv.jited);
|
|
|
|
free_msgs(&spec->unpriv.jited);
|
2024-11-26 08:58:32 +00:00
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
free(spec->priv.name);
|
|
|
|
free(spec->unpriv.name);
|
2023-07-11 08:07:22 +00:00
|
|
|
spec->priv.name = NULL;
|
|
|
|
spec->unpriv.name = NULL;
|
2023-07-11 07:20:42 +00:00
|
|
|
}
|
|
|
|
|
2024-12-18 11:21:43 +00:00
|
|
|
/* Compiles regular expression matching pattern.
|
|
|
|
* Pattern has a special syntax:
|
|
|
|
*
|
|
|
|
* pattern := (<verbatim text> | regex)*
|
|
|
|
* regex := "{{" <posix extended regular expression> "}}"
|
|
|
|
*
|
|
|
|
* In other words, pattern is a verbatim text with inclusion
|
|
|
|
* of regular expressions enclosed in "{{" "}}" pairs.
|
|
|
|
* For example, pattern "foo{{[0-9]+}}" matches strings like
|
|
|
|
* "foo0", "foo007", etc.
|
|
|
|
*/
|
|
|
|
static int compile_regex(const char *pattern, regex_t *regex)
|
|
|
|
{
|
|
|
|
char err_buf[256], buf[256] = {}, *ptr, *buf_end;
|
|
|
|
const char *original_pattern = pattern;
|
|
|
|
bool in_regex = false;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf_end = buf + sizeof(buf);
|
|
|
|
ptr = buf;
|
|
|
|
while (*pattern && ptr < buf_end - 2) {
|
|
|
|
if (!in_regex && str_has_pfx(pattern, "{{")) {
|
|
|
|
in_regex = true;
|
|
|
|
pattern += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (in_regex && str_has_pfx(pattern, "}}")) {
|
|
|
|
in_regex = false;
|
|
|
|
pattern += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (in_regex) {
|
|
|
|
*ptr++ = *pattern++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* list of characters that need escaping for extended posix regex */
|
|
|
|
if (strchr(".[]\\()*+?{}|^$", *pattern)) {
|
|
|
|
*ptr++ = '\\';
|
|
|
|
*ptr++ = *pattern++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*ptr++ = *pattern++;
|
|
|
|
}
|
|
|
|
if (*pattern) {
|
|
|
|
PRINT_FAIL("Regexp too long: '%s'\n", original_pattern);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
if (in_regex) {
|
|
|
|
PRINT_FAIL("Regexp has open '{{' but no closing '}}': '%s'\n", original_pattern);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
err = regcomp(regex, buf, REG_EXTENDED | REG_NEWLINE);
|
|
|
|
if (err != 0) {
|
|
|
|
regerror(err, regex, err_buf, sizeof(err_buf));
|
|
|
|
PRINT_FAIL("Regexp compilation error in '%s': '%s'\n", buf, err_buf);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __push_msg(const char *pattern, bool on_next_line, struct expected_msgs *msgs)
|
2023-07-11 07:20:42 +00:00
|
|
|
{
|
2024-11-26 08:58:32 +00:00
|
|
|
struct expect_msg *msg;
|
2024-12-18 11:21:43 +00:00
|
|
|
void *tmp;
|
|
|
|
int err;
|
2023-07-11 07:20:42 +00:00
|
|
|
|
2024-12-06 13:53:15 +00:00
|
|
|
tmp = realloc(msgs->patterns,
|
|
|
|
(1 + msgs->cnt) * sizeof(struct expect_msg));
|
2023-07-11 07:20:42 +00:00
|
|
|
if (!tmp) {
|
|
|
|
ASSERT_FAIL("failed to realloc memory for messages\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2024-12-06 13:53:15 +00:00
|
|
|
msgs->patterns = tmp;
|
|
|
|
msg = &msgs->patterns[msgs->cnt];
|
2024-12-18 11:21:43 +00:00
|
|
|
msg->on_next_line = on_next_line;
|
|
|
|
msg->substr = pattern;
|
|
|
|
msg->is_regex = false;
|
|
|
|
if (strstr(pattern, "{{")) {
|
|
|
|
err = compile_regex(pattern, &msg->regex);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
msg->is_regex = true;
|
2024-11-26 08:58:32 +00:00
|
|
|
}
|
2024-12-06 13:53:15 +00:00
|
|
|
msgs->cnt += 1;
|
2023-07-11 07:20:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:21:43 +00:00
|
|
|
static int clone_msgs(struct expected_msgs *from, struct expected_msgs *to)
|
|
|
|
{
|
|
|
|
struct expect_msg *msg;
|
|
|
|
int i, err;
|
|
|
|
|
|
|
|
for (i = 0; i < from->cnt; i++) {
|
|
|
|
msg = &from->patterns[i];
|
|
|
|
err = __push_msg(msg->substr, msg->on_next_line, to);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int push_msg(const char *substr, struct expected_msgs *msgs)
|
|
|
|
{
|
|
|
|
return __push_msg(substr, false, msgs);
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
static int push_disasm_msg(const char *regex_str, bool *on_next_line, struct expected_msgs *msgs)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (strcmp(regex_str, "...") == 0) {
|
|
|
|
*on_next_line = false;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
err = __push_msg(regex_str, *on_next_line, msgs);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
*on_next_line = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
static int parse_int(const char *str, int *val, const char *name)
|
|
|
|
{
|
|
|
|
char *end;
|
|
|
|
long tmp;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
if (str_has_pfx(str, "0x"))
|
|
|
|
tmp = strtol(str + 2, &end, 16);
|
|
|
|
else
|
|
|
|
tmp = strtol(str, &end, 10);
|
|
|
|
if (errno || end[0] != '\0') {
|
|
|
|
PRINT_FAIL("failed to parse %s from '%s'\n", name, str);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
*val = tmp;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_retval(const char *str, int *val, const char *name)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
char *name;
|
|
|
|
int val;
|
|
|
|
} named_values[] = {
|
|
|
|
{ "INT_MIN" , INT_MIN },
|
|
|
|
{ "POINTER_VALUE", POINTER_VALUE },
|
|
|
|
{ "TEST_DATA_LEN", TEST_DATA_LEN },
|
|
|
|
};
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(named_values); ++i) {
|
|
|
|
if (strcmp(str, named_values[i].name) != 0)
|
|
|
|
continue;
|
|
|
|
*val = named_values[i].val;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parse_int(str, val, name);
|
|
|
|
}
|
|
|
|
|
2024-04-15 09:55:55 +00:00
|
|
|
static void update_flags(int *flags, int flag, bool clear)
|
|
|
|
{
|
|
|
|
if (clear)
|
|
|
|
*flags &= ~flag;
|
|
|
|
else
|
|
|
|
*flags |= flag;
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:21:43 +00:00
|
|
|
/* Matches a string of form '<pfx>[^=]=.*' and returns it's suffix.
|
|
|
|
* Used to parse btf_decl_tag values.
|
|
|
|
* Such values require unique prefix because compiler does not add
|
|
|
|
* same __attribute__((btf_decl_tag(...))) twice.
|
|
|
|
* Test suite uses two-component tags for such cases:
|
|
|
|
*
|
|
|
|
* <pfx> __COUNTER__ '='
|
|
|
|
*
|
|
|
|
* For example, two consecutive __msg tags '__msg("foo") __msg("foo")'
|
|
|
|
* would be encoded as:
|
|
|
|
*
|
|
|
|
* [18] DECL_TAG 'comment:test_expect_msg=0=foo' type_id=15 component_idx=-1
|
|
|
|
* [19] DECL_TAG 'comment:test_expect_msg=1=foo' type_id=15 component_idx=-1
|
|
|
|
*
|
|
|
|
* And the purpose of this function is to extract 'foo' from the above.
|
|
|
|
*/
|
|
|
|
static const char *skip_dynamic_pfx(const char *s, const char *pfx)
|
|
|
|
{
|
|
|
|
const char *msg;
|
|
|
|
|
|
|
|
if (strncmp(s, pfx, strlen(pfx)) != 0)
|
|
|
|
return NULL;
|
|
|
|
msg = s + strlen(pfx);
|
|
|
|
msg = strchr(msg, '=');
|
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
return msg + 1;
|
|
|
|
}
|
|
|
|
|
2024-12-06 13:53:16 +00:00
|
|
|
enum arch {
|
2024-12-18 14:25:55 +00:00
|
|
|
ARCH_UNKNOWN = 0x1,
|
|
|
|
ARCH_X86_64 = 0x2,
|
|
|
|
ARCH_ARM64 = 0x4,
|
|
|
|
ARCH_RISCV64 = 0x8,
|
2024-12-06 13:53:16 +00:00
|
|
|
};
|
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
static int get_current_arch(void)
|
|
|
|
{
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
return ARCH_X86_64;
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
return ARCH_ARM64;
|
|
|
|
#elif defined(__riscv) && __riscv_xlen == 64
|
|
|
|
return ARCH_RISCV64;
|
|
|
|
#endif
|
2024-12-18 14:25:55 +00:00
|
|
|
return ARCH_UNKNOWN;
|
2024-12-18 11:28:17 +00:00
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
/* Uses btf_decl_tag attributes to describe the expected test
|
|
|
|
* behavior, see bpf_misc.h for detailed description of each attribute
|
|
|
|
* and attribute combinations.
|
|
|
|
*/
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
static int parse_test_spec(struct test_loader *tester,
|
|
|
|
struct bpf_object *obj,
|
|
|
|
struct bpf_program *prog,
|
|
|
|
struct test_spec *spec)
|
|
|
|
{
|
2023-07-11 07:20:42 +00:00
|
|
|
const char *description = NULL;
|
|
|
|
bool has_unpriv_result = false;
|
2023-07-11 07:20:42 +00:00
|
|
|
bool has_unpriv_retval = false;
|
2024-12-18 11:28:17 +00:00
|
|
|
bool unpriv_xlated_on_next_line = true;
|
|
|
|
bool xlated_on_next_line = true;
|
2024-12-18 11:28:17 +00:00
|
|
|
bool unpriv_jit_on_next_line;
|
|
|
|
bool jit_on_next_line;
|
|
|
|
bool collect_jit = false;
|
2023-07-11 07:20:42 +00:00
|
|
|
int func_id, i, err = 0;
|
2024-12-06 13:53:16 +00:00
|
|
|
u32 arch_mask = 0;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
struct btf *btf;
|
2024-12-18 11:28:17 +00:00
|
|
|
enum arch arch;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
memset(spec, 0, sizeof(*spec));
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
spec->prog_name = bpf_program__name(prog);
|
2024-06-10 12:09:23 +00:00
|
|
|
spec->prog_flags = testing_prog_flags();
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
btf = bpf_object__btf(obj);
|
|
|
|
if (!btf) {
|
|
|
|
ASSERT_FAIL("BPF object has no BTF");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
func_id = btf__find_by_name_kind(btf, spec->prog_name, BTF_KIND_FUNC);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
if (func_id < 0) {
|
2023-07-11 07:20:42 +00:00
|
|
|
ASSERT_FAIL("failed to find FUNC BTF type for '%s'", spec->prog_name);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 1; i < btf__type_cnt(btf); i++) {
|
2023-07-11 07:20:42 +00:00
|
|
|
const char *s, *val, *msg;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
const struct btf_type *t;
|
2024-04-15 09:55:55 +00:00
|
|
|
bool clear;
|
|
|
|
int flags;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
t = btf__type_by_id(btf, i);
|
|
|
|
if (!btf_is_decl_tag(t))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (t->type != func_id || btf_decl_tag(t)->component_idx != -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
s = btf__str_by_offset(btf, t->name_off);
|
2023-07-11 07:20:42 +00:00
|
|
|
if (str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX)) {
|
|
|
|
description = s + sizeof(TEST_TAG_DESCRIPTION_PFX) - 1;
|
|
|
|
} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE) == 0) {
|
|
|
|
spec->priv.expect_failure = true;
|
|
|
|
spec->mode_mask |= PRIV;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
} else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS) == 0) {
|
2023-07-11 07:20:42 +00:00
|
|
|
spec->priv.expect_failure = false;
|
|
|
|
spec->mode_mask |= PRIV;
|
|
|
|
} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE_UNPRIV) == 0) {
|
|
|
|
spec->unpriv.expect_failure = true;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
|
|
|
has_unpriv_result = true;
|
|
|
|
} else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS_UNPRIV) == 0) {
|
|
|
|
spec->unpriv.expect_failure = false;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
|
|
|
has_unpriv_result = true;
|
2023-07-11 08:07:22 +00:00
|
|
|
} else if (strcmp(s, TEST_TAG_AUXILIARY) == 0) {
|
|
|
|
spec->auxiliary = true;
|
|
|
|
spec->mode_mask |= PRIV;
|
|
|
|
} else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) {
|
|
|
|
spec->auxiliary = true;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
2024-12-18 11:21:43 +00:00
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) {
|
2024-12-18 11:21:43 +00:00
|
|
|
err = push_msg(msg, &spec->priv.expect_msgs);
|
2023-07-11 07:20:42 +00:00
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= PRIV;
|
2024-12-18 11:21:43 +00:00
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) {
|
2024-12-18 11:21:43 +00:00
|
|
|
err = push_msg(msg, &spec->unpriv.expect_msgs);
|
2023-07-11 07:20:42 +00:00
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
2024-12-18 11:28:17 +00:00
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX))) {
|
|
|
|
if (arch_mask == 0) {
|
|
|
|
PRINT_FAIL("__jited used before __arch_*");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (collect_jit) {
|
|
|
|
err = push_disasm_msg(msg, &jit_on_next_line,
|
|
|
|
&spec->priv.jited);
|
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= PRIV;
|
|
|
|
}
|
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX_UNPRIV))) {
|
|
|
|
if (arch_mask == 0) {
|
|
|
|
PRINT_FAIL("__unpriv_jited used before __arch_*");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (collect_jit) {
|
|
|
|
err = push_disasm_msg(msg, &unpriv_jit_on_next_line,
|
|
|
|
&spec->unpriv.jited);
|
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
|
|
|
}
|
2024-12-18 11:21:43 +00:00
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) {
|
2024-12-18 11:28:17 +00:00
|
|
|
err = push_disasm_msg(msg, &xlated_on_next_line,
|
|
|
|
&spec->priv.expect_xlated);
|
2024-12-06 13:53:16 +00:00
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= PRIV;
|
2024-12-18 11:21:43 +00:00
|
|
|
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) {
|
2024-12-18 11:28:17 +00:00
|
|
|
err = push_disasm_msg(msg, &unpriv_xlated_on_next_line,
|
|
|
|
&spec->unpriv.expect_xlated);
|
2024-12-06 13:53:16 +00:00
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
2023-07-11 07:20:42 +00:00
|
|
|
} else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX)) {
|
|
|
|
val = s + sizeof(TEST_TAG_RETVAL_PFX) - 1;
|
|
|
|
err = parse_retval(val, &spec->priv.retval, "__retval");
|
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->priv.execute = true;
|
|
|
|
spec->mode_mask |= PRIV;
|
|
|
|
} else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX_UNPRIV)) {
|
|
|
|
val = s + sizeof(TEST_TAG_RETVAL_PFX_UNPRIV) - 1;
|
|
|
|
err = parse_retval(val, &spec->unpriv.retval, "__retval_unpriv");
|
|
|
|
if (err)
|
|
|
|
goto cleanup;
|
|
|
|
spec->mode_mask |= UNPRIV;
|
|
|
|
spec->unpriv.execute = true;
|
|
|
|
has_unpriv_retval = true;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
} else if (str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX)) {
|
2023-07-10 12:46:35 +00:00
|
|
|
val = s + sizeof(TEST_TAG_LOG_LEVEL_PFX) - 1;
|
2023-07-11 07:20:42 +00:00
|
|
|
err = parse_int(val, &spec->log_level, "test log level");
|
|
|
|
if (err)
|
2023-07-11 07:20:42 +00:00
|
|
|
goto cleanup;
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX)) {
|
|
|
|
val = s + sizeof(TEST_TAG_PROG_FLAGS_PFX) - 1;
|
2024-04-15 09:55:55 +00:00
|
|
|
|
|
|
|
clear = val[0] == '!';
|
|
|
|
if (clear)
|
|
|
|
val++;
|
|
|
|
|
2023-07-10 12:46:35 +00:00
|
|
|
if (strcmp(val, "BPF_F_STRICT_ALIGNMENT") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_STRICT_ALIGNMENT, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_ANY_ALIGNMENT") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_ANY_ALIGNMENT, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_TEST_RND_HI32") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_TEST_RND_HI32, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_TEST_STATE_FREQ") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_TEST_STATE_FREQ, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_SLEEPABLE") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_SLEEPABLE, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_XDP_HAS_FRAGS") == 0) {
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, BPF_F_XDP_HAS_FRAGS, clear);
|
2024-04-15 09:55:55 +00:00
|
|
|
} else if (strcmp(val, "BPF_F_TEST_REG_INVARIANTS") == 0) {
|
|
|
|
update_flags(&spec->prog_flags, BPF_F_TEST_REG_INVARIANTS, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
} else /* assume numeric value */ {
|
2024-04-15 09:55:55 +00:00
|
|
|
err = parse_int(val, &flags, "test prog flags");
|
2023-07-11 07:20:42 +00:00
|
|
|
if (err)
|
2023-07-11 07:20:42 +00:00
|
|
|
goto cleanup;
|
2024-04-15 09:55:55 +00:00
|
|
|
update_flags(&spec->prog_flags, flags, clear);
|
2023-07-10 12:46:35 +00:00
|
|
|
}
|
2024-12-06 13:53:16 +00:00
|
|
|
} else if (str_has_pfx(s, TEST_TAG_ARCH)) {
|
|
|
|
val = s + sizeof(TEST_TAG_ARCH) - 1;
|
|
|
|
if (strcmp(val, "X86_64") == 0) {
|
2024-12-18 11:28:17 +00:00
|
|
|
arch = ARCH_X86_64;
|
2024-12-06 13:53:16 +00:00
|
|
|
} else if (strcmp(val, "ARM64") == 0) {
|
2024-12-18 11:28:17 +00:00
|
|
|
arch = ARCH_ARM64;
|
2024-12-06 13:53:16 +00:00
|
|
|
} else if (strcmp(val, "RISCV64") == 0) {
|
2024-12-18 11:28:17 +00:00
|
|
|
arch = ARCH_RISCV64;
|
2024-12-06 13:53:16 +00:00
|
|
|
} else {
|
|
|
|
PRINT_FAIL("bad arch spec: '%s'", val);
|
|
|
|
err = -EINVAL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2024-12-18 11:28:17 +00:00
|
|
|
arch_mask |= arch;
|
|
|
|
collect_jit = get_current_arch() == arch;
|
|
|
|
unpriv_jit_on_next_line = true;
|
|
|
|
jit_on_next_line = true;
|
2024-04-15 12:19:55 +00:00
|
|
|
} else if (str_has_pfx(s, TEST_BTF_PATH)) {
|
|
|
|
spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:29:53 +00:00
|
|
|
spec->arch_mask = arch_mask ?: -1;
|
2024-12-06 13:53:16 +00:00
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
if (spec->mode_mask == 0)
|
|
|
|
spec->mode_mask = PRIV;
|
|
|
|
|
|
|
|
if (!description)
|
|
|
|
description = spec->prog_name;
|
|
|
|
|
|
|
|
if (spec->mode_mask & PRIV) {
|
|
|
|
spec->priv.name = strdup(description);
|
|
|
|
if (!spec->priv.name) {
|
|
|
|
PRINT_FAIL("failed to allocate memory for priv.name\n");
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spec->mode_mask & UNPRIV) {
|
|
|
|
int descr_len = strlen(description);
|
|
|
|
const char *suffix = " @unpriv";
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
name = malloc(descr_len + strlen(suffix) + 1);
|
|
|
|
if (!name) {
|
|
|
|
PRINT_FAIL("failed to allocate memory for unpriv.name\n");
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(name, description);
|
|
|
|
strcpy(&name[descr_len], suffix);
|
|
|
|
spec->unpriv.name = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spec->mode_mask & (PRIV | UNPRIV)) {
|
|
|
|
if (!has_unpriv_result)
|
|
|
|
spec->unpriv.expect_failure = spec->priv.expect_failure;
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
if (!has_unpriv_retval) {
|
|
|
|
spec->unpriv.retval = spec->priv.retval;
|
|
|
|
spec->unpriv.execute = spec->priv.execute;
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:21:43 +00:00
|
|
|
if (spec->unpriv.expect_msgs.cnt == 0)
|
|
|
|
clone_msgs(&spec->priv.expect_msgs, &spec->unpriv.expect_msgs);
|
|
|
|
if (spec->unpriv.expect_xlated.cnt == 0)
|
|
|
|
clone_msgs(&spec->priv.expect_xlated, &spec->unpriv.expect_xlated);
|
2024-12-18 11:28:17 +00:00
|
|
|
if (spec->unpriv.jited.cnt == 0)
|
|
|
|
clone_msgs(&spec->priv.jited, &spec->unpriv.jited);
|
2023-07-11 07:20:42 +00:00
|
|
|
}
|
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
spec->valid = true;
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
return 0;
|
2023-07-11 07:20:42 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free_test_spec(spec);
|
|
|
|
return err;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void prepare_case(struct test_loader *tester,
|
|
|
|
struct test_spec *spec,
|
|
|
|
struct bpf_object *obj,
|
|
|
|
struct bpf_program *prog)
|
|
|
|
{
|
2023-07-10 12:46:35 +00:00
|
|
|
int min_log_level = 0, prog_flags;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
if (env.verbosity > VERBOSE_NONE)
|
|
|
|
min_log_level = 1;
|
|
|
|
if (env.verbosity > VERBOSE_VERY)
|
|
|
|
min_log_level = 2;
|
|
|
|
|
|
|
|
bpf_program__set_log_buf(prog, tester->log_buf, tester->log_buf_sz);
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
/* Make sure we set at least minimal log level, unless test requires
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
* even higher level already. Make sure to preserve independent log
|
|
|
|
* level 4 (verifier stats), though.
|
|
|
|
*/
|
|
|
|
if ((spec->log_level & 3) < min_log_level)
|
|
|
|
bpf_program__set_log_level(prog, (spec->log_level & 4) | min_log_level);
|
|
|
|
else
|
|
|
|
bpf_program__set_log_level(prog, spec->log_level);
|
|
|
|
|
2023-07-10 12:46:35 +00:00
|
|
|
prog_flags = bpf_program__flags(prog);
|
|
|
|
bpf_program__set_flags(prog, prog_flags | spec->prog_flags);
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
tester->log_buf[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static void emit_verifier_log(const char *log_buf, bool force)
|
|
|
|
{
|
|
|
|
if (!force && env.verbosity == VERBOSE_NONE)
|
|
|
|
return;
|
|
|
|
fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log_buf);
|
|
|
|
}
|
|
|
|
|
2024-12-06 13:53:16 +00:00
|
|
|
static void emit_xlated(const char *xlated, bool force)
|
|
|
|
{
|
|
|
|
if (!force && env.verbosity == VERBOSE_NONE)
|
|
|
|
return;
|
|
|
|
fprintf(stdout, "XLATED:\n=============\n%s=============\n", xlated);
|
|
|
|
}
|
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
static void emit_jited(const char *jited, bool force)
|
|
|
|
{
|
|
|
|
if (!force && env.verbosity == VERBOSE_NONE)
|
|
|
|
return;
|
|
|
|
fprintf(stdout, "JITED:\n=============\n%s=============\n", jited);
|
|
|
|
}
|
|
|
|
|
2024-12-06 13:53:16 +00:00
|
|
|
static void validate_msgs(char *log_buf, struct expected_msgs *msgs,
|
|
|
|
void (*emit_fn)(const char *buf, bool force))
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
{
|
2024-12-18 11:28:17 +00:00
|
|
|
const char *log = log_buf, *prev_match;
|
2024-11-26 08:58:32 +00:00
|
|
|
regmatch_t reg_match[1];
|
2024-12-18 11:28:17 +00:00
|
|
|
int prev_match_line;
|
|
|
|
int match_line;
|
2024-12-06 13:53:15 +00:00
|
|
|
int i, j, err;
|
2023-07-10 12:46:35 +00:00
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
prev_match_line = -1;
|
|
|
|
match_line = 0;
|
|
|
|
prev_match = log;
|
2024-12-06 13:53:15 +00:00
|
|
|
for (i = 0; i < msgs->cnt; i++) {
|
|
|
|
struct expect_msg *msg = &msgs->patterns[i];
|
2024-12-18 11:28:17 +00:00
|
|
|
const char *match = NULL, *pat_status;
|
|
|
|
bool wrong_line = false;
|
2024-11-26 08:58:32 +00:00
|
|
|
|
2024-12-18 11:21:43 +00:00
|
|
|
if (!msg->is_regex) {
|
2024-12-06 13:53:15 +00:00
|
|
|
match = strstr(log, msg->substr);
|
2024-11-26 08:58:32 +00:00
|
|
|
if (match)
|
2024-12-18 11:21:43 +00:00
|
|
|
log = match + strlen(msg->substr);
|
2024-11-26 08:58:32 +00:00
|
|
|
} else {
|
2024-12-06 13:53:15 +00:00
|
|
|
err = regexec(&msg->regex, log, 1, reg_match, 0);
|
2024-11-26 08:58:32 +00:00
|
|
|
if (err == 0) {
|
2024-12-06 13:53:15 +00:00
|
|
|
match = log + reg_match[0].rm_so;
|
|
|
|
log += reg_match[0].rm_eo;
|
2024-11-26 08:58:32 +00:00
|
|
|
}
|
|
|
|
}
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
if (match) {
|
|
|
|
for (; prev_match < match; ++prev_match)
|
|
|
|
if (*prev_match == '\n')
|
|
|
|
++match_line;
|
|
|
|
wrong_line = msg->on_next_line && prev_match_line >= 0 &&
|
|
|
|
prev_match_line + 1 != match_line;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!match || wrong_line) {
|
2024-12-18 11:21:42 +00:00
|
|
|
PRINT_FAIL("expect_msg\n");
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
if (env.verbosity == VERBOSE_NONE)
|
2024-12-06 13:53:16 +00:00
|
|
|
emit_fn(log_buf, true /*force*/);
|
2024-11-26 08:58:32 +00:00
|
|
|
for (j = 0; j <= i; j++) {
|
2024-12-06 13:53:15 +00:00
|
|
|
msg = &msgs->patterns[j];
|
2024-12-18 11:28:17 +00:00
|
|
|
if (j < i)
|
|
|
|
pat_status = "MATCHED ";
|
|
|
|
else if (wrong_line)
|
|
|
|
pat_status = "WRONG LINE";
|
|
|
|
else
|
|
|
|
pat_status = "EXPECTED ";
|
|
|
|
msg = &msgs->patterns[j];
|
2024-11-26 08:58:32 +00:00
|
|
|
fprintf(stderr, "%s %s: '%s'\n",
|
2024-12-18 11:28:17 +00:00
|
|
|
pat_status,
|
2024-12-18 11:21:43 +00:00
|
|
|
msg->is_regex ? " REGEX" : "SUBSTR",
|
|
|
|
msg->substr);
|
2024-11-26 08:58:32 +00:00
|
|
|
}
|
2024-12-18 11:28:17 +00:00
|
|
|
if (wrong_line) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"expecting match at line %d, actual match is at line %d\n",
|
|
|
|
prev_match_line + 1, match_line);
|
|
|
|
}
|
|
|
|
break;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
}
|
2024-12-18 11:28:17 +00:00
|
|
|
|
|
|
|
prev_match_line = match_line;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
struct cap_state {
|
|
|
|
__u64 old_caps;
|
|
|
|
bool initialized;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int drop_capabilities(struct cap_state *caps)
|
|
|
|
{
|
|
|
|
const __u64 caps_to_drop = (1ULL << CAP_SYS_ADMIN | 1ULL << CAP_NET_ADMIN |
|
|
|
|
1ULL << CAP_PERFMON | 1ULL << CAP_BPF);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = cap_disable_effective(caps_to_drop, &caps->old_caps);
|
|
|
|
if (err) {
|
|
|
|
PRINT_FAIL("failed to drop capabilities: %i, %s\n", err, strerror(err));
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
caps->initialized = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int restore_capabilities(struct cap_state *caps)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!caps->initialized)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err = cap_enable_effective(caps->old_caps, NULL);
|
|
|
|
if (err)
|
|
|
|
PRINT_FAIL("failed to restore capabilities: %i, %s\n", err, strerror(err));
|
|
|
|
caps->initialized = false;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool can_execute_unpriv(struct test_loader *tester, struct test_spec *spec)
|
|
|
|
{
|
|
|
|
if (sysctl_unpriv_disabled < 0)
|
|
|
|
sysctl_unpriv_disabled = get_unpriv_disabled() ? 1 : 0;
|
|
|
|
if (sysctl_unpriv_disabled)
|
|
|
|
return false;
|
|
|
|
if ((spec->prog_flags & BPF_F_ANY_ALIGNMENT) && !EFFICIENT_UNALIGNED_ACCESS)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_unpriv_capable_map(struct bpf_map *map)
|
|
|
|
{
|
|
|
|
enum bpf_map_type type;
|
|
|
|
__u32 flags;
|
|
|
|
|
|
|
|
type = bpf_map__type(map);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case BPF_MAP_TYPE_HASH:
|
|
|
|
case BPF_MAP_TYPE_PERCPU_HASH:
|
|
|
|
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
|
|
|
flags = bpf_map__map_flags(map);
|
|
|
|
return !(flags & BPF_F_ZERO_SEED);
|
|
|
|
case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
|
|
|
|
case BPF_MAP_TYPE_ARRAY:
|
|
|
|
case BPF_MAP_TYPE_RINGBUF:
|
|
|
|
case BPF_MAP_TYPE_PROG_ARRAY:
|
|
|
|
case BPF_MAP_TYPE_CGROUP_ARRAY:
|
|
|
|
case BPF_MAP_TYPE_PERCPU_ARRAY:
|
|
|
|
case BPF_MAP_TYPE_USER_RINGBUF:
|
|
|
|
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
|
|
|
case BPF_MAP_TYPE_CGROUP_STORAGE:
|
|
|
|
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-25 09:52:05 +00:00
|
|
|
static int do_prog_test_run(int fd_prog, int *retval, bool empty_opts)
|
2023-07-11 07:20:42 +00:00
|
|
|
{
|
|
|
|
__u8 tmp_out[TEST_DATA_LEN << 2] = {};
|
|
|
|
__u8 tmp_in[TEST_DATA_LEN] = {};
|
|
|
|
int err, saved_errno;
|
|
|
|
LIBBPF_OPTS(bpf_test_run_opts, topts,
|
|
|
|
.data_in = tmp_in,
|
|
|
|
.data_size_in = sizeof(tmp_in),
|
|
|
|
.data_out = tmp_out,
|
|
|
|
.data_size_out = sizeof(tmp_out),
|
|
|
|
.repeat = 1,
|
|
|
|
);
|
|
|
|
|
2024-06-25 09:52:05 +00:00
|
|
|
if (empty_opts) {
|
|
|
|
memset(&topts, 0, sizeof(struct bpf_test_run_opts));
|
|
|
|
topts.sz = sizeof(struct bpf_test_run_opts);
|
|
|
|
}
|
2023-07-11 07:20:42 +00:00
|
|
|
err = bpf_prog_test_run_opts(fd_prog, &topts);
|
|
|
|
saved_errno = errno;
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
PRINT_FAIL("FAIL: Unexpected bpf_prog_test_run error: %d (%s) ",
|
|
|
|
saved_errno, strerror(saved_errno));
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_OK(0, "bpf_prog_test_run");
|
|
|
|
*retval = topts.retval;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool should_do_test_run(struct test_spec *spec, struct test_subspec *subspec)
|
|
|
|
{
|
|
|
|
if (!subspec->execute)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (subspec->expect_failure)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((spec->prog_flags & BPF_F_ANY_ALIGNMENT) && !EFFICIENT_UNALIGNED_ACCESS) {
|
|
|
|
if (env.verbosity != VERBOSE_NONE)
|
|
|
|
printf("alignment prevents execution\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-12-06 13:53:16 +00:00
|
|
|
/* Get a disassembly of BPF program after verifier applies all rewrites */
|
|
|
|
static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz)
|
|
|
|
{
|
|
|
|
struct bpf_insn *insn_start = NULL, *insn, *insn_end;
|
|
|
|
__u32 insns_cnt = 0, i;
|
|
|
|
char buf[64];
|
|
|
|
FILE *out = NULL;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_xlated_program(prog_fd, &insn_start, &insns_cnt);
|
|
|
|
if (!ASSERT_OK(err, "get_xlated_program"))
|
|
|
|
goto out;
|
|
|
|
out = fmemopen(text, text_sz, "w");
|
|
|
|
if (!ASSERT_OK_PTR(out, "open_memstream"))
|
|
|
|
goto out;
|
|
|
|
insn_end = insn_start + insns_cnt;
|
|
|
|
insn = insn_start;
|
|
|
|
while (insn < insn_end) {
|
|
|
|
i = insn - insn_start;
|
|
|
|
insn = disasm_insn(insn, buf, sizeof(buf));
|
|
|
|
fprintf(out, "%d: %s\n", i, buf);
|
|
|
|
}
|
|
|
|
fflush(out);
|
|
|
|
|
|
|
|
out:
|
|
|
|
free(insn_start);
|
|
|
|
if (out)
|
|
|
|
fclose(out);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
/* this function is forced noinline and has short generic name to look better
|
|
|
|
* in test_progs output (in case of a failure)
|
|
|
|
*/
|
|
|
|
static noinline
|
|
|
|
void run_subtest(struct test_loader *tester,
|
2023-07-11 07:20:42 +00:00
|
|
|
struct bpf_object_open_opts *open_opts,
|
|
|
|
const void *obj_bytes,
|
|
|
|
size_t obj_byte_cnt,
|
2023-07-11 08:07:22 +00:00
|
|
|
struct test_spec *specs,
|
2023-07-11 07:20:42 +00:00
|
|
|
struct test_spec *spec,
|
|
|
|
bool unpriv)
|
|
|
|
{
|
|
|
|
struct test_subspec *subspec = unpriv ? &spec->unpriv : &spec->priv;
|
2024-03-06 12:21:05 +00:00
|
|
|
struct bpf_program *tprog = NULL, *tprog_iter;
|
2024-12-18 14:37:21 +00:00
|
|
|
struct bpf_link *link, *links[32] = {};
|
2023-07-11 08:07:22 +00:00
|
|
|
struct test_spec *spec_iter;
|
2023-07-11 07:20:42 +00:00
|
|
|
struct cap_state caps = {};
|
|
|
|
struct bpf_object *tobj;
|
|
|
|
struct bpf_map *map;
|
2023-07-11 08:07:22 +00:00
|
|
|
int retval, err, i;
|
2024-12-18 14:37:21 +00:00
|
|
|
int links_cnt = 0;
|
2023-07-11 08:07:22 +00:00
|
|
|
bool should_load;
|
2023-07-11 07:20:42 +00:00
|
|
|
|
|
|
|
if (!test__start_subtest(subspec->name))
|
|
|
|
return;
|
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
if ((get_current_arch() & spec->arch_mask) == 0) {
|
2024-12-06 13:53:16 +00:00
|
|
|
test__skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
if (unpriv) {
|
|
|
|
if (!can_execute_unpriv(tester, spec)) {
|
|
|
|
test__skip();
|
|
|
|
test__end_subtest();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (drop_capabilities(&caps)) {
|
|
|
|
test__end_subtest();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-15 12:19:55 +00:00
|
|
|
/* Implicitly reset to NULL if next test case doesn't specify */
|
|
|
|
open_opts->btf_custom_path = spec->btf_custom_path;
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
tobj = bpf_object__open_mem(obj_bytes, obj_byte_cnt, open_opts);
|
|
|
|
if (!ASSERT_OK_PTR(tobj, "obj_open_mem")) /* shouldn't happen */
|
|
|
|
goto subtest_cleanup;
|
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
i = 0;
|
|
|
|
bpf_object__for_each_program(tprog_iter, tobj) {
|
|
|
|
spec_iter = &specs[i++];
|
|
|
|
should_load = false;
|
|
|
|
|
|
|
|
if (spec_iter->valid) {
|
|
|
|
if (strcmp(bpf_program__name(tprog_iter), spec->prog_name) == 0) {
|
|
|
|
tprog = tprog_iter;
|
|
|
|
should_load = true;
|
|
|
|
}
|
2023-07-11 07:20:42 +00:00
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
if (spec_iter->auxiliary &&
|
|
|
|
spec_iter->mode_mask & (unpriv ? UNPRIV : PRIV))
|
|
|
|
should_load = true;
|
2023-07-11 07:20:42 +00:00
|
|
|
}
|
2023-07-11 08:07:22 +00:00
|
|
|
|
|
|
|
bpf_program__set_autoload(tprog_iter, should_load);
|
2023-07-11 07:20:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
prepare_case(tester, spec, tobj, tprog);
|
|
|
|
|
|
|
|
/* By default bpf_object__load() automatically creates all
|
|
|
|
* maps declared in the skeleton. Some map types are only
|
|
|
|
* allowed in priv mode. Disable autoload for such maps in
|
|
|
|
* unpriv mode.
|
|
|
|
*/
|
|
|
|
bpf_object__for_each_map(map, tobj)
|
|
|
|
bpf_map__set_autocreate(map, !unpriv || is_unpriv_capable_map(map));
|
|
|
|
|
|
|
|
err = bpf_object__load(tobj);
|
|
|
|
if (subspec->expect_failure) {
|
|
|
|
if (!ASSERT_ERR(err, "unexpected_load_success")) {
|
|
|
|
emit_verifier_log(tester->log_buf, false /*force*/);
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!ASSERT_OK(err, "unexpected_load_failure")) {
|
|
|
|
emit_verifier_log(tester->log_buf, true /*force*/);
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
emit_verifier_log(tester->log_buf, false /*force*/);
|
2024-12-06 13:53:16 +00:00
|
|
|
validate_msgs(tester->log_buf, &subspec->expect_msgs, emit_verifier_log);
|
|
|
|
|
|
|
|
if (subspec->expect_xlated.cnt) {
|
|
|
|
err = get_xlated_program_text(bpf_program__fd(tprog),
|
|
|
|
tester->log_buf, tester->log_buf_sz);
|
|
|
|
if (err)
|
|
|
|
goto tobj_cleanup;
|
|
|
|
emit_xlated(tester->log_buf, false /*force*/);
|
|
|
|
validate_msgs(tester->log_buf, &subspec->expect_xlated, emit_xlated);
|
|
|
|
}
|
2023-07-11 07:20:42 +00:00
|
|
|
|
2024-12-18 11:28:17 +00:00
|
|
|
if (subspec->jited.cnt) {
|
|
|
|
err = get_jited_program_text(bpf_program__fd(tprog),
|
|
|
|
tester->log_buf, tester->log_buf_sz);
|
|
|
|
if (err == -EOPNOTSUPP) {
|
|
|
|
printf("%s:SKIP: jited programs disassembly is not supported,\n", __func__);
|
|
|
|
printf("%s:SKIP: tests are built w/o LLVM development libs\n", __func__);
|
|
|
|
test__skip();
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
if (!ASSERT_EQ(err, 0, "get_jited_program_text"))
|
|
|
|
goto tobj_cleanup;
|
|
|
|
emit_jited(tester->log_buf, false /*force*/);
|
|
|
|
validate_msgs(tester->log_buf, &subspec->jited, emit_jited);
|
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
if (should_do_test_run(spec, subspec)) {
|
|
|
|
/* For some reason test_verifier executes programs
|
|
|
|
* with all capabilities restored. Do the same here.
|
|
|
|
*/
|
2023-07-11 08:07:21 +00:00
|
|
|
if (restore_capabilities(&caps))
|
2023-07-11 07:20:42 +00:00
|
|
|
goto tobj_cleanup;
|
|
|
|
|
2024-12-18 14:37:21 +00:00
|
|
|
/* Do bpf_map__attach_struct_ops() for each struct_ops map.
|
|
|
|
* This should trigger bpf_struct_ops->reg callback on kernel side.
|
|
|
|
*/
|
|
|
|
bpf_object__for_each_map(map, tobj) {
|
|
|
|
if (!bpf_map__autocreate(map) ||
|
|
|
|
bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
|
|
|
|
continue;
|
|
|
|
if (links_cnt >= ARRAY_SIZE(links)) {
|
|
|
|
PRINT_FAIL("too many struct_ops maps");
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
link = bpf_map__attach_struct_ops(map);
|
|
|
|
if (!link) {
|
|
|
|
PRINT_FAIL("bpf_map__attach_struct_ops failed for map %s: err=%d\n",
|
|
|
|
bpf_map__name(map), err);
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
links[links_cnt++] = link;
|
|
|
|
}
|
|
|
|
|
2023-07-11 08:07:21 +00:00
|
|
|
if (tester->pre_execution_cb) {
|
|
|
|
err = tester->pre_execution_cb(tobj);
|
|
|
|
if (err) {
|
|
|
|
PRINT_FAIL("pre_execution_cb failed: %d\n", err);
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-25 09:52:05 +00:00
|
|
|
do_prog_test_run(bpf_program__fd(tprog), &retval,
|
|
|
|
bpf_program__type(tprog) == BPF_PROG_TYPE_SYSCALL ? true : false);
|
2023-07-11 07:20:42 +00:00
|
|
|
if (retval != subspec->retval && subspec->retval != POINTER_VALUE) {
|
|
|
|
PRINT_FAIL("Unexpected retval: %d != %d\n", retval, subspec->retval);
|
|
|
|
goto tobj_cleanup;
|
|
|
|
}
|
2024-12-18 14:37:21 +00:00
|
|
|
/* redo bpf_map__attach_struct_ops for each test */
|
|
|
|
while (links_cnt > 0)
|
|
|
|
bpf_link__destroy(links[--links_cnt]);
|
2023-07-11 07:20:42 +00:00
|
|
|
}
|
|
|
|
|
2023-07-11 07:20:42 +00:00
|
|
|
tobj_cleanup:
|
2024-12-18 14:37:21 +00:00
|
|
|
while (links_cnt > 0)
|
|
|
|
bpf_link__destroy(links[--links_cnt]);
|
2023-07-11 07:20:42 +00:00
|
|
|
bpf_object__close(tobj);
|
|
|
|
subtest_cleanup:
|
|
|
|
test__end_subtest();
|
|
|
|
restore_capabilities(&caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void process_subtest(struct test_loader *tester,
|
|
|
|
const char *skel_name,
|
|
|
|
skel_elf_bytes_fn elf_bytes_factory)
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
{
|
|
|
|
LIBBPF_OPTS(bpf_object_open_opts, open_opts, .object_name = skel_name);
|
2023-07-11 08:07:22 +00:00
|
|
|
struct test_spec *specs = NULL;
|
2023-07-11 07:20:42 +00:00
|
|
|
struct bpf_object *obj = NULL;
|
|
|
|
struct bpf_program *prog;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
const void *obj_bytes;
|
2023-07-11 08:07:22 +00:00
|
|
|
int err, i, nr_progs;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
size_t obj_byte_cnt;
|
|
|
|
|
|
|
|
if (tester_init(tester) < 0)
|
|
|
|
return; /* failed to initialize tester */
|
|
|
|
|
|
|
|
obj_bytes = elf_bytes_factory(&obj_byte_cnt);
|
|
|
|
obj = bpf_object__open_mem(obj_bytes, obj_byte_cnt, &open_opts);
|
|
|
|
if (!ASSERT_OK_PTR(obj, "obj_open_mem"))
|
|
|
|
return;
|
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
nr_progs = 0;
|
|
|
|
bpf_object__for_each_program(prog, obj)
|
|
|
|
++nr_progs;
|
|
|
|
|
|
|
|
specs = calloc(nr_progs, sizeof(struct test_spec));
|
2024-06-10 08:39:58 +00:00
|
|
|
if (!ASSERT_OK_PTR(specs, "specs_alloc"))
|
2023-07-11 08:07:22 +00:00
|
|
|
return;
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
i = 0;
|
|
|
|
bpf_object__for_each_program(prog, obj) {
|
|
|
|
/* ignore tests for which we can't derive test specification */
|
|
|
|
err = parse_test_spec(tester, obj, prog, &specs[i++]);
|
|
|
|
if (err)
|
2023-07-11 07:20:42 +00:00
|
|
|
PRINT_FAIL("Can't parse test spec for program '%s'\n",
|
|
|
|
bpf_program__name(prog));
|
2023-07-11 08:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
bpf_object__for_each_program(prog, obj) {
|
|
|
|
struct test_spec *spec = &specs[i++];
|
|
|
|
|
|
|
|
if (!spec->valid || spec->auxiliary)
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
continue;
|
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
if (spec->mode_mask & PRIV)
|
|
|
|
run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
|
|
|
|
specs, spec, false);
|
|
|
|
if (spec->mode_mask & UNPRIV)
|
|
|
|
run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
|
|
|
|
specs, spec, true);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-11 08:07:22 +00:00
|
|
|
for (i = 0; i < nr_progs; ++i)
|
|
|
|
free_test_spec(&specs[i]);
|
|
|
|
free(specs);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
bpf_object__close(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_loader__run_subtests(struct test_loader *tester,
|
|
|
|
const char *skel_name,
|
|
|
|
skel_elf_bytes_fn elf_bytes_factory)
|
|
|
|
{
|
|
|
|
/* see comment in run_subtest() for why we do this function nesting */
|
2023-07-11 07:20:42 +00:00
|
|
|
process_subtest(tester, skel_name, elf_bytes_factory);
|
selftests/bpf: add generic BPF program tester-loader
Bugzilla: https://bugzilla.redhat.com/2177177
commit 537c3f66eac137a02ec50a40219d2da6597e5dc9
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Wed Dec 7 12:16:47 2022 -0800
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-21 14:14:32 +00:00
|
|
|
}
|