1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright (c) 2025 Isovalent */
3 
4 #include <test_progs.h>
5 #include <bpf/btf.h>
6 #include <sys/stat.h>
7 #include <sys/mman.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 
test_btf_mmap_sysfs(const char * path,struct btf * base)11 static void test_btf_mmap_sysfs(const char *path, struct btf *base)
12 {
13 	struct stat st;
14 	__u64 btf_size, end;
15 	void *raw_data = NULL;
16 	int fd = -1;
17 	long page_size;
18 	struct btf *btf = NULL;
19 
20 	page_size = sysconf(_SC_PAGESIZE);
21 	if (!ASSERT_GE(page_size, 0, "get_page_size"))
22 		goto cleanup;
23 
24 	if (!ASSERT_OK(stat(path, &st), "stat_btf"))
25 		goto cleanup;
26 
27 	btf_size = st.st_size;
28 	end = (btf_size + page_size - 1) / page_size * page_size;
29 
30 	fd = open(path, O_RDONLY);
31 	if (!ASSERT_GE(fd, 0, "open_btf"))
32 		goto cleanup;
33 
34 	raw_data = mmap(NULL, btf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
35 	if (!ASSERT_EQ(raw_data, MAP_FAILED, "mmap_btf_writable"))
36 		goto cleanup;
37 
38 	raw_data = mmap(NULL, btf_size, PROT_READ, MAP_SHARED, fd, 0);
39 	if (!ASSERT_EQ(raw_data, MAP_FAILED, "mmap_btf_shared"))
40 		goto cleanup;
41 
42 	raw_data = mmap(NULL, end + 1, PROT_READ, MAP_PRIVATE, fd, 0);
43 	if (!ASSERT_EQ(raw_data, MAP_FAILED, "mmap_btf_invalid_size"))
44 		goto cleanup;
45 
46 	raw_data = mmap(NULL, end, PROT_READ, MAP_PRIVATE, fd, 0);
47 	if (!ASSERT_OK_PTR(raw_data, "mmap_btf"))
48 		goto cleanup;
49 
50 	if (!ASSERT_EQ(mprotect(raw_data, btf_size, PROT_READ | PROT_WRITE), -1,
51 	    "mprotect_writable"))
52 		goto cleanup;
53 
54 	if (!ASSERT_EQ(mprotect(raw_data, btf_size, PROT_READ | PROT_EXEC), -1,
55 	    "mprotect_executable"))
56 		goto cleanup;
57 
58 	/* Check padding is zeroed */
59 	for (int i = btf_size; i < end; i++) {
60 		if (((__u8 *)raw_data)[i] != 0) {
61 			PRINT_FAIL("tail of BTF is not zero at page offset %d\n", i);
62 			goto cleanup;
63 		}
64 	}
65 
66 	btf = btf__new_split(raw_data, btf_size, base);
67 	if (!ASSERT_OK_PTR(btf, "parse_btf"))
68 		goto cleanup;
69 
70 cleanup:
71 	btf__free(btf);
72 	if (raw_data && raw_data != MAP_FAILED)
73 		munmap(raw_data, btf_size);
74 	if (fd >= 0)
75 		close(fd);
76 }
77 
test_btf_sysfs(void)78 void test_btf_sysfs(void)
79 {
80 	test_btf_mmap_sysfs("/sys/kernel/btf/vmlinux", NULL);
81 }
82