1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 #define _GNU_SOURCE
4 #include <sched.h>
5 #include <sys/mount.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <test_progs.h>
9 
10 #define TDIR "/sys/kernel/debug"
11 
12 static int read_iter(char *file)
13 {
14 	/* 1024 should be enough to get contiguous 4 "iter" letters at some point */
15 	char buf[1024];
16 	int fd, len;
17 
18 	fd = open(file, 0);
19 	if (fd < 0)
20 		return -1;
21 	while ((len = read(fd, buf, sizeof(buf))) > 0)
22 		if (strstr(buf, "iter")) {
23 			close(fd);
24 			return 0;
25 		}
26 	close(fd);
27 	return -1;
28 }
29 
30 static int fn(void)
31 {
32 	int err, duration = 0;
33 
34 	err = unshare(CLONE_NEWNS);
35 	if (CHECK(err, "unshare", "failed: %d\n", errno))
36 		goto out;
37 
38 	err = mount("", "/", "", MS_REC | MS_PRIVATE, NULL);
39 	if (CHECK(err, "mount /", "failed: %d\n", errno))
40 		goto out;
41 
42 	err = umount(TDIR);
43 	if (CHECK(err, "umount " TDIR, "failed: %d\n", errno))
44 		goto out;
45 
46 	err = mount("none", TDIR, "tmpfs", 0, NULL);
47 	if (CHECK(err, "mount", "mount root failed: %d\n", errno))
48 		goto out;
49 
50 	err = mkdir(TDIR "/fs1", 0777);
51 	if (CHECK(err, "mkdir "TDIR"/fs1", "failed: %d\n", errno))
52 		goto out;
53 	err = mkdir(TDIR "/fs2", 0777);
54 	if (CHECK(err, "mkdir "TDIR"/fs2", "failed: %d\n", errno))
55 		goto out;
56 
57 	err = mount("bpf", TDIR "/fs1", "bpf", 0, NULL);
58 	if (CHECK(err, "mount bpffs "TDIR"/fs1", "failed: %d\n", errno))
59 		goto out;
60 	err = mount("bpf", TDIR "/fs2", "bpf", 0, NULL);
61 	if (CHECK(err, "mount bpffs " TDIR "/fs2", "failed: %d\n", errno))
62 		goto out;
63 
64 	err = read_iter(TDIR "/fs1/maps.debug");
65 	if (CHECK(err, "reading " TDIR "/fs1/maps.debug", "failed\n"))
66 		goto out;
67 	err = read_iter(TDIR "/fs2/progs.debug");
68 	if (CHECK(err, "reading " TDIR "/fs2/progs.debug", "failed\n"))
69 		goto out;
70 out:
71 	umount(TDIR "/fs1");
72 	umount(TDIR "/fs2");
73 	rmdir(TDIR "/fs1");
74 	rmdir(TDIR "/fs2");
75 	umount(TDIR);
76 	exit(err);
77 }
78 
79 void test_test_bpffs(void)
80 {
81 	int err, duration = 0, status = 0;
82 	pid_t pid;
83 
84 	pid = fork();
85 	if (CHECK(pid == -1, "clone", "clone failed %d", errno))
86 		return;
87 	if (pid == 0)
88 		fn();
89 	err = waitpid(pid, &status, 0);
90 	if (CHECK(err == -1 && errno != ECHILD, "waitpid", "failed %d", errno))
91 		return;
92 	if (CHECK(WEXITSTATUS(status), "bpffs test ", "failed %d", WEXITSTATUS(status)))
93 		return;
94 }
95