xref: /linux/tools/testing/selftests/bpf/prog_tests/map_excl.c (revision a0fa68d8ce759dbf6aaf19a043ddd77a2128c26c)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2025 Google LLC. */
3 #define _GNU_SOURCE
4 #include <unistd.h>
5 #include <sys/syscall.h>
6 #include <test_progs.h>
7 #include <bpf/btf.h>
8 
9 #include "map_excl.skel.h"
10 
11 #ifndef SHA256_DIGEST_SIZE
12 #define SHA256_DIGEST_SIZE	32
13 #endif
14 
15 static void test_map_excl_allowed(void)
16 {
17 	struct map_excl *skel = map_excl__open();
18 	int err;
19 
20 	err = bpf_map__set_exclusive_program(skel->maps.excl_map, skel->progs.should_have_access);
21 	if (!ASSERT_OK(err, "bpf_map__set_exclusive_program"))
22 		goto out;
23 
24 	bpf_program__set_autoload(skel->progs.should_have_access, true);
25 	bpf_program__set_autoload(skel->progs.should_not_have_access, false);
26 
27 	err = map_excl__load(skel);
28 	ASSERT_OK(err, "map_excl__load");
29 out:
30 	map_excl__destroy(skel);
31 }
32 
33 static void test_map_excl_denied(void)
34 {
35 	struct map_excl *skel = map_excl__open();
36 	int err;
37 
38 	err = bpf_map__set_exclusive_program(skel->maps.excl_map, skel->progs.should_have_access);
39 	if (!ASSERT_OK(err, "bpf_map__make_exclusive"))
40 		goto out;
41 
42 	bpf_program__set_autoload(skel->progs.should_have_access, false);
43 	bpf_program__set_autoload(skel->progs.should_not_have_access, true);
44 
45 	err = map_excl__load(skel);
46 	ASSERT_EQ(err, -EACCES, "exclusive map access not denied\n");
47 out:
48 	map_excl__destroy(skel);
49 
50 }
51 
52 static void test_map_excl_no_map_in_map(void)
53 {
54 	__u8 hash[SHA256_DIGEST_SIZE] = {};
55 	LIBBPF_OPTS(bpf_map_create_opts, excl_opts,
56 		    .excl_prog_hash = hash,
57 		    .excl_prog_hash_size = sizeof(hash));
58 	LIBBPF_OPTS(bpf_map_create_opts, outer_opts);
59 	int excl_fd, tmpl_fd = -1, outer_fd = -1, err;
60 	__u32 key = 0;
61 
62 	excl_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "excl_inner", 4, 4, 1, &excl_opts);
63 	if (!ASSERT_OK_FD(excl_fd, "create exclusive map"))
64 		return;
65 
66 	outer_opts.inner_map_fd = excl_fd;
67 	err = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, "outer_from_excl",
68 			     4, 4, 1, &outer_opts);
69 	if (err >= 0)
70 		close(err);
71 	ASSERT_EQ(err, -ENOTSUPP, "reject exclusive map as map-in-map template");
72 
73 	tmpl_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "tmpl", 4, 4, 1, NULL);
74 	if (!ASSERT_OK_FD(tmpl_fd, "create inner template"))
75 		goto out;
76 
77 	outer_opts.inner_map_fd = tmpl_fd;
78 	outer_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, "outer", 4, 4, 1, &outer_opts);
79 	if (!ASSERT_OK_FD(outer_fd, "create map-of-maps"))
80 		goto out;
81 
82 	err = bpf_map_update_elem(outer_fd, &key, &excl_fd, 0);
83 	ASSERT_EQ(err, -ENOTSUPP, "reject exclusive map as map-in-map element");
84 out:
85 	if (outer_fd >= 0)
86 		close(outer_fd);
87 	if (tmpl_fd >= 0)
88 		close(tmpl_fd);
89 	close(excl_fd);
90 }
91 
92 void test_map_excl(void)
93 {
94 	if (test__start_subtest("map_excl_allowed"))
95 		test_map_excl_allowed();
96 	if (test__start_subtest("map_excl_denied"))
97 		test_map_excl_denied();
98 	if (test__start_subtest("map_excl_no_map_in_map"))
99 		test_map_excl_no_map_in_map();
100 }
101