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
FIXTURE(set_layers_via_fds)21 FIXTURE(set_layers_via_fds) {
22 int pidfd;
23 };
24
FIXTURE_SETUP(set_layers_via_fds)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
FIXTURE_TEARDOWN(set_layers_via_fds)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
TEST_F(set_layers_via_fds,set_layers_via_fds)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
TEST_F(set_layers_via_fds,set_500_layers_via_fds)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
TEST_F(set_layers_via_fds,set_override_creds)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
TEST_F(set_layers_via_fds,set_override_creds_invalid)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
TEST_F(set_layers_via_fds,set_override_creds_nomknod)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
TEST_F(set_layers_via_fds,set_500_layers_via_opath_fds)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
TEST_F(set_layers_via_fds,set_layers_via_detached_mount_fds)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