xref: /linux/tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c (revision 2487b6b9bf2874cfca7efb59c95650c5b1d88d43)
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/socket.h>
10 #include <sys/stat.h>
11 #include <sys/sysmacros.h>
12 #include <sys/mount.h>
13 #include <unistd.h>
14 
15 #include "../../kselftest_harness.h"
16 #include "../../pidfd/pidfd.h"
17 #include "log.h"
18 #include "../utils.h"
19 #include "wrappers.h"
20 
21 FIXTURE(set_layers_via_fds) {
22 	int pidfd;
23 };
24 
25 FIXTURE_SETUP(set_layers_via_fds)
26 {
27 	self->pidfd = -EBADF;
28 	EXPECT_EQ(mkdir("/set_layers_via_fds", 0755), 0);
29 	EXPECT_EQ(mkdir("/set_layers_via_fds_tmpfs", 0755), 0);
30 }
31 
32 FIXTURE_TEARDOWN(set_layers_via_fds)
33 {
34 	if (self->pidfd >= 0) {
35 		EXPECT_EQ(sys_pidfd_send_signal(self->pidfd, SIGKILL, NULL, 0), 0);
36 		EXPECT_EQ(close(self->pidfd), 0);
37 	}
38 	umount2("/set_layers_via_fds", 0);
39 	EXPECT_EQ(rmdir("/set_layers_via_fds"), 0);
40 
41 	umount2("/set_layers_via_fds_tmpfs", 0);
42 	EXPECT_EQ(rmdir("/set_layers_via_fds_tmpfs"), 0);
43 }
44 
45 TEST_F(set_layers_via_fds, set_layers_via_fds)
46 {
47 	int fd_context, fd_tmpfs, fd_overlay;
48 	int layer_fds[] = { [0 ... 8] = -EBADF };
49 	bool layers_found[] = { [0 ... 8] =  false };
50 	size_t len = 0;
51 	char *line = NULL;
52 	FILE *f_mountinfo;
53 
54 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
55 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
56 
57 	fd_context = sys_fsopen("tmpfs", 0);
58 	ASSERT_GE(fd_context, 0);
59 
60 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
61 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
62 	ASSERT_GE(fd_tmpfs, 0);
63 	ASSERT_EQ(close(fd_context), 0);
64 
65 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
66 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
67 	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
68 	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
69 	ASSERT_EQ(mkdirat(fd_tmpfs, "l3", 0755), 0);
70 	ASSERT_EQ(mkdirat(fd_tmpfs, "l4", 0755), 0);
71 	ASSERT_EQ(mkdirat(fd_tmpfs, "d1", 0755), 0);
72 	ASSERT_EQ(mkdirat(fd_tmpfs, "d2", 0755), 0);
73 	ASSERT_EQ(mkdirat(fd_tmpfs, "d3", 0755), 0);
74 
75 	layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
76 	ASSERT_GE(layer_fds[0], 0);
77 
78 	layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
79 	ASSERT_GE(layer_fds[1], 0);
80 
81 	layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
82 	ASSERT_GE(layer_fds[2], 0);
83 
84 	layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
85 	ASSERT_GE(layer_fds[3], 0);
86 
87 	layer_fds[4] = openat(fd_tmpfs, "l3", O_DIRECTORY);
88 	ASSERT_GE(layer_fds[4], 0);
89 
90 	layer_fds[5] = openat(fd_tmpfs, "l4", O_DIRECTORY);
91 	ASSERT_GE(layer_fds[5], 0);
92 
93 	layer_fds[6] = openat(fd_tmpfs, "d1", O_DIRECTORY);
94 	ASSERT_GE(layer_fds[6], 0);
95 
96 	layer_fds[7] = openat(fd_tmpfs, "d2", O_DIRECTORY);
97 	ASSERT_GE(layer_fds[7], 0);
98 
99 	layer_fds[8] = openat(fd_tmpfs, "d3", O_DIRECTORY);
100 	ASSERT_GE(layer_fds[8], 0);
101 
102 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
103 	ASSERT_EQ(close(fd_tmpfs), 0);
104 
105 	fd_context = sys_fsopen("overlay", 0);
106 	ASSERT_GE(fd_context, 0);
107 
108 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
109 
110 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, layer_fds[0]), 0);
111 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, layer_fds[1]), 0);
112 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
113 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
114 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[4]), 0);
115 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[5]), 0);
116 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[6]), 0);
117 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[7]), 0);
118 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[8]), 0);
119 
120 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_STRING, "metacopy", "on", 0), 0);
121 
122 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
123 
124 	fd_overlay = sys_fsmount(fd_context, 0, 0);
125 	ASSERT_GE(fd_overlay, 0);
126 
127 	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
128 
129 	f_mountinfo = fopen("/proc/self/mountinfo", "r");
130 	ASSERT_NE(f_mountinfo, NULL);
131 
132 	while (getline(&line, &len, f_mountinfo) != -1) {
133 		char *haystack = line;
134 
135 		if (strstr(haystack, "workdir=/tmp/w"))
136 			layers_found[0] = true;
137 		if (strstr(haystack, "upperdir=/tmp/u"))
138 			layers_found[1] = true;
139 		if (strstr(haystack, "lowerdir+=/tmp/l1"))
140 			layers_found[2] = true;
141 		if (strstr(haystack, "lowerdir+=/tmp/l2"))
142 			layers_found[3] = true;
143 		if (strstr(haystack, "lowerdir+=/tmp/l3"))
144 			layers_found[4] = true;
145 		if (strstr(haystack, "lowerdir+=/tmp/l4"))
146 			layers_found[5] = true;
147 		if (strstr(haystack, "datadir+=/tmp/d1"))
148 			layers_found[6] = true;
149 		if (strstr(haystack, "datadir+=/tmp/d2"))
150 			layers_found[7] = true;
151 		if (strstr(haystack, "datadir+=/tmp/d3"))
152 			layers_found[8] = true;
153 	}
154 	free(line);
155 
156 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
157 		ASSERT_EQ(layers_found[i], true);
158 		ASSERT_EQ(close(layer_fds[i]), 0);
159 	}
160 
161 	ASSERT_EQ(close(fd_context), 0);
162 	ASSERT_EQ(close(fd_overlay), 0);
163 	ASSERT_EQ(fclose(f_mountinfo), 0);
164 }
165 
166 TEST_F(set_layers_via_fds, set_500_layers_via_fds)
167 {
168 	int fd_context, fd_tmpfs, fd_overlay, fd_work, fd_upper, fd_lower;
169 	int layer_fds[500] = { [0 ... 499] = -EBADF };
170 
171 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
172 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
173 
174 	fd_context = sys_fsopen("tmpfs", 0);
175 	ASSERT_GE(fd_context, 0);
176 
177 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
178 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
179 	ASSERT_GE(fd_tmpfs, 0);
180 	ASSERT_EQ(close(fd_context), 0);
181 
182 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
183 		char path[100];
184 
185 		sprintf(path, "l%d", i);
186 		ASSERT_EQ(mkdirat(fd_tmpfs, path, 0755), 0);
187 		layer_fds[i] = openat(fd_tmpfs, path, O_DIRECTORY);
188 		ASSERT_GE(layer_fds[i], 0);
189 	}
190 
191 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
192 	fd_work = openat(fd_tmpfs, "w", O_DIRECTORY);
193 	ASSERT_GE(fd_work, 0);
194 
195 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
196 	fd_upper = openat(fd_tmpfs, "u", O_DIRECTORY);
197 	ASSERT_GE(fd_upper, 0);
198 
199 	ASSERT_EQ(mkdirat(fd_tmpfs, "l501", 0755), 0);
200 	fd_lower = openat(fd_tmpfs, "l501", O_DIRECTORY);
201 	ASSERT_GE(fd_lower, 0);
202 
203 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
204 	ASSERT_EQ(close(fd_tmpfs), 0);
205 
206 	fd_context = sys_fsopen("overlay", 0);
207 	ASSERT_GE(fd_context, 0);
208 
209 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, fd_work), 0);
210 	ASSERT_EQ(close(fd_work), 0);
211 
212 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, fd_upper), 0);
213 	ASSERT_EQ(close(fd_upper), 0);
214 
215 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
216 		ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[i]), 0);
217 		ASSERT_EQ(close(layer_fds[i]), 0);
218 	}
219 
220 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower), 0);
221 	ASSERT_EQ(close(fd_lower), 0);
222 
223 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
224 
225 	fd_overlay = sys_fsmount(fd_context, 0, 0);
226 	ASSERT_GE(fd_overlay, 0);
227 	ASSERT_EQ(close(fd_context), 0);
228 	ASSERT_EQ(close(fd_overlay), 0);
229 }
230 
231 TEST_F(set_layers_via_fds, set_override_creds)
232 {
233 	int fd_context, fd_tmpfs, fd_overlay;
234 	int layer_fds[] = { [0 ... 3] = -EBADF };
235 	pid_t pid;
236 	int pidfd;
237 
238 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
239 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
240 
241 	fd_context = sys_fsopen("tmpfs", 0);
242 	ASSERT_GE(fd_context, 0);
243 
244 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
245 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
246 	ASSERT_GE(fd_tmpfs, 0);
247 	ASSERT_EQ(close(fd_context), 0);
248 
249 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
250 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
251 	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
252 	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
253 
254 	layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
255 	ASSERT_GE(layer_fds[0], 0);
256 
257 	layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
258 	ASSERT_GE(layer_fds[1], 0);
259 
260 	layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
261 	ASSERT_GE(layer_fds[2], 0);
262 
263 	layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
264 	ASSERT_GE(layer_fds[3], 0);
265 
266 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
267 	ASSERT_EQ(close(fd_tmpfs), 0);
268 
269 	fd_context = sys_fsopen("overlay", 0);
270 	ASSERT_GE(fd_context, 0);
271 
272 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
273 
274 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, layer_fds[0]), 0);
275 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, layer_fds[1]), 0);
276 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
277 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
278 
279 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_STRING, "metacopy", "on", 0), 0);
280 
281 	pid = create_child(&pidfd, 0);
282 	ASSERT_GE(pid, 0);
283 	if (pid == 0) {
284 		if (sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "override_creds", NULL, 0)) {
285 			TH_LOG("sys_fsconfig should have succeeded");
286 			_exit(EXIT_FAILURE);
287 		}
288 
289 		_exit(EXIT_SUCCESS);
290 	}
291 	ASSERT_GE(sys_waitid(P_PID, pid, NULL, WEXITED), 0);
292 	ASSERT_GE(close(pidfd), 0);
293 
294 	pid = create_child(&pidfd, 0);
295 	ASSERT_GE(pid, 0);
296 	if (pid == 0) {
297 		if (sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "nooverride_creds", NULL, 0)) {
298 			TH_LOG("sys_fsconfig should have succeeded");
299 			_exit(EXIT_FAILURE);
300 		}
301 
302 		_exit(EXIT_SUCCESS);
303 	}
304 	ASSERT_GE(sys_waitid(P_PID, pid, NULL, WEXITED), 0);
305 	ASSERT_GE(close(pidfd), 0);
306 
307 	pid = create_child(&pidfd, 0);
308 	ASSERT_GE(pid, 0);
309 	if (pid == 0) {
310 		if (sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "override_creds", NULL, 0)) {
311 			TH_LOG("sys_fsconfig should have succeeded");
312 			_exit(EXIT_FAILURE);
313 		}
314 
315 		_exit(EXIT_SUCCESS);
316 	}
317 	ASSERT_GE(sys_waitid(P_PID, pid, NULL, WEXITED), 0);
318 	ASSERT_GE(close(pidfd), 0);
319 
320 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
321 
322 	fd_overlay = sys_fsmount(fd_context, 0, 0);
323 	ASSERT_GE(fd_overlay, 0);
324 
325 	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
326 
327 	ASSERT_EQ(close(fd_context), 0);
328 	ASSERT_EQ(close(fd_overlay), 0);
329 }
330 
331 TEST_F(set_layers_via_fds, set_override_creds_invalid)
332 {
333 	int fd_context, fd_tmpfs, fd_overlay, ret;
334 	int layer_fds[] = { [0 ... 3] = -EBADF };
335 	pid_t pid;
336 	int fd_userns1, fd_userns2;
337 	int ipc_sockets[2];
338 	char c;
339 	const unsigned int predictable_fd_context_nr = 123;
340 
341 	fd_userns1 = get_userns_fd(0, 0, 10000);
342 	ASSERT_GE(fd_userns1, 0);
343 
344 	fd_userns2 = get_userns_fd(0, 1234, 10000);
345 	ASSERT_GE(fd_userns2, 0);
346 
347 	ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
348 	ASSERT_GE(ret, 0);
349 
350 	pid = create_child(&self->pidfd, 0);
351 	ASSERT_GE(pid, 0);
352 	if (pid == 0) {
353 		if (close(ipc_sockets[0])) {
354 			TH_LOG("close should have succeeded");
355 			_exit(EXIT_FAILURE);
356 		}
357 
358 		if (!switch_userns(fd_userns2, 0, 0, false)) {
359 			TH_LOG("switch_userns should have succeeded");
360 			_exit(EXIT_FAILURE);
361 		}
362 
363 		if (read_nointr(ipc_sockets[1], &c, 1) != 1) {
364 			TH_LOG("read_nointr should have succeeded");
365 			_exit(EXIT_FAILURE);
366 		}
367 
368 		if (close(ipc_sockets[1])) {
369 			TH_LOG("close should have succeeded");
370 			_exit(EXIT_FAILURE);
371 		}
372 
373 		if (!sys_fsconfig(predictable_fd_context_nr, FSCONFIG_SET_FLAG, "override_creds", NULL, 0)) {
374 			TH_LOG("sys_fsconfig should have failed");
375 			_exit(EXIT_FAILURE);
376 		}
377 
378 		_exit(EXIT_SUCCESS);
379 	}
380 
381 	ASSERT_EQ(close(ipc_sockets[1]), 0);
382 	ASSERT_EQ(switch_userns(fd_userns1, 0, 0, false), true);
383 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
384 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
385 
386 	fd_context = sys_fsopen("tmpfs", 0);
387 	ASSERT_GE(fd_context, 0);
388 
389 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
390 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
391 	ASSERT_GE(fd_tmpfs, 0);
392 	ASSERT_EQ(close(fd_context), 0);
393 
394 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
395 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
396 	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
397 	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
398 
399 	layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
400 	ASSERT_GE(layer_fds[0], 0);
401 
402 	layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
403 	ASSERT_GE(layer_fds[1], 0);
404 
405 	layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
406 	ASSERT_GE(layer_fds[2], 0);
407 
408 	layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
409 	ASSERT_GE(layer_fds[3], 0);
410 
411 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
412 	ASSERT_EQ(close(fd_tmpfs), 0);
413 
414 	fd_context = sys_fsopen("overlay", 0);
415 	ASSERT_GE(fd_context, 0);
416 	ASSERT_EQ(dup3(fd_context, predictable_fd_context_nr, 0), predictable_fd_context_nr);
417 	ASSERT_EQ(close(fd_context), 0);
418 	fd_context = predictable_fd_context_nr;
419 	ASSERT_EQ(write_nointr(ipc_sockets[0], "1", 1), 1);
420 	ASSERT_EQ(close(ipc_sockets[0]), 0);
421 
422 	ASSERT_EQ(wait_for_pid(pid), 0);
423 	ASSERT_EQ(close(self->pidfd), 0);
424 	self->pidfd = -EBADF;
425 
426 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
427 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, layer_fds[0]), 0);
428 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, layer_fds[1]), 0);
429 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
430 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
431 
432 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++)
433 		ASSERT_EQ(close(layer_fds[i]), 0);
434 
435 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "userxattr", NULL, 0), 0);
436 
437 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
438 
439 	fd_overlay = sys_fsmount(fd_context, 0, 0);
440 	ASSERT_GE(fd_overlay, 0);
441 
442 	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
443 
444 	ASSERT_EQ(close(fd_context), 0);
445 	ASSERT_EQ(close(fd_overlay), 0);
446 	ASSERT_EQ(close(fd_userns1), 0);
447 	ASSERT_EQ(close(fd_userns2), 0);
448 }
449 
450 TEST_F(set_layers_via_fds, set_override_creds_nomknod)
451 {
452 	int fd_context, fd_tmpfs, fd_overlay;
453 	int layer_fds[] = { [0 ... 3] = -EBADF };
454 	pid_t pid;
455 	int pidfd;
456 
457 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
458 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
459 
460 	fd_context = sys_fsopen("tmpfs", 0);
461 	ASSERT_GE(fd_context, 0);
462 
463 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
464 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
465 	ASSERT_GE(fd_tmpfs, 0);
466 	ASSERT_EQ(close(fd_context), 0);
467 
468 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
469 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
470 	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
471 	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
472 
473 	layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
474 	ASSERT_GE(layer_fds[0], 0);
475 
476 	layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
477 	ASSERT_GE(layer_fds[1], 0);
478 
479 	layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
480 	ASSERT_GE(layer_fds[2], 0);
481 
482 	layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
483 	ASSERT_GE(layer_fds[3], 0);
484 
485 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
486 	ASSERT_EQ(close(fd_tmpfs), 0);
487 
488 	fd_context = sys_fsopen("overlay", 0);
489 	ASSERT_GE(fd_context, 0);
490 
491 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
492 
493 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, layer_fds[0]), 0);
494 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, layer_fds[1]), 0);
495 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
496 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
497 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "userxattr", NULL, 0), 0);
498 
499 	pid = create_child(&pidfd, 0);
500 	ASSERT_GE(pid, 0);
501 	if (pid == 0) {
502 		if (!cap_down(CAP_MKNOD))
503 			_exit(EXIT_FAILURE);
504 
505 		if (!cap_down(CAP_SYS_ADMIN))
506 			_exit(EXIT_FAILURE);
507 
508 		if (sys_fsconfig(fd_context, FSCONFIG_SET_FLAG, "override_creds", NULL, 0))
509 			_exit(EXIT_FAILURE);
510 
511 		_exit(EXIT_SUCCESS);
512 	}
513 	ASSERT_EQ(sys_waitid(P_PID, pid, NULL, WEXITED), 0);
514 	ASSERT_GE(close(pidfd), 0);
515 
516 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
517 
518 	fd_overlay = sys_fsmount(fd_context, 0, 0);
519 	ASSERT_GE(fd_overlay, 0);
520 
521 	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
522 	ASSERT_EQ(mknodat(fd_overlay, "dev-zero", S_IFCHR | 0644, makedev(1, 5)), -1);
523 	ASSERT_EQ(errno, EPERM);
524 
525 	ASSERT_EQ(close(fd_context), 0);
526 	ASSERT_EQ(close(fd_overlay), 0);
527 }
528 
529 TEST_F(set_layers_via_fds, set_500_layers_via_opath_fds)
530 {
531 	int fd_context, fd_tmpfs, fd_overlay, fd_work, fd_upper, fd_lower;
532 	int layer_fds[500] = { [0 ... 499] = -EBADF };
533 
534 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
535 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
536 
537 	fd_context = sys_fsopen("tmpfs", 0);
538 	ASSERT_GE(fd_context, 0);
539 
540 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
541 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
542 	ASSERT_GE(fd_tmpfs, 0);
543 	ASSERT_EQ(close(fd_context), 0);
544 
545 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
546 		char path[100];
547 
548 		sprintf(path, "l%d", i);
549 		ASSERT_EQ(mkdirat(fd_tmpfs, path, 0755), 0);
550 		layer_fds[i] = openat(fd_tmpfs, path, O_DIRECTORY | O_PATH);
551 		ASSERT_GE(layer_fds[i], 0);
552 	}
553 
554 	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
555 	fd_work = openat(fd_tmpfs, "w", O_DIRECTORY | O_PATH);
556 	ASSERT_GE(fd_work, 0);
557 
558 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
559 	fd_upper = openat(fd_tmpfs, "u", O_DIRECTORY | O_PATH);
560 	ASSERT_GE(fd_upper, 0);
561 
562 	ASSERT_EQ(mkdirat(fd_tmpfs, "l501", 0755), 0);
563 	fd_lower = openat(fd_tmpfs, "l501", O_DIRECTORY | O_PATH);
564 	ASSERT_GE(fd_lower, 0);
565 
566 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
567 	ASSERT_EQ(close(fd_tmpfs), 0);
568 
569 	fd_context = sys_fsopen("overlay", 0);
570 	ASSERT_GE(fd_context, 0);
571 
572 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, fd_work), 0);
573 	ASSERT_EQ(close(fd_work), 0);
574 
575 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, fd_upper), 0);
576 	ASSERT_EQ(close(fd_upper), 0);
577 
578 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
579 		ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[i]), 0);
580 		ASSERT_EQ(close(layer_fds[i]), 0);
581 	}
582 
583 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower), 0);
584 	ASSERT_EQ(close(fd_lower), 0);
585 
586 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
587 
588 	fd_overlay = sys_fsmount(fd_context, 0, 0);
589 	ASSERT_GE(fd_overlay, 0);
590 	ASSERT_EQ(close(fd_context), 0);
591 	ASSERT_EQ(close(fd_overlay), 0);
592 }
593 
594 TEST_F(set_layers_via_fds, set_layers_via_detached_mount_fds)
595 {
596 	int fd_context, fd_tmpfs, fd_overlay, fd_tmp;
597 	int layer_fds[] = { [0 ... 8] = -EBADF };
598 	bool layers_found[] = { [0 ... 8] =  false };
599 	size_t len = 0;
600 	char *line = NULL;
601 	FILE *f_mountinfo;
602 
603 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
604 	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
605 
606 	fd_context = sys_fsopen("tmpfs", 0);
607 	ASSERT_GE(fd_context, 0);
608 
609 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
610 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
611 	ASSERT_GE(fd_tmpfs, 0);
612 	ASSERT_EQ(close(fd_context), 0);
613 
614 	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
615 	ASSERT_EQ(mkdirat(fd_tmpfs, "u/upper", 0755), 0);
616 	ASSERT_EQ(mkdirat(fd_tmpfs, "u/work", 0755), 0);
617 	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
618 	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
619 	ASSERT_EQ(mkdirat(fd_tmpfs, "l3", 0755), 0);
620 	ASSERT_EQ(mkdirat(fd_tmpfs, "l4", 0755), 0);
621 	ASSERT_EQ(mkdirat(fd_tmpfs, "d1", 0755), 0);
622 	ASSERT_EQ(mkdirat(fd_tmpfs, "d2", 0755), 0);
623 	ASSERT_EQ(mkdirat(fd_tmpfs, "d3", 0755), 0);
624 
625 	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/set_layers_via_fds_tmpfs", MOVE_MOUNT_F_EMPTY_PATH), 0);
626 
627 	fd_tmp = open_tree(fd_tmpfs, "u", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
628 	ASSERT_GE(fd_tmp, 0);
629 
630 	layer_fds[0] = openat(fd_tmp, "upper", O_CLOEXEC | O_DIRECTORY | O_PATH);
631 	ASSERT_GE(layer_fds[0], 0);
632 
633 	layer_fds[1] = openat(fd_tmp, "work", O_CLOEXEC | O_DIRECTORY | O_PATH);
634 	ASSERT_GE(layer_fds[1], 0);
635 
636 	layer_fds[2] = open_tree(fd_tmpfs, "l1", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
637 	ASSERT_GE(layer_fds[2], 0);
638 
639 	layer_fds[3] = open_tree(fd_tmpfs, "l2", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
640 	ASSERT_GE(layer_fds[3], 0);
641 
642 	layer_fds[4] = open_tree(fd_tmpfs, "l3", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
643 	ASSERT_GE(layer_fds[4], 0);
644 
645 	layer_fds[5] = open_tree(fd_tmpfs, "l4", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
646 	ASSERT_GE(layer_fds[5], 0);
647 
648 	layer_fds[6] = open_tree(fd_tmpfs, "d1", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
649 	ASSERT_GE(layer_fds[6], 0);
650 
651 	layer_fds[7] = open_tree(fd_tmpfs, "d2", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
652 	ASSERT_GE(layer_fds[7], 0);
653 
654 	layer_fds[8] = open_tree(fd_tmpfs, "d3", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
655 	ASSERT_GE(layer_fds[8], 0);
656 
657 	ASSERT_EQ(close(fd_tmpfs), 0);
658 
659 	fd_context = sys_fsopen("overlay", 0);
660 	ASSERT_GE(fd_context, 0);
661 
662 	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
663 
664 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir",  NULL, layer_fds[0]), 0);
665 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir",   NULL, layer_fds[1]), 0);
666 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
667 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
668 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[4]), 0);
669 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[5]), 0);
670 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[6]), 0);
671 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[7]), 0);
672 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+",  NULL, layer_fds[8]), 0);
673 
674 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_STRING, "metacopy", "on", 0), 0);
675 
676 	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
677 
678 	fd_overlay = sys_fsmount(fd_context, 0, 0);
679 	ASSERT_GE(fd_overlay, 0);
680 
681 	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
682 
683 	f_mountinfo = fopen("/proc/self/mountinfo", "r");
684 	ASSERT_NE(f_mountinfo, NULL);
685 
686 	while (getline(&line, &len, f_mountinfo) != -1) {
687 		char *haystack = line;
688 
689 		if (strstr(haystack, "workdir=/tmp/w"))
690 			layers_found[0] = true;
691 		if (strstr(haystack, "upperdir=/tmp/u"))
692 			layers_found[1] = true;
693 		if (strstr(haystack, "lowerdir+=/tmp/l1"))
694 			layers_found[2] = true;
695 		if (strstr(haystack, "lowerdir+=/tmp/l2"))
696 			layers_found[3] = true;
697 		if (strstr(haystack, "lowerdir+=/tmp/l3"))
698 			layers_found[4] = true;
699 		if (strstr(haystack, "lowerdir+=/tmp/l4"))
700 			layers_found[5] = true;
701 		if (strstr(haystack, "datadir+=/tmp/d1"))
702 			layers_found[6] = true;
703 		if (strstr(haystack, "datadir+=/tmp/d2"))
704 			layers_found[7] = true;
705 		if (strstr(haystack, "datadir+=/tmp/d3"))
706 			layers_found[8] = true;
707 	}
708 	free(line);
709 
710 	for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
711 		ASSERT_EQ(layers_found[i], true);
712 		ASSERT_EQ(close(layer_fds[i]), 0);
713 	}
714 
715 	ASSERT_EQ(close(fd_context), 0);
716 	ASSERT_EQ(close(fd_overlay), 0);
717 	ASSERT_EQ(fclose(f_mountinfo), 0);
718 }
719 
720 TEST_HARNESS_MAIN
721