mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
selftests/bpf: Enable signature verification for some lskel tests
The test harness uses the verify_sig_setup.sh to generate the required key material for program signing. Generate key material for signing LSKEL some lskel programs and use xxd to convert the verification certificate into a C header file. Finally, update the main test runner to load this certificate into the session keyring via the add_key() syscall before executing any tests. Use the session keyring in the tests with signed programs. Signed-off-by: KP Singh <kpsingh@kernel.org> Link: https://lore.kernel.org/r/20250921160120.9711-6-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
committed by
Alexei Starovoitov
parent
40863f4d6e
commit
b720903e2b
1
tools/testing/selftests/bpf/.gitignore
vendored
1
tools/testing/selftests/bpf/.gitignore
vendored
@@ -44,3 +44,4 @@ xdp_redirect_multi
|
|||||||
xdp_synproxy
|
xdp_synproxy
|
||||||
xdp_hw_metadata
|
xdp_hw_metadata
|
||||||
xdp_features
|
xdp_features
|
||||||
|
verification_cert.h
|
||||||
|
|||||||
@@ -496,15 +496,16 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
|
|||||||
test_subskeleton.skel.h test_subskeleton_lib.skel.h \
|
test_subskeleton.skel.h test_subskeleton_lib.skel.h \
|
||||||
test_usdt.skel.h
|
test_usdt.skel.h
|
||||||
|
|
||||||
LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c \
|
LSKELS := fexit_sleep.c trace_printk.c trace_vprintk.c map_ptr_kern.c \
|
||||||
trace_printk.c trace_vprintk.c map_ptr_kern.c \
|
|
||||||
core_kern.c core_kern_overflow.c test_ringbuf.c \
|
core_kern.c core_kern_overflow.c test_ringbuf.c \
|
||||||
test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c
|
test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c
|
||||||
|
|
||||||
|
LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c
|
||||||
|
|
||||||
# Generate both light skeleton and libbpf skeleton for these
|
# Generate both light skeleton and libbpf skeleton for these
|
||||||
LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
|
LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
|
||||||
kfunc_call_test_subprog.c
|
kfunc_call_test_subprog.c
|
||||||
SKEL_BLACKLIST += $$(LSKELS)
|
SKEL_BLACKLIST += $$(LSKELS) $$(LSKELS_SIGNED)
|
||||||
|
|
||||||
test_static_linked.skel.h-deps := test_static_linked1.bpf.o test_static_linked2.bpf.o
|
test_static_linked.skel.h-deps := test_static_linked1.bpf.o test_static_linked2.bpf.o
|
||||||
linked_funcs.skel.h-deps := linked_funcs1.bpf.o linked_funcs2.bpf.o
|
linked_funcs.skel.h-deps := linked_funcs1.bpf.o linked_funcs2.bpf.o
|
||||||
@@ -535,6 +536,7 @@ HEADERS_FOR_BPF_OBJS := $(wildcard $(BPFDIR)/*.bpf.h) \
|
|||||||
# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc)
|
# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc)
|
||||||
define DEFINE_TEST_RUNNER
|
define DEFINE_TEST_RUNNER
|
||||||
|
|
||||||
|
LSKEL_SIGN := -S -k $(PRIVATE_KEY) -i $(VERIFICATION_CERT)
|
||||||
TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
|
TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
|
||||||
TRUNNER_BINARY := $1$(if $2,-)$2
|
TRUNNER_BINARY := $1$(if $2,-)$2
|
||||||
TRUNNER_TEST_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.test.o, \
|
TRUNNER_TEST_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.test.o, \
|
||||||
@@ -550,6 +552,7 @@ TRUNNER_BPF_SKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.skel.h, \
|
|||||||
$$(TRUNNER_BPF_SRCS)))
|
$$(TRUNNER_BPF_SRCS)))
|
||||||
TRUNNER_BPF_LSKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS) $$(LSKELS_EXTRA))
|
TRUNNER_BPF_LSKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS) $$(LSKELS_EXTRA))
|
||||||
TRUNNER_BPF_SKELS_LINKED := $$(addprefix $$(TRUNNER_OUTPUT)/,$(LINKED_SKELS))
|
TRUNNER_BPF_SKELS_LINKED := $$(addprefix $$(TRUNNER_OUTPUT)/,$(LINKED_SKELS))
|
||||||
|
TRUNNER_BPF_LSKELS_SIGNED := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS_SIGNED))
|
||||||
TEST_GEN_FILES += $$(TRUNNER_BPF_OBJS)
|
TEST_GEN_FILES += $$(TRUNNER_BPF_OBJS)
|
||||||
|
|
||||||
# Evaluate rules now with extra TRUNNER_XXX variables above already defined
|
# Evaluate rules now with extra TRUNNER_XXX variables above already defined
|
||||||
@@ -604,6 +607,15 @@ $(TRUNNER_BPF_LSKELS): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
|
|||||||
$(Q)$$(BPFTOOL) gen skeleton -L $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@
|
$(Q)$$(BPFTOOL) gen skeleton -L $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@
|
||||||
$(Q)rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
|
$(Q)rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
|
||||||
|
|
||||||
|
$(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
|
||||||
|
$$(call msg,GEN-SKEL,$(TRUNNER_BINARY) (signed),$$@)
|
||||||
|
$(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked1.o) $$<
|
||||||
|
$(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o)
|
||||||
|
$(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o)
|
||||||
|
$(Q)diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
|
||||||
|
$(Q)$$(BPFTOOL) gen skeleton $(LSKEL_SIGN) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@
|
||||||
|
$(Q)rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
|
||||||
|
|
||||||
$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
|
$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
|
||||||
|
|
||||||
# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
|
# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
|
||||||
@@ -653,6 +665,7 @@ $(TRUNNER_TEST_OBJS:.o=.d): $(TRUNNER_OUTPUT)/%.test.d: \
|
|||||||
$(TRUNNER_EXTRA_HDRS) \
|
$(TRUNNER_EXTRA_HDRS) \
|
||||||
$(TRUNNER_BPF_SKELS) \
|
$(TRUNNER_BPF_SKELS) \
|
||||||
$(TRUNNER_BPF_LSKELS) \
|
$(TRUNNER_BPF_LSKELS) \
|
||||||
|
$(TRUNNER_BPF_LSKELS_SIGNED) \
|
||||||
$(TRUNNER_BPF_SKELS_LINKED) \
|
$(TRUNNER_BPF_SKELS_LINKED) \
|
||||||
$$(BPFOBJ) | $(TRUNNER_OUTPUT)
|
$$(BPFOBJ) | $(TRUNNER_OUTPUT)
|
||||||
|
|
||||||
@@ -667,6 +680,7 @@ $(foreach N,$(patsubst $(TRUNNER_OUTPUT)/%.o,%,$(TRUNNER_EXTRA_OBJS)), \
|
|||||||
$(TRUNNER_EXTRA_OBJS): $(TRUNNER_OUTPUT)/%.o: \
|
$(TRUNNER_EXTRA_OBJS): $(TRUNNER_OUTPUT)/%.o: \
|
||||||
%.c \
|
%.c \
|
||||||
$(TRUNNER_EXTRA_HDRS) \
|
$(TRUNNER_EXTRA_HDRS) \
|
||||||
|
$(VERIFY_SIG_HDR) \
|
||||||
$(TRUNNER_TESTS_HDR) \
|
$(TRUNNER_TESTS_HDR) \
|
||||||
$$(BPFOBJ) | $(TRUNNER_OUTPUT)
|
$$(BPFOBJ) | $(TRUNNER_OUTPUT)
|
||||||
$$(call msg,EXT-OBJ,$(TRUNNER_BINARY),$$@)
|
$$(call msg,EXT-OBJ,$(TRUNNER_BINARY),$$@)
|
||||||
@@ -697,6 +711,18 @@ $(OUTPUT)/$(TRUNNER_BINARY): $(TRUNNER_TEST_OBJS) \
|
|||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
VERIFY_SIG_SETUP := $(CURDIR)/verify_sig_setup.sh
|
||||||
|
VERIFY_SIG_HDR := verification_cert.h
|
||||||
|
VERIFICATION_CERT := $(BUILD_DIR)/signing_key.der
|
||||||
|
PRIVATE_KEY := $(BUILD_DIR)/signing_key.pem
|
||||||
|
|
||||||
|
$(VERIFICATION_CERT) $(PRIVATE_KEY): $(VERIFY_SIG_SETUP)
|
||||||
|
$(Q)mkdir -p $(BUILD_DIR)
|
||||||
|
$(Q)$(VERIFY_SIG_SETUP) genkey $(BUILD_DIR)
|
||||||
|
|
||||||
|
$(VERIFY_SIG_HDR): $(VERIFICATION_CERT)
|
||||||
|
$(Q)xxd -i -n test_progs_verification_cert $< > $@
|
||||||
|
|
||||||
# Define test_progs test runner.
|
# Define test_progs test runner.
|
||||||
TRUNNER_TESTS_DIR := prog_tests
|
TRUNNER_TESTS_DIR := prog_tests
|
||||||
TRUNNER_BPF_PROGS_DIR := progs
|
TRUNNER_BPF_PROGS_DIR := progs
|
||||||
@@ -716,6 +742,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \
|
|||||||
disasm.c \
|
disasm.c \
|
||||||
disasm_helpers.c \
|
disasm_helpers.c \
|
||||||
json_writer.c \
|
json_writer.c \
|
||||||
|
$(VERIFY_SIG_HDR) \
|
||||||
flow_dissector_load.h \
|
flow_dissector_load.h \
|
||||||
ip_check_defrag_frags.h
|
ip_check_defrag_frags.h
|
||||||
TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
|
TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
|
||||||
@@ -725,7 +752,7 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
|
|||||||
$(OUTPUT)/uprobe_multi \
|
$(OUTPUT)/uprobe_multi \
|
||||||
$(TEST_KMOD_TARGETS) \
|
$(TEST_KMOD_TARGETS) \
|
||||||
ima_setup.sh \
|
ima_setup.sh \
|
||||||
verify_sig_setup.sh \
|
$(VERIFY_SIG_SETUP) \
|
||||||
$(wildcard progs/btf_dump_test_case_*.c) \
|
$(wildcard progs/btf_dump_test_case_*.c) \
|
||||||
$(wildcard progs/*.bpf.o)
|
$(wildcard progs/*.bpf.o)
|
||||||
TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE
|
TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE
|
||||||
|
|||||||
@@ -165,11 +165,17 @@ static void test_xchg(struct atomics_lskel *skel)
|
|||||||
void test_atomics(void)
|
void test_atomics(void)
|
||||||
{
|
{
|
||||||
struct atomics_lskel *skel;
|
struct atomics_lskel *skel;
|
||||||
|
int err;
|
||||||
|
|
||||||
skel = atomics_lskel__open_and_load();
|
skel = atomics_lskel__open();
|
||||||
if (!ASSERT_OK_PTR(skel, "atomics skeleton load"))
|
if (!ASSERT_OK_PTR(skel, "atomics skeleton open"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
skel->keyring_id = KEY_SPEC_SESSION_KEYRING;
|
||||||
|
err = atomics_lskel__load(skel);
|
||||||
|
if (!ASSERT_OK(err, "atomics skeleton load"))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (skel->data->skip_tests) {
|
if (skel->data->skip_tests) {
|
||||||
printf("%s:SKIP:no ENABLE_ATOMICS_TESTS (missing Clang BPF atomics support)",
|
printf("%s:SKIP:no ENABLE_ATOMICS_TESTS (missing Clang BPF atomics support)",
|
||||||
__func__);
|
__func__);
|
||||||
|
|||||||
@@ -12,13 +12,24 @@ void test_fentry_fexit(void)
|
|||||||
int err, prog_fd, i;
|
int err, prog_fd, i;
|
||||||
LIBBPF_OPTS(bpf_test_run_opts, topts);
|
LIBBPF_OPTS(bpf_test_run_opts, topts);
|
||||||
|
|
||||||
fentry_skel = fentry_test_lskel__open_and_load();
|
fentry_skel = fentry_test_lskel__open();
|
||||||
if (!ASSERT_OK_PTR(fentry_skel, "fentry_skel_load"))
|
if (!ASSERT_OK_PTR(fentry_skel, "fentry_skel_load"))
|
||||||
goto close_prog;
|
goto close_prog;
|
||||||
fexit_skel = fexit_test_lskel__open_and_load();
|
|
||||||
|
fentry_skel->keyring_id = KEY_SPEC_SESSION_KEYRING;
|
||||||
|
err = fentry_test_lskel__load(fentry_skel);
|
||||||
|
if (!ASSERT_OK(err, "fentry_skel_load"))
|
||||||
|
goto close_prog;
|
||||||
|
|
||||||
|
fexit_skel = fexit_test_lskel__open();
|
||||||
if (!ASSERT_OK_PTR(fexit_skel, "fexit_skel_load"))
|
if (!ASSERT_OK_PTR(fexit_skel, "fexit_skel_load"))
|
||||||
goto close_prog;
|
goto close_prog;
|
||||||
|
|
||||||
|
fexit_skel->keyring_id = KEY_SPEC_SESSION_KEYRING;
|
||||||
|
err = fexit_test_lskel__load(fexit_skel);
|
||||||
|
if (!ASSERT_OK(err, "fexit_skel_load"))
|
||||||
|
goto close_prog;
|
||||||
|
|
||||||
err = fentry_test_lskel__attach(fentry_skel);
|
err = fentry_test_lskel__attach(fentry_skel);
|
||||||
if (!ASSERT_OK(err, "fentry_attach"))
|
if (!ASSERT_OK(err, "fentry_attach"))
|
||||||
goto close_prog;
|
goto close_prog;
|
||||||
|
|||||||
@@ -43,8 +43,13 @@ static void fentry_test(void)
|
|||||||
struct fentry_test_lskel *fentry_skel = NULL;
|
struct fentry_test_lskel *fentry_skel = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
fentry_skel = fentry_test_lskel__open_and_load();
|
fentry_skel = fentry_test_lskel__open();
|
||||||
if (!ASSERT_OK_PTR(fentry_skel, "fentry_skel_load"))
|
if (!ASSERT_OK_PTR(fentry_skel, "fentry_skel_open"))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
fentry_skel->keyring_id = KEY_SPEC_SESSION_KEYRING;
|
||||||
|
err = fentry_test_lskel__load(fentry_skel);
|
||||||
|
if (!ASSERT_OK(err, "fentry_skel_load"))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
err = fentry_test_common(fentry_skel);
|
err = fentry_test_common(fentry_skel);
|
||||||
|
|||||||
@@ -43,8 +43,13 @@ static void fexit_test(void)
|
|||||||
struct fexit_test_lskel *fexit_skel = NULL;
|
struct fexit_test_lskel *fexit_skel = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
fexit_skel = fexit_test_lskel__open_and_load();
|
fexit_skel = fexit_test_lskel__open();
|
||||||
if (!ASSERT_OK_PTR(fexit_skel, "fexit_skel_load"))
|
if (!ASSERT_OK_PTR(fexit_skel, "fexit_skel_open"))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
fexit_skel->keyring_id = KEY_SPEC_SESSION_KEYRING;
|
||||||
|
err = fexit_test_lskel__load(fexit_skel);
|
||||||
|
if (!ASSERT_OK(err, "fexit_skel_load"))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
err = fexit_test_common(fexit_skel);
|
err = fexit_test_common(fexit_skel);
|
||||||
|
|||||||
@@ -14,12 +14,14 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <linux/keyctl.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <bpf/btf.h>
|
#include <bpf/btf.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "json_writer.h"
|
#include "json_writer.h"
|
||||||
|
|
||||||
#include "network_helpers.h"
|
#include "network_helpers.h"
|
||||||
|
#include "verification_cert.h"
|
||||||
|
|
||||||
/* backtrace() and backtrace_symbols_fd() are glibc specific,
|
/* backtrace() and backtrace_symbols_fd() are glibc specific,
|
||||||
* use header file when glibc is available and provide stub
|
* use header file when glibc is available and provide stub
|
||||||
@@ -1928,6 +1930,13 @@ static void free_test_states(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __u32 register_session_key(const char *key_data, size_t key_data_size)
|
||||||
|
{
|
||||||
|
return syscall(__NR_add_key, "asymmetric", "libbpf_session_key",
|
||||||
|
(const void *)key_data, key_data_size,
|
||||||
|
KEY_SPEC_SESSION_KEYRING);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static const struct argp argp = {
|
static const struct argp argp = {
|
||||||
@@ -1961,6 +1970,10 @@ int main(int argc, char **argv)
|
|||||||
/* Use libbpf 1.0 API mode */
|
/* Use libbpf 1.0 API mode */
|
||||||
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
|
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
|
||||||
libbpf_set_print(libbpf_print_fn);
|
libbpf_set_print(libbpf_print_fn);
|
||||||
|
err = register_session_key((const char *)test_progs_verification_cert,
|
||||||
|
test_progs_verification_cert_len);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
traffic_monitor_set_print(traffic_monitor_print_fn);
|
traffic_monitor_set_print(traffic_monitor_print_fn);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ usage()
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
setup()
|
genkey()
|
||||||
{
|
{
|
||||||
local tmp_dir="$1"
|
local tmp_dir="$1"
|
||||||
|
|
||||||
@@ -45,9 +45,14 @@ setup()
|
|||||||
|
|
||||||
openssl x509 -in ${tmp_dir}/signing_key.pem -out \
|
openssl x509 -in ${tmp_dir}/signing_key.pem -out \
|
||||||
${tmp_dir}/signing_key.der -outform der
|
${tmp_dir}/signing_key.der -outform der
|
||||||
|
}
|
||||||
|
|
||||||
|
setup()
|
||||||
|
{
|
||||||
|
local tmp_dir="$1"
|
||||||
|
|
||||||
|
genkey "${tmp_dir}"
|
||||||
key_id=$(cat ${tmp_dir}/signing_key.der | keyctl padd asymmetric ebpf_testing_key @s)
|
key_id=$(cat ${tmp_dir}/signing_key.der | keyctl padd asymmetric ebpf_testing_key @s)
|
||||||
|
|
||||||
keyring_id=$(keyctl newring ebpf_testing_keyring @s)
|
keyring_id=$(keyctl newring ebpf_testing_keyring @s)
|
||||||
keyctl link $key_id $keyring_id
|
keyctl link $key_id $keyring_id
|
||||||
}
|
}
|
||||||
@@ -105,6 +110,8 @@ main()
|
|||||||
|
|
||||||
if [[ "${action}" == "setup" ]]; then
|
if [[ "${action}" == "setup" ]]; then
|
||||||
setup "${tmp_dir}"
|
setup "${tmp_dir}"
|
||||||
|
elif [[ "${action}" == "genkey" ]]; then
|
||||||
|
genkey "${tmp_dir}"
|
||||||
elif [[ "${action}" == "cleanup" ]]; then
|
elif [[ "${action}" == "cleanup" ]]; then
|
||||||
cleanup "${tmp_dir}"
|
cleanup "${tmp_dir}"
|
||||||
elif [[ "${action}" == "fsverity-create-sign" ]]; then
|
elif [[ "${action}" == "fsverity-create-sign" ]]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user