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