File Index
Files and directories
Sign in
FILE

set_layers_via_fds.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c C
  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
 21FIXTURE(set_layers_via_fds) {
 22	int pidfd;
 23};
 24
 25FIXTURE_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
 32FIXTURE_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
 45TEST_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
166TEST_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
231TEST_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
331TEST_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
450TEST_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
529TEST_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
594TEST_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
720TEST_HARNESS_MAIN
~/ Read-only file preview.