1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #define __SANE_USERSPACE_TYPES__ // Use ll64
4
5 #include <fcntl.h>
6 #include <sched.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/stat.h>
10 #include <sys/mount.h>
11 #include <unistd.h>
12
13 #include "../../kselftest_harness.h"
14 #include "log.h"
15 #include "wrappers.h"
16
FIXTURE(set_layers_via_fds)17 FIXTURE(set_layers_via_fds) {
18 };
19
FIXTURE_SETUP(set_layers_via_fds)20 FIXTURE_SETUP(set_layers_via_fds)
21 {
22 ASSERT_EQ(mkdir("/set_layers_via_fds", 0755), 0);
23 }
24
FIXTURE_TEARDOWN(set_layers_via_fds)25 FIXTURE_TEARDOWN(set_layers_via_fds)
26 {
27 umount2("/set_layers_via_fds", 0);
28 ASSERT_EQ(rmdir("/set_layers_via_fds"), 0);
29 }
30
TEST_F(set_layers_via_fds,set_layers_via_fds)31 TEST_F(set_layers_via_fds, set_layers_via_fds)
32 {
33 int fd_context, fd_tmpfs, fd_overlay;
34 int layer_fds[] = { [0 ... 8] = -EBADF };
35 bool layers_found[] = { [0 ... 8] = false };
36 size_t len = 0;
37 char *line = NULL;
38 FILE *f_mountinfo;
39
40 ASSERT_EQ(unshare(CLONE_NEWNS), 0);
41 ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
42
43 fd_context = sys_fsopen("tmpfs", 0);
44 ASSERT_GE(fd_context, 0);
45
46 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
47 fd_tmpfs = sys_fsmount(fd_context, 0, 0);
48 ASSERT_GE(fd_tmpfs, 0);
49 ASSERT_EQ(close(fd_context), 0);
50
51 ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
52 ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
53 ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
54 ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
55 ASSERT_EQ(mkdirat(fd_tmpfs, "l3", 0755), 0);
56 ASSERT_EQ(mkdirat(fd_tmpfs, "l4", 0755), 0);
57 ASSERT_EQ(mkdirat(fd_tmpfs, "d1", 0755), 0);
58 ASSERT_EQ(mkdirat(fd_tmpfs, "d2", 0755), 0);
59 ASSERT_EQ(mkdirat(fd_tmpfs, "d3", 0755), 0);
60
61 layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
62 ASSERT_GE(layer_fds[0], 0);
63
64 layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
65 ASSERT_GE(layer_fds[1], 0);
66
67 layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
68 ASSERT_GE(layer_fds[2], 0);
69
70 layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
71 ASSERT_GE(layer_fds[3], 0);
72
73 layer_fds[4] = openat(fd_tmpfs, "l3", O_DIRECTORY);
74 ASSERT_GE(layer_fds[4], 0);
75
76 layer_fds[5] = openat(fd_tmpfs, "l4", O_DIRECTORY);
77 ASSERT_GE(layer_fds[5], 0);
78
79 layer_fds[6] = openat(fd_tmpfs, "d1", O_DIRECTORY);
80 ASSERT_GE(layer_fds[6], 0);
81
82 layer_fds[7] = openat(fd_tmpfs, "d2", O_DIRECTORY);
83 ASSERT_GE(layer_fds[7], 0);
84
85 layer_fds[8] = openat(fd_tmpfs, "d3", O_DIRECTORY);
86 ASSERT_GE(layer_fds[8], 0);
87
88 ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
89 ASSERT_EQ(close(fd_tmpfs), 0);
90
91 fd_context = sys_fsopen("overlay", 0);
92 ASSERT_GE(fd_context, 0);
93
94 ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
95
96 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir", NULL, layer_fds[0]), 0);
97 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir", NULL, layer_fds[1]), 0);
98 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
99 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
100 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[4]), 0);
101 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[5]), 0);
102 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[6]), 0);
103 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[7]), 0);
104 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[8]), 0);
105
106 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_STRING, "metacopy", "on", 0), 0);
107
108 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
109
110 fd_overlay = sys_fsmount(fd_context, 0, 0);
111 ASSERT_GE(fd_overlay, 0);
112
113 ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
114
115 f_mountinfo = fopen("/proc/self/mountinfo", "r");
116 ASSERT_NE(f_mountinfo, NULL);
117
118 while (getline(&line, &len, f_mountinfo) != -1) {
119 char *haystack = line;
120
121 if (strstr(haystack, "workdir=/tmp/w"))
122 layers_found[0] = true;
123 if (strstr(haystack, "upperdir=/tmp/u"))
124 layers_found[1] = true;
125 if (strstr(haystack, "lowerdir+=/tmp/l1"))
126 layers_found[2] = true;
127 if (strstr(haystack, "lowerdir+=/tmp/l2"))
128 layers_found[3] = true;
129 if (strstr(haystack, "lowerdir+=/tmp/l3"))
130 layers_found[4] = true;
131 if (strstr(haystack, "lowerdir+=/tmp/l4"))
132 layers_found[5] = true;
133 if (strstr(haystack, "datadir+=/tmp/d1"))
134 layers_found[6] = true;
135 if (strstr(haystack, "datadir+=/tmp/d2"))
136 layers_found[7] = true;
137 if (strstr(haystack, "datadir+=/tmp/d3"))
138 layers_found[8] = true;
139 }
140 free(line);
141
142 for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
143 ASSERT_EQ(layers_found[i], true);
144 ASSERT_EQ(close(layer_fds[i]), 0);
145 }
146
147 ASSERT_EQ(close(fd_context), 0);
148 ASSERT_EQ(close(fd_overlay), 0);
149 ASSERT_EQ(fclose(f_mountinfo), 0);
150 }
151
TEST_F(set_layers_via_fds,set_500_layers_via_fds)152 TEST_F(set_layers_via_fds, set_500_layers_via_fds)
153 {
154 int fd_context, fd_tmpfs, fd_overlay, fd_work, fd_upper, fd_lower;
155 int layer_fds[500] = { [0 ... 499] = -EBADF };
156
157 ASSERT_EQ(unshare(CLONE_NEWNS), 0);
158 ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
159
160 fd_context = sys_fsopen("tmpfs", 0);
161 ASSERT_GE(fd_context, 0);
162
163 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
164 fd_tmpfs = sys_fsmount(fd_context, 0, 0);
165 ASSERT_GE(fd_tmpfs, 0);
166 ASSERT_EQ(close(fd_context), 0);
167
168 for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
169 char path[100];
170
171 sprintf(path, "l%d", i);
172 ASSERT_EQ(mkdirat(fd_tmpfs, path, 0755), 0);
173 layer_fds[i] = openat(fd_tmpfs, path, O_DIRECTORY);
174 ASSERT_GE(layer_fds[i], 0);
175 }
176
177 ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
178 fd_work = openat(fd_tmpfs, "w", O_DIRECTORY);
179 ASSERT_GE(fd_work, 0);
180
181 ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
182 fd_upper = openat(fd_tmpfs, "u", O_DIRECTORY);
183 ASSERT_GE(fd_upper, 0);
184
185 ASSERT_EQ(mkdirat(fd_tmpfs, "l501", 0755), 0);
186 fd_lower = openat(fd_tmpfs, "l501", O_DIRECTORY);
187 ASSERT_GE(fd_lower, 0);
188
189 ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
190 ASSERT_EQ(close(fd_tmpfs), 0);
191
192 fd_context = sys_fsopen("overlay", 0);
193 ASSERT_GE(fd_context, 0);
194
195 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir", NULL, fd_work), 0);
196 ASSERT_EQ(close(fd_work), 0);
197
198 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir", NULL, fd_upper), 0);
199 ASSERT_EQ(close(fd_upper), 0);
200
201 for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
202 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[i]), 0);
203 ASSERT_EQ(close(layer_fds[i]), 0);
204 }
205
206 ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower), 0);
207 ASSERT_EQ(close(fd_lower), 0);
208
209 ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
210
211 fd_overlay = sys_fsmount(fd_context, 0, 0);
212 ASSERT_GE(fd_overlay, 0);
213 ASSERT_EQ(close(fd_context), 0);
214 ASSERT_EQ(close(fd_overlay), 0);
215 }
216
217 TEST_HARNESS_MAIN
218