From: John Fastabend <john.fastabend@gmail.com>
To: bpf@vger.kernel.org
Cc: john.fastabend@gmail.com, daniel@iogearbox.net
Subject: [PATCH bpf-next 2/2] libbpf: selftest for bpf_map__reuse_fd_from_loader_ctx()
Date: Fri, 26 Jun 2026 14:51:13 -0700 [thread overview]
Message-ID: <20260626215113.52273-2-john.fastabend@gmail.com> (raw)
In-Reply-To: <20260626215113.52273-1-john.fastabend@gmail.com>
Extend signed loader test case to exercise __reuse_fd_from_loader_ctx().
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
.../selftests/bpf/prog_tests/signed_loader.c | 115 ++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/signed_loader.c b/tools/testing/selftests/bpf/prog_tests/signed_loader.c
index 5fc417e31fc6..0af33362ab1b 100644
--- a/tools/testing/selftests/bpf/prog_tests/signed_loader.c
+++ b/tools/testing/selftests/bpf/prog_tests/signed_loader.c
@@ -8,8 +8,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
+#include <unistd.h>
#include <linux/keyctl.h>
#include <linux/bpf.h>
+#include <linux/if_ether.h>
#include "bpf/libbpf_internal.h" /* for libbpf_sha256() */
#include "bpf/skel_internal.h" /* for loader ctx layout (bpf_loader_ctx etc) */
@@ -699,6 +701,117 @@ static void metadata_ctx_initial_value_ignored(void)
test_signed_loader_data__destroy(skel);
}
+static void loader_ctx_reuse_fd_shared_map(void)
+{
+ LIBBPF_OPTS(gen_loader_opts, gopts, .gen_hash = true);
+ struct test_signed_loader_map *skel = NULL;
+ struct bpf_map_info shared_info, reused_info;
+ __u32 shared_info_len, reused_info_len;
+ __u8 excl[SHA256_DIGEST_LENGTH];
+ __u8 pkt[ETH_HLEN] = {};
+ __u32 key = 0, expected_retval = 42;
+ __u64 shared_value = expected_retval;
+ LIBBPF_OPTS(bpf_test_run_opts, topts,
+ .data_in = pkt,
+ .data_size_in = sizeof(pkt),
+ .repeat = 1,
+ );
+ int nr_maps = 0, nr_progs = 0, ctx_fd = -1, shared_fd = -1;
+ int supplied_fd, r;
+ struct bpf_prog_desc *pd;
+ struct bpf_map_desc *md;
+ struct bpf_program *p;
+ struct bpf_map *m;
+ unsigned char *blob = NULL;
+ __u32 ctx_sz, data_sz;
+ void *ctx = NULL;
+ bool ran;
+
+ skel = test_signed_loader_map__open();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ goto cleanup;
+ if (!ASSERT_OK(bpf_map__reuse_fd_from_loader_ctx(skel->maps.amap),
+ "reuse_fd_from_loader_ctx"))
+ goto cleanup;
+ if (!ASSERT_OK(bpf_object__gen_loader(skel->obj, &gopts), "gen_loader"))
+ goto cleanup;
+ if (!ASSERT_OK(bpf_object__load(skel->obj), "gen_load"))
+ goto cleanup;
+
+ bpf_object__for_each_program(p, skel->obj)
+ nr_progs++;
+ bpf_object__for_each_map(m, skel->obj)
+ nr_maps++;
+ if (!ASSERT_EQ(nr_maps, 1, "one map") ||
+ !ASSERT_EQ(nr_progs, 1, "one prog"))
+ goto cleanup;
+
+ shared_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "ctx_reuse",
+ sizeof(__u32), sizeof(__u64), 4, NULL);
+ if (!ASSERT_OK_FD(shared_fd, "shared_map"))
+ goto cleanup;
+ if (!ASSERT_OK(bpf_map_update_elem(shared_fd, &key, &shared_value, BPF_ANY),
+ "shared_map_update"))
+ goto cleanup;
+
+ ctx_sz = sizeof(struct bpf_loader_ctx) +
+ nr_maps * sizeof(struct bpf_map_desc) +
+ nr_progs * sizeof(struct bpf_prog_desc);
+ ctx = calloc(1, ctx_sz);
+ if (!ASSERT_OK_PTR(ctx, "ctx_alloc"))
+ goto cleanup;
+ ((struct bpf_loader_ctx *)ctx)->sz = ctx_sz;
+
+ md = (struct bpf_map_desc *)((char *)ctx + sizeof(struct bpf_loader_ctx));
+ pd = (struct bpf_prog_desc *)(md + nr_maps);
+ ctx_fd = dup(shared_fd);
+ if (!ASSERT_OK_FD(ctx_fd, "ctx_map_fd"))
+ goto cleanup;
+ md[0].map_fd = ctx_fd;
+ ctx_fd = -1;
+ supplied_fd = md[0].map_fd;
+
+ libbpf_sha256(gopts.insns, gopts.insns_sz, excl);
+ data_sz = gopts.data_sz;
+ blob = malloc(data_sz);
+ if (!ASSERT_OK_PTR(blob, "blob_alloc"))
+ goto cleanup;
+ memcpy(blob, gopts.data, data_sz);
+
+ r = run_gen_loader(gopts.insns, gopts.insns_sz, blob, data_sz,
+ excl, sizeof(excl), NULL, 0, true, ctx, ctx_sz, &ran);
+ if (!ASSERT_TRUE(ran, "loader ran") ||
+ !ASSERT_EQ(r, 0, "loader retval"))
+ goto cleanup;
+
+ ASSERT_EQ(md[0].map_fd, supplied_fd, "ctx map fd preserved");
+ ASSERT_GT(pd[0].prog_fd, 0, "prog fd populated");
+ if (ASSERT_OK(bpf_prog_test_run_opts(pd[0].prog_fd, &topts),
+ "shared map prog run"))
+ ASSERT_EQ(topts.retval, expected_retval, "shared map value");
+
+ memset(&shared_info, 0, sizeof(shared_info));
+ memset(&reused_info, 0, sizeof(reused_info));
+ shared_info_len = sizeof(shared_info);
+ reused_info_len = sizeof(reused_info);
+ if (ASSERT_OK(bpf_map_get_info_by_fd(shared_fd, &shared_info, &shared_info_len),
+ "shared map info") &&
+ ASSERT_OK(bpf_map_get_info_by_fd(md[0].map_fd, &reused_info, &reused_info_len),
+ "reused map info"))
+ ASSERT_EQ(reused_info.id, shared_info.id, "shared map reused");
+
+cleanup:
+ if (ctx)
+ close_loader_ctx_fds(ctx, nr_maps, nr_progs);
+ if (ctx_fd >= 0)
+ close(ctx_fd);
+ if (shared_fd >= 0)
+ close(shared_fd);
+ free(blob);
+ free(ctx);
+ test_signed_loader_map__destroy(skel);
+}
+
/*
* The load-time signature must authenticate the loader instructions: a valid
* signature loads, and the very same signature over one-byte-tampered insns is
@@ -1112,6 +1225,8 @@ void test_signed_loader(void)
metadata_ctx_max_entries_ignored();
if (test__start_subtest("metadata_ctx_initial_value_ignored"))
metadata_ctx_initial_value_ignored();
+ if (test__start_subtest("loader_ctx_reuse_fd_shared_map"))
+ loader_ctx_reuse_fd_shared_map();
if (test__start_subtest("signature_authenticates_insns"))
signature_authenticates_insns();
if (test__start_subtest("hash_requires_frozen"))
--
2.53.0
prev parent reply other threads:[~2026-06-26 21:51 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-26 21:51 [PATCH bpf-next 1/2] libbpf: add bpf_map__reuse_fd_from_loader_ctx() to allow shared maps John Fastabend
2026-06-26 21:51 ` John Fastabend [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260626215113.52273-2-john.fastabend@gmail.com \
--to=john.fastabend@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox