BPF List
 help / color / mirror / Atom feed
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


      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