1 // SPDX-License-Identifier: GPL-2.0
14 #include <linux/limits.h>
15 #include <linux/types.h>
20 #include <sys/fsuid.h>
22 #include <sys/types.h>
23 #include <sys/sysmacros.h>
24 #include <sys/xattr.h>
27 #ifdef HAVE_SYS_CAPABILITY_H
28 #include <sys/capability.h>
31 #ifdef HAVE_LIBURING_H
38 #define T_DIR1 "idmapped_mounts_1"
40 #define FILE1_RENAME "file1_rename"
42 #define FILE2_RENAME "file2_rename"
46 #define DIR1_RENAME "dir1_rename"
47 #define HARDLINK1 "hardlink1"
48 #define SYMLINK1 "symlink1"
49 #define SYMLINK_USER1 "symlink_user1"
50 #define SYMLINK_USER2 "symlink_user2"
51 #define SYMLINK_USER3 "symlink_user3"
52 #define CHRDEV1 "chrdev1"
54 #define log_stderr(format, ...) \
55 fprintf(stderr, "%s: %d: %s - %m - " format "\n", __FILE__, __LINE__, __func__, \
59 #define log_debug(format, ...) \
60 fprintf(stderr, "%s: %d: %s - " format "\n", __FILE__, __LINE__, \
61 __func__, ##__VA_ARGS__)
63 #define log_debug(format, ...)
66 #define log_error_errno(__ret__, __errno__, format, ...) \
68 typeof(__ret__) __internal_ret__ = (__ret__); \
69 errno = (__errno__); \
70 log_stderr(format, ##__VA_ARGS__); \
74 #define log_errno(__ret__, format, ...) log_error_errno(__ret__, errno, format, ##__VA_ARGS__)
76 #define die_errno(__errno__, format, ...) \
78 errno = (__errno__); \
79 log_stderr(format, ##__VA_ARGS__); \
83 #define die(format, ...) die_errno(errno, format, ##__VA_ARGS__)
85 uid_t t_overflowuid = 65534;
86 gid_t t_overflowgid = 65534;
88 /* path of the test device */
91 /* path of the test device */
94 /* mountpoint of the test device */
95 const char *t_mountpoint;
97 /* fd for @t_mountpoint */
103 /* temporary buffer */
104 char t_buf[PATH_MAX];
106 static void stash_overflowuid(void)
112 fd = open("/proc/sys/fs/overflowuid", O_RDONLY | O_CLOEXEC);
116 ret = read(fd, buf, sizeof(buf));
121 t_overflowuid = atoi(buf);
124 static void stash_overflowgid(void)
130 fd = open("/proc/sys/fs/overflowgid", O_RDONLY | O_CLOEXEC);
134 ret = read(fd, buf, sizeof(buf));
139 t_overflowgid = atoi(buf);
142 static bool is_xfs(void)
144 static int enabled = -1;
147 enabled = !strcmp(t_fstype, "xfs");
152 static bool protected_symlinks_enabled(void)
154 static int enabled = -1;
163 fd = open("/proc/sys/fs/protected_symlinks", O_RDONLY | O_CLOEXEC);
167 ret = read(fd, buf, sizeof(buf));
179 static bool xfs_irix_sgid_inherit_enabled(void)
181 static int enabled = -1;
191 fd = open("/proc/sys/fs/xfs/irix_sgid_inherit", O_RDONLY | O_CLOEXEC);
195 ret = read(fd, buf, sizeof(buf));
208 static inline bool caps_supported(void)
212 #ifdef HAVE_SYS_CAPABILITY_H
219 /* caps_down - lower all effective caps */
220 static int caps_down(void)
223 #ifdef HAVE_SYS_CAPABILITY_H
227 caps = cap_get_proc();
231 ret = cap_clear_flag(caps, CAP_EFFECTIVE);
235 ret = cap_set_proc(caps);
247 /* caps_up - raise all permitted caps */
248 static int caps_up(void)
251 #ifdef HAVE_SYS_CAPABILITY_H
256 caps = cap_get_proc();
260 for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
261 cap_flag_value_t flag;
263 ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
271 ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
276 ret = cap_set_proc(caps);
287 /* __expected_uid_gid - check whether file is owned by the provided uid and gid */
288 static bool __expected_uid_gid(int dfd, const char *path, int flags,
289 uid_t expected_uid, gid_t expected_gid, bool log)
294 ret = fstatat(dfd, path, &st, flags);
296 return log_errno(false, "failure: fstatat");
298 if (log && st.st_uid != expected_uid)
299 log_stderr("failure: uid(%d) != expected_uid(%d)", st.st_uid, expected_uid);
301 if (log && st.st_gid != expected_gid)
302 log_stderr("failure: gid(%d) != expected_gid(%d)", st.st_gid, expected_gid);
304 errno = 0; /* Don't report misleading errno. */
305 return st.st_uid == expected_uid && st.st_gid == expected_gid;
308 static bool expected_uid_gid(int dfd, const char *path, int flags,
309 uid_t expected_uid, gid_t expected_gid)
311 return __expected_uid_gid(dfd, path, flags,
312 expected_uid, expected_gid, true);
315 static bool expected_file_size(int dfd, const char *path,
316 int flags, off_t expected_size)
321 ret = fstatat(dfd, path, &st, flags);
323 return log_errno(false, "failure: fstatat");
325 if (st.st_size != expected_size)
326 return log_errno(false, "failure: st_size(%zu) != expected_size(%zu)",
327 (size_t)st.st_size, (size_t)expected_size);
332 /* is_setid - check whether file is S_ISUID and S_ISGID */
333 static bool is_setid(int dfd, const char *path, int flags)
338 ret = fstatat(dfd, path, &st, flags);
342 errno = 0; /* Don't report misleading errno. */
343 return (st.st_mode & S_ISUID) || (st.st_mode & S_ISGID);
346 /* is_setgid - check whether file or directory is S_ISGID */
347 static bool is_setgid(int dfd, const char *path, int flags)
352 ret = fstatat(dfd, path, &st, flags);
356 errno = 0; /* Don't report misleading errno. */
357 return (st.st_mode & S_ISGID);
360 /* is_sticky - check whether file is S_ISVTX */
361 static bool is_sticky(int dfd, const char *path, int flags)
366 ret = fstatat(dfd, path, &st, flags);
370 errno = 0; /* Don't report misleading errno. */
371 return (st.st_mode & S_ISVTX) > 0;
374 static inline int set_cloexec(int fd)
376 return fcntl(fd, F_SETFD, FD_CLOEXEC);
379 static inline bool switch_fsids(uid_t fsuid, gid_t fsgid)
382 return log_errno(false, "failure: setfsgid");
384 if (setfsgid(-1) != fsgid)
385 return log_errno(false, "failure: setfsgid(-1)");
388 return log_errno(false, "failure: setfsuid");
390 if (setfsuid(-1) != fsuid)
391 return log_errno(false, "failure: setfsuid(-1)");
396 static inline bool switch_ids(uid_t uid, gid_t gid)
398 if (setgroups(0, NULL))
399 return log_errno(false, "failure: setgroups");
401 if (setresgid(gid, gid, gid))
402 return log_errno(false, "failure: setresgid");
404 if (setresuid(uid, uid, uid))
405 return log_errno(false, "failure: setresuid");
410 static inline bool switch_userns(int fd, uid_t uid, gid_t gid, bool drop_caps)
412 if (setns(fd, CLONE_NEWUSER))
413 return log_errno(false, "failure: setns");
415 if (!switch_ids(uid, gid))
416 return log_errno(false, "failure: switch_ids");
418 if (drop_caps && !caps_down())
419 return log_errno(false, "failure: caps_down");
424 /* rm_r - recursively remove all files */
425 static int rm_r(int fd, const char *path)
429 struct dirent *direntp;
431 if (!path || strcmp(path, "") == 0)
434 dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
438 dir = fdopendir(dfd);
444 while ((direntp = readdir(dir))) {
447 if (!strcmp(direntp->d_name, ".") ||
448 !strcmp(direntp->d_name, ".."))
451 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
452 if (ret < 0 && errno != ENOENT)
455 if (S_ISDIR(st.st_mode))
456 ret = rm_r(dfd, direntp->d_name);
458 ret = unlinkat(dfd, direntp->d_name, 0);
459 if (ret < 0 && errno != ENOENT)
463 ret = unlinkat(fd, path, AT_REMOVEDIR);
468 /* chown_r - recursively change ownership of all files */
469 static int chown_r(int fd, const char *path, uid_t uid, gid_t gid)
473 struct dirent *direntp;
475 dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
479 dir = fdopendir(dfd);
485 while ((direntp = readdir(dir))) {
488 if (!strcmp(direntp->d_name, ".") ||
489 !strcmp(direntp->d_name, ".."))
492 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
493 if (ret < 0 && errno != ENOENT)
496 if (S_ISDIR(st.st_mode))
497 ret = chown_r(dfd, direntp->d_name, uid, gid);
499 ret = fchownat(dfd, direntp->d_name, uid, gid, AT_SYMLINK_NOFOLLOW);
500 if (ret < 0 && errno != ENOENT)
504 ret = fchownat(fd, path, uid, gid, AT_SYMLINK_NOFOLLOW);
510 * There'll be scenarios where you'll want to see the attributes associated with
511 * a directory tree during debugging or just to make sure things look correct.
512 * Simply uncomment and place the print_r() helper where you need it.
515 static int fd_cloexec(int fd, bool cloexec)
519 oflags = fcntl(fd, F_GETFD, 0);
524 nflags = oflags | FD_CLOEXEC;
526 nflags = oflags & ~FD_CLOEXEC;
528 if (nflags == oflags)
531 if (fcntl(fd, F_SETFD, nflags) < 0)
537 static inline int dup_cloexec(int fd)
545 if (fd_cloexec(fd_dup, true)) {
553 __attribute__((unused)) static int print_r(int fd, const char *path)
558 struct dirent *direntp;
561 if (!path || *path == '\0') {
562 char buf[sizeof("/proc/self/fd/") + 30];
564 ret = snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
565 if (ret < 0 || (size_t)ret >= sizeof(buf))
569 * O_PATH file descriptors can't be used so we need to re-open
572 dfd = openat(-EBADF, buf, O_CLOEXEC | O_DIRECTORY, 0);
574 dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY, 0);
580 * When fdopendir() below succeeds it assumes ownership of the fd so we
581 * to make sure we always have an fd that fdopendir() can own which is
582 * why we dup() in the case where the caller wants us to operate on the
585 dfd_dup = dup_cloexec(dfd);
591 dir = fdopendir(dfd);
597 /* Transfer ownership to fdopendir(). */
600 while ((direntp = readdir(dir))) {
601 if (!strcmp(direntp->d_name, ".") ||
602 !strcmp(direntp->d_name, ".."))
605 ret = fstatat(dfd_dup, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
606 if (ret < 0 && errno != ENOENT)
610 if (S_ISDIR(st.st_mode))
611 ret = print_r(dfd_dup, direntp->d_name);
613 fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %d/%s\n",
614 (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
615 dfd_dup, direntp->d_name);
616 if (ret < 0 && errno != ENOENT)
620 if (!path || *path == '\0')
621 ret = fstatat(fd, "", &st,
622 AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW |
625 ret = fstatat(fd, path, &st,
626 AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW);
628 fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %s",
629 (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
630 (path && *path) ? path : "(null)");
639 /* fd_to_fd - transfer data from one fd to another */
640 static int fd_to_fd(int from, int to)
643 uint8_t buf[PATH_MAX];
645 ssize_t bytes_to_write;
648 bytes_read = read_nointr(from, buf, sizeof buf);
654 bytes_to_write = (size_t)bytes_read;
656 ssize_t bytes_written;
658 bytes_written = write_nointr(to, p, bytes_to_write);
659 if (bytes_written < 0)
662 bytes_to_write -= bytes_written;
664 } while (bytes_to_write > 0);
670 static int sys_execveat(int fd, const char *path, char **argv, char **envp,
674 return syscall(__NR_execveat, fd, path, argv, envp, flags);
682 #define CAP_NET_RAW 13
685 #ifndef VFS_CAP_FLAGS_EFFECTIVE
686 #define VFS_CAP_FLAGS_EFFECTIVE 0x000001
689 #ifndef VFS_CAP_U32_3
690 #define VFS_CAP_U32_3 2
694 #define VFS_CAP_U32 VFS_CAP_U32_3
697 #ifndef VFS_CAP_REVISION_1
698 #define VFS_CAP_REVISION_1 0x01000000
701 #ifndef VFS_CAP_REVISION_2
702 #define VFS_CAP_REVISION_2 0x02000000
705 #ifndef VFS_CAP_REVISION_3
706 #define VFS_CAP_REVISION_3 0x03000000
707 struct vfs_ns_cap_data {
717 #if __BYTE_ORDER == __BIG_ENDIAN
718 #define cpu_to_le16(w16) le16_to_cpu(w16)
719 #define le16_to_cpu(w16) ((u_int16_t)((u_int16_t)(w16) >> 8) | (u_int16_t)((u_int16_t)(w16) << 8))
720 #define cpu_to_le32(w32) le32_to_cpu(w32)
721 #define le32_to_cpu(w32) \
722 ((u_int32_t)((u_int32_t)(w32) >> 24) | (u_int32_t)(((u_int32_t)(w32) >> 8) & 0xFF00) | \
723 (u_int32_t)(((u_int32_t)(w32) << 8) & 0xFF0000) | (u_int32_t)((u_int32_t)(w32) << 24))
724 #elif __BYTE_ORDER == __LITTLE_ENDIAN
725 #define cpu_to_le16(w16) ((u_int16_t)(w16))
726 #define le16_to_cpu(w16) ((u_int16_t)(w16))
727 #define cpu_to_le32(w32) ((u_int32_t)(w32))
728 #define le32_to_cpu(w32) ((u_int32_t)(w32))
730 #error Expected endianess macro to be set
733 /* expected_dummy_vfs_caps_uid - check vfs caps are stored with the provided uid */
734 static bool expected_dummy_vfs_caps_uid(int fd, uid_t expected_uid)
736 #define __cap_raised_permitted(x, ns_cap_data) \
737 ((ns_cap_data.data[(x) >> 5].permitted) & (1 << ((x)&31)))
738 struct vfs_ns_cap_data ns_xattr = {};
741 ret = fgetxattr(fd, "security.capability", &ns_xattr, sizeof(ns_xattr));
742 if (ret < 0 || ret == 0)
745 if (ns_xattr.magic_etc & VFS_CAP_REVISION_3) {
747 if (le32_to_cpu(ns_xattr.rootid) != expected_uid) {
749 log_stderr("failure: rootid(%d) != expected_rootid(%d)", le32_to_cpu(ns_xattr.rootid), expected_uid);
752 return (le32_to_cpu(ns_xattr.rootid) == expected_uid) &&
753 (__cap_raised_permitted(CAP_NET_RAW, ns_xattr) > 0);
755 log_stderr("failure: fscaps version");
761 /* set_dummy_vfs_caps - set dummy vfs caps for the provided uid */
762 static int set_dummy_vfs_caps(int fd, int flags, int rootuid)
764 #define __raise_cap_permitted(x, ns_cap_data) \
765 ns_cap_data.data[(x) >> 5].permitted |= (1 << ((x)&31))
767 struct vfs_ns_cap_data ns_xattr;
769 memset(&ns_xattr, 0, sizeof(ns_xattr));
770 __raise_cap_permitted(CAP_NET_RAW, ns_xattr);
771 ns_xattr.magic_etc |= VFS_CAP_REVISION_3 | VFS_CAP_FLAGS_EFFECTIVE;
772 ns_xattr.rootid = cpu_to_le32(rootuid);
774 return fsetxattr(fd, "security.capability",
775 &ns_xattr, sizeof(ns_xattr), flags);
778 #define safe_close(fd) \
786 static void test_setup(void)
788 if (mkdirat(t_mnt_fd, T_DIR1, 0777))
789 die("failure: mkdirat");
791 t_dir1_fd = openat(t_mnt_fd, T_DIR1, O_CLOEXEC | O_DIRECTORY);
793 die("failure: openat");
795 if (fchmod(t_dir1_fd, 0777))
796 die("failure: fchmod");
799 static void test_cleanup(void)
801 safe_close(t_dir1_fd);
802 if (rm_r(t_mnt_fd, T_DIR1))
803 die("failure: rm_r");
806 /* Validate that basic file operations on idmapped mounts. */
807 static int fsids_unmapped(void)
810 int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
811 struct mount_attr attr = {
812 .attr_set = MOUNT_ATTR_IDMAP,
815 /* create hardlink target */
816 hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
817 if (hardlink_target_fd < 0) {
818 log_stderr("failure: openat");
822 /* create directory for rename test */
823 if (mkdirat(t_dir1_fd, DIR1, 0700)) {
824 log_stderr("failure: mkdirat");
828 /* change ownership of all files to uid 0 */
829 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
830 log_stderr("failure: chown_r");
834 /* Changing mount properties on a detached mount. */
835 attr.userns_fd = get_userns_fd(0, 10000, 10000);
836 if (attr.userns_fd < 0) {
837 log_stderr("failure: get_userns_fd");
841 open_tree_fd = sys_open_tree(t_dir1_fd, "",
844 AT_SYMLINK_NOFOLLOW |
847 if (open_tree_fd < 0) {
848 log_stderr("failure: sys_open_tree");
852 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
853 log_stderr("failure: sys_mount_setattr");
857 if (!switch_fsids(0, 0)) {
858 log_stderr("failure: switch_fsids");
862 /* The caller's fsids don't have a mappings in the idmapped mount so any
863 * file creation must fail.
866 /* create hardlink */
867 if (!linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
868 log_stderr("failure: linkat");
871 if (errno != EOVERFLOW) {
872 log_stderr("failure: errno");
876 /* try to rename a file */
877 if (!renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0)) {
878 log_stderr("failure: renameat2");
881 if (errno != EOVERFLOW) {
882 log_stderr("failure: errno");
886 /* try to rename a directory */
887 if (!renameat2(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME, 0)) {
888 log_stderr("failure: renameat2");
891 if (errno != EOVERFLOW) {
892 log_stderr("failure: errno");
896 /* The caller is privileged over the inode so file deletion must work. */
899 if (unlinkat(open_tree_fd, FILE1, 0)) {
900 log_stderr("failure: unlinkat");
904 /* remove directory */
905 if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR)) {
906 log_stderr("failure: unlinkat");
910 /* The caller's fsids don't have a mappings in the idmapped mount so
911 * any file creation must fail.
914 /* create regular file via open() */
915 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
917 log_stderr("failure: create");
920 if (errno != EOVERFLOW) {
921 log_stderr("failure: errno");
925 /* create regular file via mknod */
926 if (!mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0)) {
927 log_stderr("failure: mknodat");
930 if (errno != EOVERFLOW) {
931 log_stderr("failure: errno");
935 /* create character device */
936 if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
937 log_stderr("failure: mknodat");
940 if (errno != EOVERFLOW) {
941 log_stderr("failure: errno");
946 if (!symlinkat(FILE2, open_tree_fd, SYMLINK1)) {
947 log_stderr("failure: symlinkat");
950 if (errno != EOVERFLOW) {
951 log_stderr("failure: errno");
955 /* create directory */
956 if (!mkdirat(open_tree_fd, DIR1, 0700)) {
957 log_stderr("failure: mkdirat");
960 if (errno != EOVERFLOW) {
961 log_stderr("failure: errno");
966 log_debug("Ran test");
968 safe_close(attr.userns_fd);
969 safe_close(hardlink_target_fd);
970 safe_close(file1_fd);
971 safe_close(open_tree_fd);
976 static int fsids_mapped(void)
979 int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
980 struct mount_attr attr = {
981 .attr_set = MOUNT_ATTR_IDMAP,
985 if (!caps_supported())
988 /* create hardlink target */
989 hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
990 if (hardlink_target_fd < 0) {
991 log_stderr("failure: openat");
995 /* create directory for rename test */
996 if (mkdirat(t_dir1_fd, DIR1, 0700)) {
997 log_stderr("failure: mkdirat");
1001 /* change ownership of all files to uid 0 */
1002 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1003 log_stderr("failure: chown_r");
1007 /* Changing mount properties on a detached mount. */
1008 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1009 if (attr.userns_fd < 0) {
1010 log_stderr("failure: get_userns_fd");
1014 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1017 AT_SYMLINK_NOFOLLOW |
1020 if (open_tree_fd < 0) {
1021 log_stderr("failure: sys_open_tree");
1025 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1026 log_stderr("failure: sys_mount_setattr");
1032 log_stderr("failure: fork");
1036 if (!switch_fsids(10000, 10000))
1037 die("failure: switch fsids");
1040 die("failure: raise caps");
1042 /* The caller's fsids now have mappings in the idmapped mount so
1043 * any file creation must fail.
1046 /* create hardlink */
1047 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1048 die("failure: create hardlink");
1050 /* try to rename a file */
1051 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
1052 die("failure: rename");
1054 /* try to rename a directory */
1055 if (renameat2(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME, 0))
1056 die("failure: rename");
1059 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1060 die("failure: delete");
1062 /* remove directory */
1063 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1064 die("failure: delete");
1066 /* The caller's fsids have mappings in the idmapped mount so any
1067 * file creation must fail.
1070 /* create regular file via open() */
1071 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1073 die("failure: create");
1075 /* create regular file via mknod */
1076 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1077 die("failure: create");
1079 /* create character device */
1080 if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
1081 die("failure: create");
1083 /* create symlink */
1084 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1085 die("failure: create");
1087 /* create directory */
1088 if (mkdirat(open_tree_fd, DIR1, 0700))
1089 die("failure: create");
1093 if (wait_for_pid(pid))
1097 log_debug("Ran test");
1099 safe_close(attr.userns_fd);
1100 safe_close(file1_fd);
1101 safe_close(hardlink_target_fd);
1102 safe_close(open_tree_fd);
1107 /* Validate that basic file operations on idmapped mounts from a user namespace. */
1108 static int create_in_userns(void)
1111 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1112 struct mount_attr attr = {
1113 .attr_set = MOUNT_ATTR_IDMAP,
1117 /* change ownership of all files to uid 0 */
1118 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1119 log_stderr("failure: chown_r");
1123 /* Changing mount properties on a detached mount. */
1124 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1125 if (attr.userns_fd < 0) {
1126 log_stderr("failure: get_userns_fd");
1130 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1133 AT_SYMLINK_NOFOLLOW |
1136 if (open_tree_fd < 0) {
1137 log_stderr("failure: sys_open_tree");
1141 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1142 log_stderr("failure: sys_mount_setattr");
1148 log_stderr("failure: fork");
1152 if (!switch_userns(attr.userns_fd, 0, 0, false))
1153 die("failure: switch_userns");
1155 /* create regular file via open() */
1156 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1158 die("failure: open file");
1159 safe_close(file1_fd);
1161 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1162 die("failure: check ownership");
1164 /* create regular file via mknod */
1165 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1166 die("failure: create");
1168 if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
1169 die("failure: check ownership");
1171 /* create symlink */
1172 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1173 die("failure: create");
1175 if (!expected_uid_gid(open_tree_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0))
1176 die("failure: check ownership");
1178 /* create directory */
1179 if (mkdirat(open_tree_fd, DIR1, 0700))
1180 die("failure: create");
1182 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
1183 die("failure: check ownership");
1185 /* try to rename a file */
1186 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
1187 die("failure: create");
1189 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1190 die("failure: check ownership");
1192 /* try to rename a file */
1193 if (renameat2(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME, 0))
1194 die("failure: create");
1196 if (!expected_uid_gid(open_tree_fd, DIR1_RENAME, 0, 0, 0))
1197 die("failure: check ownership");
1200 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1201 die("failure: remove");
1203 /* remove directory */
1204 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1205 die("failure: remove");
1210 if (wait_for_pid(pid))
1214 log_debug("Ran test");
1216 safe_close(attr.userns_fd);
1217 safe_close(file1_fd);
1218 safe_close(open_tree_fd);
1223 static int hardlink_crossing_mounts(void)
1226 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1228 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1229 log_stderr("failure: chown_r");
1233 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1236 AT_SYMLINK_NOFOLLOW |
1239 if (open_tree_fd < 0) {
1240 log_stderr("failure: sys_open_tree");
1244 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1246 log_stderr("failure: openat");
1250 if (mkdirat(open_tree_fd, DIR1, 0777)) {
1251 log_stderr("failure: mkdirat");
1255 /* We're crossing a mountpoint so this must fail.
1257 * Note that this must also fail for non-idmapped mounts but here we're
1258 * interested in making sure we're not introducing an accidental way to
1259 * violate that restriction or that suddenly this becomes possible.
1261 if (!linkat(open_tree_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
1262 log_stderr("failure: linkat");
1265 if (errno != EXDEV) {
1266 log_stderr("failure: errno");
1271 log_debug("Ran test");
1273 safe_close(file1_fd);
1274 safe_close(open_tree_fd);
1279 static int hardlink_crossing_idmapped_mounts(void)
1282 int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1283 struct mount_attr attr = {
1284 .attr_set = MOUNT_ATTR_IDMAP,
1287 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1288 log_stderr("failure: chown_r");
1292 attr.userns_fd = get_userns_fd(10000, 0, 10000);
1293 if (attr.userns_fd < 0) {
1294 log_stderr("failure: get_userns_fd");
1298 open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1301 AT_SYMLINK_NOFOLLOW |
1304 if (open_tree_fd1 < 0) {
1305 log_stderr("failure: sys_open_tree");
1309 if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1310 log_stderr("failure: sys_mount_setattr");
1314 file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1316 log_stderr("failure: openat");
1320 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1321 log_stderr("failure: expected_uid_gid");
1325 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1326 log_stderr("failure: expected_uid_gid");
1330 safe_close(file1_fd);
1332 if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1333 log_stderr("failure: mkdirat");
1337 open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1339 AT_SYMLINK_NOFOLLOW |
1343 if (open_tree_fd2 < 0) {
1344 log_stderr("failure: sys_open_tree");
1348 if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1349 log_stderr("failure: sys_mount_setattr");
1353 /* We're crossing a mountpoint so this must fail.
1355 * Note that this must also fail for non-idmapped mounts but here we're
1356 * interested in making sure we're not introducing an accidental way to
1357 * violate that restriction or that suddenly this becomes possible.
1359 if (!linkat(open_tree_fd1, FILE1, open_tree_fd2, HARDLINK1, 0)) {
1360 log_stderr("failure: linkat");
1363 if (errno != EXDEV) {
1364 log_stderr("failure: errno");
1369 log_debug("Ran test");
1371 safe_close(attr.userns_fd);
1372 safe_close(file1_fd);
1373 safe_close(open_tree_fd1);
1374 safe_close(open_tree_fd2);
1379 static int hardlink_from_idmapped_mount(void)
1382 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1383 struct mount_attr attr = {
1384 .attr_set = MOUNT_ATTR_IDMAP,
1387 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1388 log_stderr("failure: chown_r");
1392 attr.userns_fd = get_userns_fd(10000, 0, 10000);
1393 if (attr.userns_fd < 0) {
1394 log_stderr("failure: get_userns_fd");
1398 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1401 AT_SYMLINK_NOFOLLOW |
1404 if (open_tree_fd < 0) {
1405 log_stderr("failure: sys_open_tree");
1409 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1410 log_stderr("failure: sys_mount_setattr");
1414 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1416 log_stderr("failure: openat");
1419 safe_close(file1_fd);
1421 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1422 log_stderr("failure: expected_uid_gid");
1426 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1427 log_stderr("failure: expected_uid_gid");
1431 /* We're not crossing a mountpoint so this must succeed. */
1432 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
1433 log_stderr("failure: linkat");
1439 log_debug("Ran test");
1441 safe_close(attr.userns_fd);
1442 safe_close(file1_fd);
1443 safe_close(open_tree_fd);
1448 static int hardlink_from_idmapped_mount_in_userns(void)
1451 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1452 struct mount_attr attr = {
1453 .attr_set = MOUNT_ATTR_IDMAP,
1457 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1458 log_stderr("failure: chown_r");
1462 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1463 if (attr.userns_fd < 0) {
1464 log_stderr("failure: get_userns_fd");
1468 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1471 AT_SYMLINK_NOFOLLOW |
1474 if (open_tree_fd < 0) {
1475 log_stderr("failure: sys_open_tree");
1479 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1480 log_stderr("failure: sys_mount_setattr");
1486 log_stderr("failure: fork");
1490 if (!switch_userns(attr.userns_fd, 0, 0, false))
1491 die("failure: switch_userns");
1493 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1495 die("failure: create");
1497 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1498 die("failure: check ownership");
1500 /* We're not crossing a mountpoint so this must succeed. */
1501 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1502 die("failure: create");
1504 if (!expected_uid_gid(open_tree_fd, HARDLINK1, 0, 0, 0))
1505 die("failure: check ownership");
1510 if (wait_for_pid(pid))
1514 log_debug("Ran test");
1516 safe_close(attr.userns_fd);
1517 safe_close(file1_fd);
1518 safe_close(open_tree_fd);
1523 static int rename_crossing_mounts(void)
1526 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1528 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1529 log_stderr("failure: chown_r");
1533 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1536 AT_SYMLINK_NOFOLLOW |
1539 if (open_tree_fd < 0) {
1540 log_stderr("failure: sys_open_tree");
1544 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1546 log_stderr("failure: openat");
1550 if (mkdirat(open_tree_fd, DIR1, 0777)) {
1551 log_stderr("failure: mkdirat");
1555 /* We're crossing a mountpoint so this must fail.
1557 * Note that this must also fail for non-idmapped mounts but here we're
1558 * interested in making sure we're not introducing an accidental way to
1559 * violate that restriction or that suddenly this becomes possible.
1561 if (!renameat2(open_tree_fd, FILE1, t_dir1_fd, FILE1_RENAME, 0)) {
1562 log_stderr("failure: renameat2");
1565 if (errno != EXDEV) {
1566 log_stderr("failure: errno");
1571 log_debug("Ran test");
1573 safe_close(file1_fd);
1574 safe_close(open_tree_fd);
1579 static int rename_crossing_idmapped_mounts(void)
1582 int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1583 struct mount_attr attr = {
1584 .attr_set = MOUNT_ATTR_IDMAP,
1587 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1588 log_stderr("failure: chown_r");
1592 attr.userns_fd = get_userns_fd(10000, 0, 10000);
1593 if (attr.userns_fd < 0) {
1594 log_stderr("failure: get_userns_fd");
1598 open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1601 AT_SYMLINK_NOFOLLOW |
1604 if (open_tree_fd1 < 0) {
1605 log_stderr("failure: sys_open_tree");
1609 if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1610 log_stderr("failure: sys_mount_setattr");
1614 file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1616 log_stderr("failure: openat");
1620 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1621 log_stderr("failure: expected_uid_gid");
1625 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1626 log_stderr("failure: expected_uid_gid");
1630 if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1631 log_stderr("failure: mkdirat");
1635 open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1637 AT_SYMLINK_NOFOLLOW |
1641 if (open_tree_fd2 < 0) {
1642 log_stderr("failure: sys_open_tree");
1646 if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1647 log_stderr("failure: sys_mount_setattr");
1651 /* We're crossing a mountpoint so this must fail.
1653 * Note that this must also fail for non-idmapped mounts but here we're
1654 * interested in making sure we're not introducing an accidental way to
1655 * violate that restriction or that suddenly this becomes possible.
1657 if (!renameat2(open_tree_fd1, FILE1, open_tree_fd2, FILE1_RENAME, 0)) {
1658 log_stderr("failure: renameat2");
1661 if (errno != EXDEV) {
1662 log_stderr("failure: errno");
1667 log_debug("Ran test");
1669 safe_close(attr.userns_fd);
1670 safe_close(file1_fd);
1671 safe_close(open_tree_fd1);
1672 safe_close(open_tree_fd2);
1677 static int rename_from_idmapped_mount(void)
1680 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1681 struct mount_attr attr = {
1682 .attr_set = MOUNT_ATTR_IDMAP,
1685 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1686 log_stderr("failure: chown_r");
1690 attr.userns_fd = get_userns_fd(10000, 0, 10000);
1691 if (attr.userns_fd < 0) {
1692 log_stderr("failure: get_userns_fd");
1696 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1699 AT_SYMLINK_NOFOLLOW |
1702 if (open_tree_fd < 0) {
1703 log_stderr("failure: sys_open_tree");
1707 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1708 log_stderr("failure: sys_mount_setattr");
1712 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1714 log_stderr("failure: openat");
1718 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1719 log_stderr("failure: expected_uid_gid");
1723 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1724 log_stderr("failure: expected_uid_gid");
1728 /* We're not crossing a mountpoint so this must succeed. */
1729 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0)) {
1730 log_stderr("failure: renameat2");
1735 log_debug("Ran test");
1737 safe_close(attr.userns_fd);
1738 safe_close(file1_fd);
1739 safe_close(open_tree_fd);
1744 static int rename_from_idmapped_mount_in_userns(void)
1747 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1749 struct mount_attr attr = {
1750 .attr_set = MOUNT_ATTR_IDMAP,
1753 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1754 log_stderr("failure: chown_r");
1758 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1759 if (attr.userns_fd < 0) {
1760 log_stderr("failure: get_userns_fd");
1764 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1767 AT_SYMLINK_NOFOLLOW |
1770 if (open_tree_fd < 0) {
1771 log_stderr("failure: sys_open_tree");
1775 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1776 log_stderr("failure: sys_mount_setattr");
1782 log_stderr("failure: fork");
1786 if (!switch_userns(attr.userns_fd, 0, 0, false))
1787 die("failure: switch_userns");
1789 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1791 die("failure: create");
1793 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1794 die("failure: check ownership");
1796 /* We're not crossing a mountpoint so this must succeed. */
1797 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
1798 die("failure: create");
1800 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1801 die("failure: check ownership");
1806 if (wait_for_pid(pid))
1810 log_debug("Ran test");
1812 safe_close(attr.userns_fd);
1813 safe_close(file1_fd);
1814 safe_close(open_tree_fd);
1819 static int symlink_regular_mounts(void)
1822 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1825 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1827 log_stderr("failure: openat");
1831 if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1832 log_stderr("failure: chown_r");
1836 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1839 AT_SYMLINK_NOFOLLOW |
1842 if (open_tree_fd < 0) {
1843 log_stderr("failure: sys_open_tree");
1847 if (symlinkat(FILE1, open_tree_fd, FILE2)) {
1848 log_stderr("failure: symlinkat");
1852 if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW)) {
1853 log_stderr("failure: fchownat");
1857 if (fstatat(open_tree_fd, FILE2, &st, AT_SYMLINK_NOFOLLOW)) {
1858 log_stderr("failure: fstatat");
1862 if (st.st_uid != 15000 || st.st_gid != 15000) {
1863 log_stderr("failure: compare ids");
1867 if (fstatat(open_tree_fd, FILE1, &st, 0)) {
1868 log_stderr("failure: fstatat");
1872 if (st.st_uid != 10000 || st.st_gid != 10000) {
1873 log_stderr("failure: compare ids");
1878 log_debug("Ran test");
1880 safe_close(file1_fd);
1881 safe_close(open_tree_fd);
1886 static int symlink_idmapped_mounts(void)
1889 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1890 struct mount_attr attr = {
1891 .attr_set = MOUNT_ATTR_IDMAP,
1895 if (!caps_supported())
1898 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1900 log_stderr("failure: openat");
1904 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1905 log_stderr("failure: chown_r");
1909 /* Changing mount properties on a detached mount. */
1910 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1911 if (attr.userns_fd < 0) {
1912 log_stderr("failure: get_userns_fd");
1916 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1919 AT_SYMLINK_NOFOLLOW |
1922 if (open_tree_fd < 0) {
1923 log_stderr("failure: sys_open_tree");
1927 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1928 log_stderr("failure: sys_mount_setattr");
1934 log_stderr("failure: fork");
1938 if (!switch_fsids(10000, 10000))
1939 die("failure: switch fsids");
1942 die("failure: raise caps");
1944 if (symlinkat(FILE1, open_tree_fd, FILE2))
1945 die("failure: create");
1947 if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW))
1948 die("failure: change ownership");
1950 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 15000, 15000))
1951 die("failure: check ownership");
1953 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
1954 die("failure: check ownership");
1958 if (wait_for_pid(pid))
1962 log_debug("Ran test");
1964 safe_close(attr.userns_fd);
1965 safe_close(file1_fd);
1966 safe_close(open_tree_fd);
1971 static int symlink_idmapped_mounts_in_userns(void)
1974 int file1_fd = -EBADF, open_tree_fd = -EBADF;
1975 struct mount_attr attr = {
1976 .attr_set = MOUNT_ATTR_IDMAP,
1980 if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1981 log_stderr("failure: chown_r");
1985 /* Changing mount properties on a detached mount. */
1986 attr.userns_fd = get_userns_fd(0, 10000, 10000);
1987 if (attr.userns_fd < 0) {
1988 log_stderr("failure: get_userns_fd");
1992 open_tree_fd = sys_open_tree(t_dir1_fd, "",
1995 AT_SYMLINK_NOFOLLOW |
1998 if (open_tree_fd < 0) {
1999 log_stderr("failure: sys_open_tree");
2003 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2004 log_stderr("failure: sys_mount_setattr");
2010 log_stderr("failure: fork");
2014 if (!switch_userns(attr.userns_fd, 0, 0, false))
2015 die("failure: switch_userns");
2017 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2019 die("failure: create");
2020 safe_close(file1_fd);
2022 if (symlinkat(FILE1, open_tree_fd, FILE2))
2023 die("failure: create");
2025 if (fchownat(open_tree_fd, FILE2, 5000, 5000, AT_SYMLINK_NOFOLLOW))
2026 die("failure: change ownership");
2028 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000))
2029 die("failure: check ownership");
2031 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
2032 die("failure: check ownership");
2037 if (wait_for_pid(pid))
2040 if (!expected_uid_gid(t_dir1_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000)) {
2041 log_stderr("failure: expected_uid_gid");
2045 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2046 log_stderr("failure: expected_uid_gid");
2051 log_debug("Ran test");
2053 safe_close(attr.userns_fd);
2054 safe_close(file1_fd);
2055 safe_close(open_tree_fd);
2060 /* Validate that a caller whose fsids map into the idmapped mount within it's
2061 * user namespace cannot create any device nodes.
2063 static int device_node_in_userns(void)
2066 int open_tree_fd = -EBADF;
2067 struct mount_attr attr = {
2068 .attr_set = MOUNT_ATTR_IDMAP,
2072 attr.userns_fd = get_userns_fd(0, 10000, 10000);
2073 if (attr.userns_fd < 0) {
2074 log_stderr("failure: get_userns_fd");
2078 open_tree_fd = sys_open_tree(t_dir1_fd, "",
2081 AT_SYMLINK_NOFOLLOW |
2084 if (open_tree_fd < 0) {
2085 log_stderr("failure: sys_open_tree");
2089 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2090 log_stderr("failure: sys_mount_setattr");
2096 log_stderr("failure: fork");
2100 if (!switch_userns(attr.userns_fd, 0, 0, false))
2101 die("failure: switch_userns");
2103 /* create character device */
2104 if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
2105 die("failure: create");
2110 if (wait_for_pid(pid))
2114 log_debug("Ran test");
2116 safe_close(attr.userns_fd);
2117 safe_close(open_tree_fd);
2123 /* Validate that changing file ownership works correctly on idmapped mounts. */
2124 static int expected_uid_gid_idmapped_mounts(void)
2127 int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
2128 struct mount_attr attr1 = {
2129 .attr_set = MOUNT_ATTR_IDMAP,
2131 struct mount_attr attr2 = {
2132 .attr_set = MOUNT_ATTR_IDMAP,
2136 if (!switch_fsids(0, 0)) {
2137 log_stderr("failure: switch_fsids");
2141 /* create regular file via open() */
2142 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2144 log_stderr("failure: openat");
2148 /* create regular file via mknod */
2149 if (mknodat(t_dir1_fd, FILE2, S_IFREG | 0000, 0)) {
2150 log_stderr("failure: mknodat");
2154 /* create character device */
2155 if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
2156 log_stderr("failure: mknodat");
2160 /* create hardlink */
2161 if (linkat(t_dir1_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
2162 log_stderr("failure: linkat");
2166 /* create symlink */
2167 if (symlinkat(FILE2, t_dir1_fd, SYMLINK1)) {
2168 log_stderr("failure: symlinkat");
2172 /* create directory */
2173 if (mkdirat(t_dir1_fd, DIR1, 0700)) {
2174 log_stderr("failure: mkdirat");
2178 /* Changing mount properties on a detached mount. */
2179 attr1.userns_fd = get_userns_fd(0, 10000, 10000);
2180 if (attr1.userns_fd < 0) {
2181 log_stderr("failure: get_userns_fd");
2185 open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
2188 AT_SYMLINK_NOFOLLOW |
2191 if (open_tree_fd1 < 0) {
2192 log_stderr("failure: sys_open_tree");
2196 if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr1, sizeof(attr1))) {
2197 log_stderr("failure: sys_mount_setattr");
2201 /* Validate that all files created through the image mountpoint are
2202 * owned by the callers fsuid and fsgid.
2204 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2205 log_stderr("failure: expected_uid_gid");
2208 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2209 log_stderr("failure: expected_uid_gid");
2212 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2213 log_stderr("failure: expected_uid_gid");
2216 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2217 log_stderr("failure: expected_uid_gid");
2220 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
2221 log_stderr("failure: expected_uid_gid");
2224 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2225 log_stderr("failure: expected_uid_gid");
2228 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2229 log_stderr("failure: expected_uid_gid");
2233 /* Validate that all files are owned by the uid and gid specified in
2234 * the idmapping of the mount they are accessed from.
2236 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2237 log_stderr("failure: expected_uid_gid");
2240 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2241 log_stderr("failure: expected_uid_gid");
2244 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2245 log_stderr("failure: expected_uid_gid");
2248 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2249 log_stderr("failure: expected_uid_gid");
2252 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 10000, 10000)) {
2253 log_stderr("failure: expected_uid_gid");
2256 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2257 log_stderr("failure: expected_uid_gid");
2260 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2261 log_stderr("failure: expected_uid_gid");
2265 /* Changing mount properties on a detached mount. */
2266 attr2.userns_fd = get_userns_fd(0, 30000, 2001);
2267 if (attr2.userns_fd < 0) {
2268 log_stderr("failure: get_userns_fd");
2272 open_tree_fd2 = sys_open_tree(t_dir1_fd, "",
2275 AT_SYMLINK_NOFOLLOW |
2278 if (open_tree_fd2 < 0) {
2279 log_stderr("failure: sys_open_tree");
2283 if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr2, sizeof(attr2))) {
2284 log_stderr("failure: sys_mount_setattr");
2288 /* Validate that all files are owned by the uid and gid specified in
2289 * the idmapping of the mount they are accessed from.
2291 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2292 log_stderr("failure: expected_uid_gid");
2295 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2296 log_stderr("failure: expected_uid_gid");
2299 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2300 log_stderr("failure: expected_uid_gid");
2303 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2304 log_stderr("failure: expected_uid_gid");
2307 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 30000, 30000)) {
2308 log_stderr("failure: expected_uid_gid");
2311 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2312 log_stderr("failure: expected_uid_gid");
2315 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2316 log_stderr("failure: expected_uid_gid");
2320 /* Change ownership throught original image mountpoint. */
2321 if (fchownat(t_dir1_fd, FILE1, 2000, 2000, 0)) {
2322 log_stderr("failure: fchownat");
2325 if (fchownat(t_dir1_fd, FILE2, 2000, 2000, 0)) {
2326 log_stderr("failure: fchownat");
2329 if (fchownat(t_dir1_fd, HARDLINK1, 2000, 2000, 0)) {
2330 log_stderr("failure: fchownat");
2333 if (fchownat(t_dir1_fd, CHRDEV1, 2000, 2000, 0)) {
2334 log_stderr("failure: fchownat");
2337 if (fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)) {
2338 log_stderr("failure: fchownat");
2341 if (fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH)) {
2342 log_stderr("failure: fchownat");
2345 if (fchownat(t_dir1_fd, DIR1, 2000, 2000, AT_EMPTY_PATH)) {
2346 log_stderr("failure: fchownat");
2350 /* Check ownership through original mount. */
2351 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 2000, 2000)) {
2352 log_stderr("failure: expected_uid_gid");
2355 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 2000, 2000)) {
2356 log_stderr("failure: expected_uid_gid");
2359 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 2000, 2000)) {
2360 log_stderr("failure: expected_uid_gid");
2363 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 2000, 2000)) {
2364 log_stderr("failure: expected_uid_gid");
2367 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 3000, 3000)) {
2368 log_stderr("failure: expected_uid_gid");
2371 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 2000, 2000)) {
2372 log_stderr("failure: expected_uid_gid");
2375 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 2000, 2000)) {
2376 log_stderr("failure: expected_uid_gid");
2380 /* Check ownership through first idmapped mount. */
2381 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 12000, 12000)) {
2382 log_stderr("failure:expected_uid_gid ");
2385 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 12000, 12000)) {
2386 log_stderr("failure: expected_uid_gid");
2389 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 12000, 12000)) {
2390 log_stderr("failure: expected_uid_gid");
2393 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 12000, 12000)) {
2394 log_stderr("failure: expected_uid_gid");
2397 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 13000, 13000)) {
2398 log_stderr("failure: expected_uid_gid");
2401 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 12000, 12000)) {
2402 log_stderr("failure:expected_uid_gid ");
2405 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 12000, 12000)) {
2406 log_stderr("failure: expected_uid_gid");
2410 /* Check ownership through second idmapped mount. */
2411 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 32000, 32000)) {
2412 log_stderr("failure: expected_uid_gid");
2415 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 32000, 32000)) {
2416 log_stderr("failure: expected_uid_gid");
2419 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 32000, 32000)) {
2420 log_stderr("failure: expected_uid_gid");
2423 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 32000, 32000)) {
2424 log_stderr("failure: expected_uid_gid");
2427 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid)) {
2428 log_stderr("failure: expected_uid_gid");
2431 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 32000, 32000)) {
2432 log_stderr("failure: expected_uid_gid");
2435 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 32000, 32000)) {
2436 log_stderr("failure: expected_uid_gid");
2442 log_stderr("failure: fork");
2446 if (!switch_userns(attr1.userns_fd, 0, 0, false))
2447 die("failure: switch_userns");
2449 if (!fchownat(t_dir1_fd, FILE1, 1000, 1000, 0))
2450 die("failure: fchownat");
2451 if (!fchownat(t_dir1_fd, FILE2, 1000, 1000, 0))
2452 die("failure: fchownat");
2453 if (!fchownat(t_dir1_fd, HARDLINK1, 1000, 1000, 0))
2454 die("failure: fchownat");
2455 if (!fchownat(t_dir1_fd, CHRDEV1, 1000, 1000, 0))
2456 die("failure: fchownat");
2457 if (!fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2458 die("failure: fchownat");
2459 if (!fchownat(t_dir1_fd, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2460 die("failure: fchownat");
2461 if (!fchownat(t_dir1_fd, DIR1, 1000, 1000, AT_EMPTY_PATH))
2462 die("failure: fchownat");
2464 if (!fchownat(open_tree_fd2, FILE1, 1000, 1000, 0))
2465 die("failure: fchownat");
2466 if (!fchownat(open_tree_fd2, FILE2, 1000, 1000, 0))
2467 die("failure: fchownat");
2468 if (!fchownat(open_tree_fd2, HARDLINK1, 1000, 1000, 0))
2469 die("failure: fchownat");
2470 if (!fchownat(open_tree_fd2, CHRDEV1, 1000, 1000, 0))
2471 die("failure: fchownat");
2472 if (!fchownat(open_tree_fd2, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2473 die("failure: fchownat");
2474 if (!fchownat(open_tree_fd2, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2475 die("failure: fchownat");
2476 if (!fchownat(open_tree_fd2, DIR1, 1000, 1000, AT_EMPTY_PATH))
2477 die("failure: fchownat");
2479 if (fchownat(open_tree_fd1, FILE1, 1000, 1000, 0))
2480 die("failure: fchownat");
2481 if (fchownat(open_tree_fd1, FILE2, 1000, 1000, 0))
2482 die("failure: fchownat");
2483 if (fchownat(open_tree_fd1, HARDLINK1, 1000, 1000, 0))
2484 die("failure: fchownat");
2485 if (fchownat(open_tree_fd1, CHRDEV1, 1000, 1000, 0))
2486 die("failure: fchownat");
2487 if (fchownat(open_tree_fd1, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2488 die("failure: fchownat");
2489 if (fchownat(open_tree_fd1, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2490 die("failure: fchownat");
2491 if (fchownat(open_tree_fd1, DIR1, 1000, 1000, AT_EMPTY_PATH))
2492 die("failure: fchownat");
2494 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2495 die("failure: expected_uid_gid");
2496 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2497 die("failure: expected_uid_gid");
2498 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2499 die("failure: expected_uid_gid");
2500 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2501 die("failure: expected_uid_gid");
2502 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2503 die("failure: expected_uid_gid");
2504 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2505 die("failure: expected_uid_gid");
2506 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2507 die("failure: expected_uid_gid");
2509 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, t_overflowuid, t_overflowgid))
2510 die("failure: expected_uid_gid");
2511 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, t_overflowuid, t_overflowgid))
2512 die("failure: expected_uid_gid");
2513 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2514 die("failure: expected_uid_gid");
2515 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2516 die("failure: expected_uid_gid");
2517 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2518 die("failure: expected_uid_gid");
2519 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2520 die("failure: expected_uid_gid");
2521 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, t_overflowuid, t_overflowgid))
2522 die("failure: expected_uid_gid");
2524 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 1000, 1000))
2525 die("failure: expected_uid_gid");
2526 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 1000, 1000))
2527 die("failure: expected_uid_gid");
2528 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 1000, 1000))
2529 die("failure: expected_uid_gid");
2530 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 1000, 1000))
2531 die("failure: expected_uid_gid");
2532 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2533 die("failure: expected_uid_gid");
2534 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 1000, 1000))
2535 die("failure: expected_uid_gid");
2536 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 1000, 1000))
2537 die("failure: expected_uid_gid");
2542 if (wait_for_pid(pid))
2545 /* Check ownership through original mount. */
2546 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 1000, 1000)) {
2547 log_stderr("failure: expected_uid_gid");
2550 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 1000, 1000)) {
2551 log_stderr("failure: expected_uid_gid");
2554 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 1000, 1000)) {
2555 log_stderr("failure: expected_uid_gid");
2558 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 1000, 1000)) {
2559 log_stderr("failure: expected_uid_gid");
2562 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2563 log_stderr("failure: expected_uid_gid");
2566 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 1000, 1000)) {
2567 log_stderr("failure: expected_uid_gid");
2570 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 1000, 1000)) {
2571 log_stderr("failure: expected_uid_gid");
2575 /* Check ownership through first idmapped mount. */
2576 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 11000, 11000)) {
2577 log_stderr("failure: expected_uid_gid");
2580 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 11000, 11000)) {
2581 log_stderr("failure: expected_uid_gid");
2584 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 11000, 11000)) {
2585 log_stderr("failure: expected_uid_gid");
2588 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 11000, 11000)) {
2589 log_stderr("failure: expected_uid_gid");
2592 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2593 log_stderr("failure: expected_uid_gid");
2596 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 11000, 11000)) {
2597 log_stderr("failure: expected_uid_gid");
2600 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 11000, 11000)) {
2601 log_stderr("failure: expected_uid_gid");
2605 /* Check ownership through second idmapped mount. */
2606 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 31000, 31000)) {
2607 log_stderr("failure: expected_uid_gid");
2610 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 31000, 31000)) {
2611 log_stderr("failure: expected_uid_gid");
2614 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 31000, 31000)) {
2615 log_stderr("failure: expected_uid_gid");
2618 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 31000, 31000)) {
2619 log_stderr("failure: expected_uid_gid");
2622 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2623 log_stderr("failure: expected_uid_gid");
2626 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 31000, 31000)) {
2627 log_stderr("failure: expected_uid_gid");
2630 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 31000, 31000)) {
2631 log_stderr("failure: expected_uid_gid");
2637 log_stderr("failure: fork");
2641 if (!switch_userns(attr2.userns_fd, 0, 0, false))
2642 die("failure: switch_userns");
2644 if (!fchownat(t_dir1_fd, FILE1, 0, 0, 0))
2645 die("failure: fchownat");
2646 if (!fchownat(t_dir1_fd, FILE2, 0, 0, 0))
2647 die("failure: fchownat");
2648 if (!fchownat(t_dir1_fd, HARDLINK1, 0, 0, 0))
2649 die("failure: fchownat");
2650 if (!fchownat(t_dir1_fd, CHRDEV1, 0, 0, 0))
2651 die("failure: fchownat");
2652 if (!fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2653 die("failure: fchownat");
2654 if (!fchownat(t_dir1_fd, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2655 die("failure: fchownat");
2656 if (!fchownat(t_dir1_fd, DIR1, 0, 0, AT_EMPTY_PATH))
2657 die("failure: fchownat");
2659 if (!fchownat(open_tree_fd1, FILE1, 0, 0, 0))
2660 die("failure: fchownat");
2661 if (!fchownat(open_tree_fd1, FILE2, 0, 0, 0))
2662 die("failure: fchownat");
2663 if (!fchownat(open_tree_fd1, HARDLINK1, 0, 0, 0))
2664 die("failure: fchownat");
2665 if (!fchownat(open_tree_fd1, CHRDEV1, 0, 0, 0))
2666 die("failure: fchownat");
2667 if (!fchownat(open_tree_fd1, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2668 die("failure: fchownat");
2669 if (!fchownat(open_tree_fd1, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2670 die("failure: fchownat");
2671 if (!fchownat(open_tree_fd1, DIR1, 0, 0, AT_EMPTY_PATH))
2672 die("failure: fchownat");
2674 if (fchownat(open_tree_fd2, FILE1, 0, 0, 0))
2675 die("failure: fchownat");
2676 if (fchownat(open_tree_fd2, FILE2, 0, 0, 0))
2677 die("failure: fchownat");
2678 if (fchownat(open_tree_fd2, HARDLINK1, 0, 0, 0))
2679 die("failure: fchownat");
2680 if (fchownat(open_tree_fd2, CHRDEV1, 0, 0, 0))
2681 die("failure: fchownat");
2682 if (!fchownat(open_tree_fd2, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2683 die("failure: fchownat");
2684 if (fchownat(open_tree_fd2, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2685 die("failure: fchownat");
2686 if (fchownat(open_tree_fd2, DIR1, 0, 0, AT_EMPTY_PATH))
2687 die("failure: fchownat");
2689 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2690 die("failure: expected_uid_gid");
2691 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2692 die("failure: expected_uid_gid");
2693 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2694 die("failure: expected_uid_gid");
2695 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2696 die("failure: expected_uid_gid");
2697 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2698 die("failure: expected_uid_gid");
2699 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2700 die("failure: expected_uid_gid");
2701 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2702 die("failure: expected_uid_gid");
2704 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, t_overflowuid, t_overflowgid))
2705 die("failure: expected_uid_gid");
2706 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, t_overflowuid, t_overflowgid))
2707 die("failure: expected_uid_gid");
2708 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2709 die("failure: expected_uid_gid");
2710 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2711 die("failure: expected_uid_gid");
2712 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2713 die("failure: expected_uid_gid");
2714 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2715 die("failure: expected_uid_gid");
2716 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, t_overflowuid, t_overflowgid))
2717 die("failure: expected_uid_gid");
2719 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 0, 0))
2720 die("failure: expected_uid_gid");
2721 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 0, 0))
2722 die("failure: expected_uid_gid");
2723 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 0, 0))
2724 die("failure: expected_uid_gid");
2725 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 0, 0))
2726 die("failure: expected_uid_gid");
2727 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2728 die("failure: expected_uid_gid");
2729 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 0, 0))
2730 die("failure: expected_uid_gid");
2731 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 0, 0))
2732 die("failure: expected_uid_gid");
2737 if (wait_for_pid(pid))
2740 /* Check ownership through original mount. */
2741 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2742 log_stderr("failure: expected_uid_gid");
2745 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2746 log_stderr("failure: expected_uid_gid");
2749 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2750 log_stderr("failure: expected_uid_gid");
2753 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2754 log_stderr("failure: expected_uid_gid");
2757 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2758 log_stderr("failure: expected_uid_gid");
2761 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2762 log_stderr("failure: expected_uid_gid");
2765 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2766 log_stderr("failure: expected_uid_gid");
2770 /* Check ownership through first idmapped mount. */
2771 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2772 log_stderr("failure: expected_uid_gid");
2775 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2776 log_stderr("failure: expected_uid_gid");
2779 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2780 log_stderr("failure: expected_uid_gid");
2783 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2784 log_stderr("failure: expected_uid_gid");
2787 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2788 log_stderr("failure: expected_uid_gid");
2791 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2792 log_stderr("failure: expected_uid_gid");
2795 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2796 log_stderr("failure: expected_uid_gid");
2800 /* Check ownership through second idmapped mount. */
2801 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2802 log_stderr("failure: expected_uid_gid");
2805 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2806 log_stderr("failure: expected_uid_gid");
2809 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2810 log_stderr("failure: expected_uid_gid");
2813 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2814 log_stderr("failure: expected_uid_gid");
2817 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2818 log_stderr("failure: expected_uid_gid");
2821 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2822 log_stderr("failure: expected_uid_gid");
2825 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2826 log_stderr("failure: expected_uid_gid");
2831 log_debug("Ran test");
2833 safe_close(attr1.userns_fd);
2834 safe_close(attr2.userns_fd);
2835 safe_close(file1_fd);
2836 safe_close(open_tree_fd1);
2837 safe_close(open_tree_fd2);
2842 static int fscaps(void)
2845 int file1_fd = -EBADF;
2846 struct mount_attr attr = {
2847 .attr_set = MOUNT_ATTR_IDMAP,
2851 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2853 log_stderr("failure: openat");
2857 /* Skip if vfs caps are unsupported. */
2858 if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2861 /* Changing mount properties on a detached mount. */
2862 attr.userns_fd = get_userns_fd(0, 10000, 10000);
2863 if (attr.userns_fd < 0) {
2864 log_stderr("failure: get_userns_fd");
2868 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
2869 log_stderr("failure: expected_dummy_vfs_caps_uid");
2875 log_stderr("failure: fork");
2879 if (!switch_userns(attr.userns_fd, 0, 0, false))
2880 die("failure: switch_userns");
2883 * On kernels before 5.12 this would succeed and return the
2884 * unconverted caps. Then - for whatever reason - this behavior
2885 * got changed and since 5.12 EOVERFLOW is returned when the
2886 * rootid stored alongside the vfs caps does not map to uid 0 in
2887 * the caller's user namespace.
2889 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
2890 die("failure: expected_dummy_vfs_caps_uid");
2895 if (wait_for_pid(pid))
2898 if (fremovexattr(file1_fd, "security.capability")) {
2899 log_stderr("failure: fremovexattr");
2902 if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2903 log_stderr("failure: expected_dummy_vfs_caps_uid");
2906 if (errno != ENODATA) {
2907 log_stderr("failure: errno");
2911 if (set_dummy_vfs_caps(file1_fd, 0, 10000)) {
2912 log_stderr("failure: set_dummy_vfs_caps");
2916 if (!expected_dummy_vfs_caps_uid(file1_fd, 10000)) {
2917 log_stderr("failure: expected_dummy_vfs_caps_uid");
2923 log_stderr("failure: fork");
2927 if (!switch_userns(attr.userns_fd, 0, 0, false))
2928 die("failure: switch_userns");
2930 if (!expected_dummy_vfs_caps_uid(file1_fd, 0))
2931 die("failure: expected_dummy_vfs_caps_uid");
2936 if (wait_for_pid(pid))
2939 if (fremovexattr(file1_fd, "security.capability")) {
2940 log_stderr("failure: fremovexattr");
2943 if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2944 log_stderr("failure: expected_dummy_vfs_caps_uid");
2947 if (errno != ENODATA) {
2948 log_stderr("failure: errno");
2953 log_debug("Ran test");
2955 safe_close(attr.userns_fd);
2956 safe_close(file1_fd);
2961 static int fscaps_idmapped_mounts(void)
2964 int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
2965 struct mount_attr attr = {
2966 .attr_set = MOUNT_ATTR_IDMAP,
2970 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2972 log_stderr("failure: openat");
2976 /* Skip if vfs caps are unsupported. */
2977 if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2980 if (fremovexattr(file1_fd, "security.capability")) {
2981 log_stderr("failure: fremovexattr");
2985 /* Changing mount properties on a detached mount. */
2986 attr.userns_fd = get_userns_fd(0, 10000, 10000);
2987 if (attr.userns_fd < 0) {
2988 log_stderr("failure: get_userns_fd");
2992 open_tree_fd = sys_open_tree(t_dir1_fd, "",
2995 AT_SYMLINK_NOFOLLOW |
2998 if (open_tree_fd < 0) {
2999 log_stderr("failure: sys_open_tree");
3003 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3004 log_stderr("failure: sys_mount_setattr");
3008 file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3009 if (file1_fd2 < 0) {
3010 log_stderr("failure: openat");
3014 if (!set_dummy_vfs_caps(file1_fd2, 0, 1000)) {
3015 log_stderr("failure: set_dummy_vfs_caps");
3019 if (set_dummy_vfs_caps(file1_fd2, 0, 10000)) {
3020 log_stderr("failure: set_dummy_vfs_caps");
3024 if (!expected_dummy_vfs_caps_uid(file1_fd2, 10000)) {
3025 log_stderr("failure: expected_dummy_vfs_caps_uid");
3029 if (!expected_dummy_vfs_caps_uid(file1_fd, 0)) {
3030 log_stderr("failure: expected_dummy_vfs_caps_uid");
3036 log_stderr("failure: fork");
3040 if (!switch_userns(attr.userns_fd, 0, 0, false))
3041 die("failure: switch_userns");
3043 if (!expected_dummy_vfs_caps_uid(file1_fd2, 0))
3044 die("failure: expected_dummy_vfs_caps_uid");
3049 if (wait_for_pid(pid))
3052 if (fremovexattr(file1_fd2, "security.capability")) {
3053 log_stderr("failure: fremovexattr");
3056 if (expected_dummy_vfs_caps_uid(file1_fd2, -1)) {
3057 log_stderr("failure: expected_dummy_vfs_caps_uid");
3060 if (errno != ENODATA) {
3061 log_stderr("failure: errno");
3065 if (set_dummy_vfs_caps(file1_fd2, 0, 12000)) {
3066 log_stderr("failure: set_dummy_vfs_caps");
3070 if (!expected_dummy_vfs_caps_uid(file1_fd2, 12000)) {
3071 log_stderr("failure: expected_dummy_vfs_caps_uid");
3075 if (!expected_dummy_vfs_caps_uid(file1_fd, 2000)) {
3076 log_stderr("failure: expected_dummy_vfs_caps_uid");
3082 log_stderr("failure: fork");
3086 if (!switch_userns(attr.userns_fd, 0, 0, false))
3087 die("failure: switch_userns");
3089 if (!expected_dummy_vfs_caps_uid(file1_fd2, 2000))
3090 die("failure: expected_dummy_vfs_caps_uid");
3095 if (wait_for_pid(pid))
3099 log_debug("Ran test");
3101 safe_close(attr.userns_fd);
3102 safe_close(file1_fd);
3103 safe_close(file1_fd2);
3104 safe_close(open_tree_fd);
3109 static int fscaps_idmapped_mounts_in_userns(void)
3112 int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
3113 struct mount_attr attr = {
3114 .attr_set = MOUNT_ATTR_IDMAP,
3118 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
3120 log_stderr("failure: openat");
3124 /* Skip if vfs caps are unsupported. */
3125 if (set_dummy_vfs_caps(file1_fd, 0, 1000))
3128 if (fremovexattr(file1_fd, "security.capability")) {
3129 log_stderr("failure: fremovexattr");
3133 /* Changing mount properties on a detached mount. */
3134 attr.userns_fd = get_userns_fd(0, 10000, 10000);
3135 if (attr.userns_fd < 0) {
3136 log_stderr("failure: get_userns_fd");
3140 open_tree_fd = sys_open_tree(t_dir1_fd, "",
3143 AT_SYMLINK_NOFOLLOW |
3146 if (open_tree_fd < 0) {
3147 log_stderr("failure: sys_open_tree");
3151 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3152 log_stderr("failure: sys_mount_setattr");
3156 file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3157 if (file1_fd2 < 0) {
3158 log_stderr("failure: openat");
3164 log_stderr("failure: fork");
3168 if (!switch_userns(attr.userns_fd, 0, 0, false))
3169 die("failure: switch_userns");
3171 if (expected_dummy_vfs_caps_uid(file1_fd2, -1))
3172 die("failure: expected_dummy_vfs_caps_uid");
3173 if (errno != ENODATA)
3174 die("failure: errno");
3176 if (set_dummy_vfs_caps(file1_fd2, 0, 1000))
3177 die("failure: set_dummy_vfs_caps");
3179 if (!expected_dummy_vfs_caps_uid(file1_fd2, 1000))
3180 die("failure: expected_dummy_vfs_caps_uid");
3182 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
3183 die("failure: expected_dummy_vfs_caps_uid");
3188 if (wait_for_pid(pid))
3191 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
3192 log_stderr("failure: expected_dummy_vfs_caps_uid");
3197 log_debug("Ran test");
3199 safe_close(attr.userns_fd);
3200 safe_close(file1_fd);
3201 safe_close(file1_fd2);
3202 safe_close(open_tree_fd);
3207 static int fscaps_idmapped_mounts_in_userns_separate_userns(void)
3210 int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
3211 struct mount_attr attr = {
3212 .attr_set = MOUNT_ATTR_IDMAP,
3216 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
3218 log_stderr("failure: openat");
3222 /* Skip if vfs caps are unsupported. */
3223 if (set_dummy_vfs_caps(file1_fd, 0, 1000)) {
3224 log_stderr("failure: set_dummy_vfs_caps");
3228 if (fremovexattr(file1_fd, "security.capability")) {
3229 log_stderr("failure: fremovexattr");
3233 /* change ownership of all files to uid 0 */
3234 if (chown_r(t_mnt_fd, T_DIR1, 20000, 20000)) {
3235 log_stderr("failure: chown_r");
3239 /* Changing mount properties on a detached mount. */
3240 attr.userns_fd = get_userns_fd(20000, 10000, 10000);
3241 if (attr.userns_fd < 0) {
3242 log_stderr("failure: get_userns_fd");
3246 open_tree_fd = sys_open_tree(t_dir1_fd, "",
3249 AT_SYMLINK_NOFOLLOW |
3252 if (open_tree_fd < 0) {
3253 log_stderr("failure: sys_open_tree");
3257 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3258 log_stderr("failure: sys_mount_setattr");
3262 file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3263 if (file1_fd2 < 0) {
3264 log_stderr("failure: openat");
3270 log_stderr("failure: fork");
3276 userns_fd = get_userns_fd(0, 10000, 10000);
3278 die("failure: get_userns_fd");
3280 if (!switch_userns(userns_fd, 0, 0, false))
3281 die("failure: switch_userns");
3283 if (set_dummy_vfs_caps(file1_fd2, 0, 0))
3284 die("failure: set fscaps");
3286 if (!expected_dummy_vfs_caps_uid(file1_fd2, 0))
3287 die("failure: expected_dummy_vfs_caps_uid");
3289 if (!expected_dummy_vfs_caps_uid(file1_fd, 20000) && errno != EOVERFLOW)
3290 die("failure: expected_dummy_vfs_caps_uid");
3295 if (wait_for_pid(pid))
3298 if (!expected_dummy_vfs_caps_uid(file1_fd, 20000)) {
3299 log_stderr("failure: expected_dummy_vfs_caps_uid");
3305 log_stderr("failure: fork");
3311 userns_fd = get_userns_fd(0, 10000, 10000);
3313 die("failure: get_userns_fd");
3315 if (!switch_userns(userns_fd, 0, 0, false))
3316 die("failure: switch_userns");
3318 if (fremovexattr(file1_fd2, "security.capability"))
3319 die("failure: fremovexattr");
3320 if (expected_dummy_vfs_caps_uid(file1_fd2, -1))
3321 die("failure: expected_dummy_vfs_caps_uid");
3322 if (errno != ENODATA)
3323 die("failure: errno");
3325 if (set_dummy_vfs_caps(file1_fd2, 0, 1000))
3326 die("failure: set_dummy_vfs_caps");
3328 if (!expected_dummy_vfs_caps_uid(file1_fd2, 1000))
3329 die("failure: expected_dummy_vfs_caps_uid");
3331 if (!expected_dummy_vfs_caps_uid(file1_fd, 21000) && errno != EOVERFLOW)
3332 die("failure: expected_dummy_vfs_caps_uid");
3337 if (wait_for_pid(pid))
3340 if (!expected_dummy_vfs_caps_uid(file1_fd, 21000)) {
3341 log_stderr("failure: expected_dummy_vfs_caps_uid");
3346 log_debug("Ran test");
3348 safe_close(attr.userns_fd);
3349 safe_close(file1_fd);
3350 safe_close(file1_fd2);
3351 safe_close(open_tree_fd);
3356 /* Validate that when the IDMAP_MOUNT_TEST_RUN_SETID environment variable is set
3357 * to 1 that we are executed with setid privileges and if set to 0 we are not.
3358 * If the env variable isn't set the tests are not run.
3360 static void __attribute__((constructor)) setuid_rexec(void)
3362 const char *expected_euid_str, *expected_egid_str, *rexec;
3364 rexec = getenv("IDMAP_MOUNT_TEST_RUN_SETID");
3365 /* This is a regular test-suite run. */
3369 expected_euid_str = getenv("EXPECTED_EUID");
3370 expected_egid_str = getenv("EXPECTED_EGID");
3372 if (expected_euid_str && expected_egid_str) {
3373 uid_t expected_euid;
3374 gid_t expected_egid;
3376 expected_euid = atoi(expected_euid_str);
3377 expected_egid = atoi(expected_egid_str);
3379 if (strcmp(rexec, "1") == 0) {
3380 /* we're expecting to run setid */
3381 if ((getuid() != geteuid()) && (expected_euid == geteuid()) &&
3382 (getgid() != getegid()) && (expected_egid == getegid()))
3384 } else if (strcmp(rexec, "0") == 0) {
3385 /* we're expecting to not run setid */
3386 if ((getuid() == geteuid()) && (expected_euid == geteuid()) &&
3387 (getgid() == getegid()) && (expected_egid == getegid()))
3390 die("failure: non-setid");
3397 /* Validate that setid transitions are handled correctly. */
3398 static int setid_binaries(void)
3401 int file1_fd = -EBADF, exec_fd = -EBADF;
3404 /* create a file to be used as setuid binary */
3405 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3407 log_stderr("failure: openat");
3411 /* open our own executable */
3412 exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3414 log_stderr("failure: openat");
3418 /* copy our own executable into the file we created */
3419 if (fd_to_fd(exec_fd, file1_fd)) {
3420 log_stderr("failure: fd_to_fd");
3424 /* chown the file to the uid and gid we want to assume */
3425 if (fchown(file1_fd, 5000, 5000)) {
3426 log_stderr("failure: fchown");
3430 /* set the setid bits and grant execute permissions to the group */
3431 if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3432 log_stderr("failure: fchmod");
3436 /* Verify that the sid bits got raised. */
3437 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3438 log_stderr("failure: is_setid");
3442 safe_close(exec_fd);
3443 safe_close(file1_fd);
3445 /* Verify we run setid binary as uid and gid 5000 from the original
3450 log_stderr("failure: fork");
3454 static char *envp[] = {
3455 "IDMAP_MOUNT_TEST_RUN_SETID=1",
3456 "EXPECTED_EUID=5000",
3457 "EXPECTED_EGID=5000",
3460 static char *argv[] = {
3464 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 5000, 5000))
3465 die("failure: expected_uid_gid");
3467 sys_execveat(t_dir1_fd, FILE1, argv, envp, 0);
3468 die("failure: sys_execveat");
3472 if (wait_for_pid(pid))
3476 log_debug("Ran test");
3482 /* Validate that setid transitions are handled correctly on idmapped mounts. */
3483 static int setid_binaries_idmapped_mounts(void)
3486 int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3487 struct mount_attr attr = {
3488 .attr_set = MOUNT_ATTR_IDMAP,
3492 if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3493 log_stderr("failure: mkdirat");
3497 /* create a file to be used as setuid binary */
3498 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3500 log_stderr("failure: openat");
3504 /* open our own executable */
3505 exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3507 log_stderr("failure:openat ");
3511 /* copy our own executable into the file we created */
3512 if (fd_to_fd(exec_fd, file1_fd)) {
3513 log_stderr("failure: fd_to_fd");
3517 /* chown the file to the uid and gid we want to assume */
3518 if (fchown(file1_fd, 5000, 5000)) {
3519 log_stderr("failure: fchown");
3523 /* set the setid bits and grant execute permissions to the group */
3524 if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3525 log_stderr("failure: fchmod");
3529 /* Verify that the sid bits got raised. */
3530 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3531 log_stderr("failure: is_setid");
3535 safe_close(exec_fd);
3536 safe_close(file1_fd);
3538 /* Changing mount properties on a detached mount. */
3539 attr.userns_fd = get_userns_fd(0, 10000, 10000);
3540 if (attr.userns_fd < 0) {
3541 log_stderr("failure: get_userns_fd");
3545 open_tree_fd = sys_open_tree(t_dir1_fd, "",
3548 AT_SYMLINK_NOFOLLOW |
3551 if (open_tree_fd < 0) {
3552 log_stderr("failure: sys_open_tree");
3556 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3557 log_stderr("failure: sys_mount_setattr");
3561 /* A detached mount will have an anonymous mount namespace attached to
3562 * it. This means that we can't execute setid binaries on a detached
3563 * mount because the mnt_may_suid() helper will fail the check_mount()
3564 * part of its check which compares the caller's mount namespace to the
3565 * detached mount's mount namespace. Since by definition an anonymous
3566 * mount namespace is not equale to any mount namespace currently in
3567 * use this can't work. So attach the mount to the filesystem first
3568 * before performing this check.
3570 if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3571 log_stderr("failure: sys_move_mount");
3575 /* Verify we run setid binary as uid and gid 10000 from idmapped mount mount. */
3578 log_stderr("failure: fork");
3582 static char *envp[] = {
3583 "IDMAP_MOUNT_TEST_RUN_SETID=1",
3584 "EXPECTED_EUID=15000",
3585 "EXPECTED_EGID=15000",
3588 static char *argv[] = {
3592 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 15000, 15000))
3593 die("failure: expected_uid_gid");
3595 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3596 die("failure: sys_execveat");
3601 if (wait_for_pid(pid))
3605 log_debug("Ran test");
3607 safe_close(exec_fd);
3608 safe_close(file1_fd);
3609 safe_close(open_tree_fd);
3611 snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
3612 sys_umount2(t_buf, MNT_DETACH);
3613 rm_r(t_mnt_fd, DIR1);
3618 /* Validate that setid transitions are handled correctly on idmapped mounts
3619 * running in a user namespace where the uid and gid of the setid binary have no
3622 static int setid_binaries_idmapped_mounts_in_userns(void)
3625 int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3626 struct mount_attr attr = {
3627 .attr_set = MOUNT_ATTR_IDMAP,
3631 if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3632 log_stderr("failure: ");
3636 /* create a file to be used as setuid binary */
3637 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3639 log_stderr("failure: openat");
3643 /* open our own executable */
3644 exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3646 log_stderr("failure: openat");
3650 /* copy our own executable into the file we created */
3651 if (fd_to_fd(exec_fd, file1_fd)) {
3652 log_stderr("failure: fd_to_fd");
3656 safe_close(exec_fd);
3658 /* chown the file to the uid and gid we want to assume */
3659 if (fchown(file1_fd, 5000, 5000)) {
3660 log_stderr("failure: fchown");
3664 /* set the setid bits and grant execute permissions to the group */
3665 if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3666 log_stderr("failure: fchmod");
3670 /* Verify that the sid bits got raised. */
3671 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3672 log_stderr("failure: is_setid");
3676 safe_close(file1_fd);
3678 /* Changing mount properties on a detached mount. */
3679 attr.userns_fd = get_userns_fd(0, 10000, 10000);
3680 if (attr.userns_fd < 0) {
3681 log_stderr("failure: get_userns_fd");
3685 open_tree_fd = sys_open_tree(t_dir1_fd, "",
3688 AT_SYMLINK_NOFOLLOW |
3691 if (open_tree_fd < 0) {
3692 log_stderr("failure: sys_open_tree");
3696 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3697 log_stderr("failure: sys_mount_setattr");
3701 /* A detached mount will have an anonymous mount namespace attached to
3702 * it. This means that we can't execute setid binaries on a detached
3703 * mount because the mnt_may_suid() helper will fail the check_mount()
3704 * part of its check which compares the caller's mount namespace to the
3705 * detached mount's mount namespace. Since by definition an anonymous
3706 * mount namespace is not equale to any mount namespace currently in
3707 * use this can't work. So attach the mount to the filesystem first
3708 * before performing this check.
3710 if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3711 log_stderr("failure: sys_move_mount");
3717 log_stderr("failure: fork");
3721 static char *envp[] = {
3722 "IDMAP_MOUNT_TEST_RUN_SETID=1",
3723 "EXPECTED_EUID=5000",
3724 "EXPECTED_EGID=5000",
3727 static char *argv[] = {
3731 if (!switch_userns(attr.userns_fd, 0, 0, false))
3732 die("failure: switch_userns");
3734 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 5000, 5000))
3735 die("failure: expected_uid_gid");
3737 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3738 die("failure: sys_execveat");
3743 if (wait_for_pid(pid)) {
3744 log_stderr("failure: wait_for_pid");
3748 file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
3750 log_stderr("failure: openat");
3754 /* chown the file to the uid and gid we want to assume */
3755 if (fchown(file1_fd, 0, 0)) {
3756 log_stderr("failure: fchown");
3760 /* set the setid bits and grant execute permissions to the group */
3761 if (fchmod(file1_fd, S_IXOTH | S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3762 log_stderr("failure: fchmod");
3766 /* Verify that the sid bits got raised. */
3767 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3768 log_stderr("failure: is_setid");
3772 safe_close(file1_fd);
3776 log_stderr("failure: fork");
3780 static char *envp[] = {
3781 "IDMAP_MOUNT_TEST_RUN_SETID=1",
3786 static char *argv[] = {
3790 if (!caps_supported()) {
3791 log_debug("skip: capability library not installed");
3795 if (!switch_userns(attr.userns_fd, 5000, 5000, true))
3796 die("failure: switch_userns");
3798 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
3799 die("failure: expected_uid_gid");
3801 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3802 die("failure: sys_execveat");
3807 if (wait_for_pid(pid)) {
3808 log_stderr("failure: wait_for_pid");
3812 file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
3814 log_stderr("failure: openat");
3818 /* chown the file to the uid and gid we want to assume */
3819 if (fchown(file1_fd, 30000, 30000)) {
3820 log_stderr("failure: fchown");
3824 if (fchmod(file1_fd, S_IXOTH | S_IEXEC | S_ISUID | S_ISGID), 0) {
3825 log_stderr("failure: fchmod");
3829 /* Verify that the sid bits got raised. */
3830 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3831 log_stderr("failure: is_setid");
3835 safe_close(file1_fd);
3837 /* Verify that we can't assume a uid and gid of a setid binary for which
3838 * we have no mapping in our user namespace.
3842 log_stderr("failure: fork");
3846 char expected_euid[100];
3847 char expected_egid[100];
3848 static char *envp[4] = {
3854 static char *argv[] = {
3858 if (!switch_userns(attr.userns_fd, 0, 0, false))
3859 die("failure: switch_userns");
3861 envp[0] = "IDMAP_MOUNT_TEST_RUN_SETID=0";
3862 snprintf(expected_euid, sizeof(expected_euid), "EXPECTED_EUID=%d", geteuid());
3863 envp[1] = expected_euid;
3864 snprintf(expected_egid, sizeof(expected_egid), "EXPECTED_EGID=%d", getegid());
3865 envp[2] = expected_egid;
3867 if (!expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid))
3868 die("failure: expected_uid_gid");
3870 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3871 die("failure: sys_execveat");
3876 if (wait_for_pid(pid)) {
3877 log_stderr("failure: wait_for_pid");
3882 log_debug("Ran test");
3884 safe_close(attr.userns_fd);
3885 safe_close(exec_fd);
3886 safe_close(file1_fd);
3887 safe_close(open_tree_fd);
3889 snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
3890 sys_umount2(t_buf, MNT_DETACH);
3891 rm_r(t_mnt_fd, DIR1);
3896 /* Validate that setid transitions are handled correctly on idmapped mounts
3897 * running in a user namespace where the uid and gid of the setid binary have no
3900 static int setid_binaries_idmapped_mounts_in_userns_separate_userns(void)
3903 int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3904 struct mount_attr attr = {
3905 .attr_set = MOUNT_ATTR_IDMAP,
3909 if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3910 log_stderr("failure: mkdirat");
3914 /* create a file to be used as setuid binary */
3915 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3917 log_stderr("failure: openat");
3921 /* open our own executable */
3922 exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3924 log_stderr("failure: openat");
3928 /* copy our own executable into the file we created */
3929 if (fd_to_fd(exec_fd, file1_fd)) {
3930 log_stderr("failure: fd_to_fd");
3934 safe_close(exec_fd);
3936 /* change ownership of all files to uid 0 */
3937 if (chown_r(t_mnt_fd, T_DIR1, 20000, 20000)) {
3938 log_stderr("failure: chown_r");
3942 /* chown the file to the uid and gid we want to assume */
3943 if (fchown(file1_fd, 25000, 25000)) {
3944 log_stderr("failure: fchown");
3948 /* set the setid bits and grant execute permissions to the group */
3949 if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3950 log_stderr("failure: fchmod");
3954 /* Verify that the sid bits got raised. */
3955 if (!is_setid(t_dir1_fd, FILE1, 0)) {
3956 log_stderr("failure: is_setid");
3960 safe_close(file1_fd);
3962 /* Changing mount properties on a detached mount. */
3963 attr.userns_fd = get_userns_fd(20000, 10000, 10000);
3964 if (attr.userns_fd < 0) {
3965 log_stderr("failure: get_userns_fd");
3969 open_tree_fd = sys_open_tree(t_dir1_fd, "",
3972 AT_SYMLINK_NOFOLLOW |
3975 if (open_tree_fd < 0) {
3976 log_stderr("failure: sys_open_tree");
3980 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3981 log_stderr("failure: sys_mount_setattr");
3985 /* A detached mount will have an anonymous mount namespace attached to
3986 * it. This means that we can't execute setid binaries on a detached
3987 * mount because the mnt_may_suid() helper will fail the check_mount()
3988 * part of its check which compares the caller's mount namespace to the
3989 * detached mount's mount namespace. Since by definition an anonymous
3990 * mount namespace is not equale to any mount namespace currently in
3991 * use this can't work. So attach the mount to the filesystem first
3992 * before performing this check.
3994 if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3995 log_stderr("failure: sys_move_mount");
4001 log_stderr("failure: fork");
4006 static char *envp[] = {
4007 "IDMAP_MOUNT_TEST_RUN_SETID=1",
4008 "EXPECTED_EUID=5000",
4009 "EXPECTED_EGID=5000",
4012 static char *argv[] = {
4016 userns_fd = get_userns_fd(0, 10000, 10000);
4018 die("failure: get_userns_fd");
4020 if (!switch_userns(userns_fd, 0, 0, false))
4021 die("failure: switch_userns");
4023 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 5000, 5000))
4024 die("failure: expected_uid_gid");
4026 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4027 die("failure: sys_execveat");
4032 if (wait_for_pid(pid)) {
4033 log_stderr("failure: wait_for_pid");
4037 file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
4039 log_stderr("failure: openat");
4043 /* chown the file to the uid and gid we want to assume */
4044 if (fchown(file1_fd, 20000, 20000)) {
4045 log_stderr("failure: fchown");
4049 /* set the setid bits and grant execute permissions to the group */
4050 if (fchmod(file1_fd, S_IXOTH | S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
4051 log_stderr("failure: fchmod");
4055 /* Verify that the sid bits got raised. */
4056 if (!is_setid(t_dir1_fd, FILE1, 0)) {
4057 log_stderr("failure: is_setid");
4061 safe_close(file1_fd);
4065 log_stderr("failure: fork");
4070 static char *envp[] = {
4071 "IDMAP_MOUNT_TEST_RUN_SETID=1",
4076 static char *argv[] = {
4080 userns_fd = get_userns_fd(0, 10000, 10000);
4082 die("failure: get_userns_fd");
4084 if (!caps_supported()) {
4085 log_debug("skip: capability library not installed");
4089 if (!switch_userns(userns_fd, 1000, 1000, true))
4090 die("failure: switch_userns");
4092 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
4093 die("failure: expected_uid_gid");
4095 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4096 die("failure: sys_execveat");
4100 if (wait_for_pid(pid)) {
4101 log_stderr("failure: wait_for_pid");
4105 file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
4107 log_stderr("failure: openat");
4111 /* chown the file to the uid and gid we want to assume */
4112 if (fchown(file1_fd, 0, 0)) {
4113 log_stderr("failure: fchown");
4117 if (fchmod(file1_fd, S_IXOTH | S_IEXEC | S_ISUID | S_ISGID), 0) {
4118 log_stderr("failure: fchmod");
4122 /* Verify that the sid bits got raised. */
4123 if (!is_setid(t_dir1_fd, FILE1, 0)) {
4124 log_stderr("failure: is_setid");
4128 safe_close(file1_fd);
4130 /* Verify that we can't assume a uid and gid of a setid binary for
4131 * which we have no mapping in our user namespace.
4135 log_stderr("failure: fork");
4140 char expected_euid[100];
4141 char expected_egid[100];
4142 static char *envp[4] = {
4148 static char *argv[] = {
4152 userns_fd = get_userns_fd(0, 10000, 10000);
4154 die("failure: get_userns_fd");
4156 if (!switch_userns(userns_fd, 0, 0, false))
4157 die("failure: switch_userns");
4159 envp[0] = "IDMAP_MOUNT_TEST_RUN_SETID=0";
4160 snprintf(expected_euid, sizeof(expected_euid), "EXPECTED_EUID=%d", geteuid());
4161 envp[1] = expected_euid;
4162 snprintf(expected_egid, sizeof(expected_egid), "EXPECTED_EGID=%d", getegid());
4163 envp[2] = expected_egid;
4165 if (!expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid))
4166 die("failure: expected_uid_gid");
4168 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4169 die("failure: sys_execveat");
4173 if (wait_for_pid(pid)) {
4174 log_stderr("failure: wait_for_pid");
4179 log_debug("Ran test");
4181 safe_close(attr.userns_fd);
4182 safe_close(exec_fd);
4183 safe_close(file1_fd);
4184 safe_close(open_tree_fd);
4186 snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
4187 sys_umount2(t_buf, MNT_DETACH);
4188 rm_r(t_mnt_fd, DIR1);
4193 static int sticky_bit_unlink(void)
4196 int dir_fd = -EBADF;
4199 if (!caps_supported())
4202 /* create directory */
4203 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4204 log_stderr("failure: mkdirat");
4208 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4210 log_stderr("failure: openat");
4214 if (fchown(dir_fd, 0, 0)) {
4215 log_stderr("failure: fchown");
4219 if (fchmod(dir_fd, 0777)) {
4220 log_stderr("failure: fchmod");
4224 /* create regular file via mknod */
4225 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4226 log_stderr("failure: mknodat");
4229 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4230 log_stderr("failure: fchownat");
4233 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4234 log_stderr("failure: fchmodat");
4238 /* create regular file via mknod */
4239 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4240 log_stderr("failure: mknodat");
4243 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4244 log_stderr("failure: fchownat");
4247 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4248 log_stderr("failure: fchmodat");
4252 /* The sticky bit is not set so we must be able to delete files not
4257 log_stderr("failure: fork");
4261 if (!switch_ids(1000, 1000))
4262 die("failure: switch_ids");
4264 if (unlinkat(dir_fd, FILE1, 0))
4265 die("failure: unlinkat");
4267 if (unlinkat(dir_fd, FILE2, 0))
4268 die("failure: unlinkat");
4272 if (wait_for_pid(pid)) {
4273 log_stderr("failure: wait_for_pid");
4277 /* set sticky bit */
4278 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4279 log_stderr("failure: fchmod");
4283 /* validate sticky bit is set */
4284 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4285 log_stderr("failure: is_sticky");
4289 /* create regular file via mknod */
4290 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4291 log_stderr("failure: mknodat");
4294 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4295 log_stderr("failure: fchownat");
4298 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4299 log_stderr("failure: fchmodat");
4303 /* create regular file via mknod */
4304 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4305 log_stderr("failure: mknodat");
4308 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4309 log_stderr("failure: fchownat");
4312 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4313 log_stderr("failure: fchmodat");
4317 /* The sticky bit is set so we must not be able to delete files not
4322 log_stderr("failure: fork");
4326 if (!switch_ids(1000, 1000))
4327 die("failure: switch_ids");
4329 if (!unlinkat(dir_fd, FILE1, 0))
4330 die("failure: unlinkat");
4332 die("failure: errno");
4334 if (!unlinkat(dir_fd, FILE2, 0))
4335 die("failure: unlinkat");
4337 die("failure: errno");
4341 if (wait_for_pid(pid)) {
4342 log_stderr("failure: wait_for_pid");
4346 /* The sticky bit is set and we own the files so we must be able to
4347 * delete the files now.
4351 log_stderr("failure: fork");
4355 /* change ownership */
4356 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
4357 die("failure: fchownat");
4358 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
4359 die("failure: expected_uid_gid");
4360 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
4361 die("failure: fchownat");
4362 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
4363 die("failure: expected_uid_gid");
4365 if (!switch_ids(1000, 1000))
4366 die("failure: switch_ids");
4368 if (unlinkat(dir_fd, FILE1, 0))
4369 die("failure: unlinkat");
4371 if (unlinkat(dir_fd, FILE2, 0))
4372 die("failure: unlinkat");
4376 if (wait_for_pid(pid)) {
4377 log_stderr("failure: wait_for_pid");
4381 /* change uid to unprivileged user */
4382 if (fchown(dir_fd, 1000, -1)) {
4383 log_stderr("failure: fchown");
4386 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4387 log_stderr("failure: fchmod");
4390 /* validate sticky bit is set */
4391 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4392 log_stderr("failure: is_sticky");
4396 /* create regular file via mknod */
4397 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4398 log_stderr("failure: mknodat");
4401 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4402 log_stderr("failure: fchownat");
4405 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4406 log_stderr("failure: fchmodat");
4410 /* create regular file via mknod */
4411 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4412 log_stderr("failure: mknodat");
4415 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4416 log_stderr("failure: fchownat");
4419 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4420 log_stderr("failure: fchmodat");
4424 /* The sticky bit is set and we own the directory so we must be able to
4425 * delete the files now.
4429 log_stderr("failure: fork");
4433 if (!switch_ids(1000, 1000))
4434 die("failure: switch_ids");
4436 if (unlinkat(dir_fd, FILE1, 0))
4437 die("failure: unlinkat");
4439 if (unlinkat(dir_fd, FILE2, 0))
4440 die("failure: unlinkat");
4444 if (wait_for_pid(pid)) {
4445 log_stderr("failure: wait_for_pid");
4450 log_debug("Ran test");
4457 static int sticky_bit_unlink_idmapped_mounts(void)
4460 int dir_fd = -EBADF, open_tree_fd = -EBADF;
4461 struct mount_attr attr = {
4462 .attr_set = MOUNT_ATTR_IDMAP,
4466 if (!caps_supported())
4469 /* create directory */
4470 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4471 log_stderr("failure: mkdirat");
4475 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4477 log_stderr("failure: openat");
4480 if (fchown(dir_fd, 10000, 10000)) {
4481 log_stderr("failure: fchown");
4484 if (fchmod(dir_fd, 0777)) {
4485 log_stderr("failure: fchmod");
4489 /* create regular file via mknod */
4490 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4491 log_stderr("failure: mknodat");
4494 if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4495 log_stderr("failure: fchownat");
4498 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4499 log_stderr("failure: fchmodat");
4503 /* create regular file via mknod */
4504 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4505 log_stderr("failure: mknodat");
4508 if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4509 log_stderr("failure: fchownat");
4512 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4513 log_stderr("failure: fchmodat");
4517 /* Changing mount properties on a detached mount. */
4518 attr.userns_fd = get_userns_fd(10000, 0, 10000);
4519 if (attr.userns_fd < 0) {
4520 log_stderr("failure: get_userns_fd");
4524 open_tree_fd = sys_open_tree(dir_fd, "",
4527 AT_SYMLINK_NOFOLLOW |
4530 if (open_tree_fd < 0) {
4531 log_stderr("failure: sys_open_tree");
4535 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
4536 log_stderr("failure: sys_mount_setattr");
4540 /* The sticky bit is not set so we must be able to delete files not
4545 log_stderr("failure: fork");
4549 if (!switch_ids(1000, 1000))
4550 die("failure: switch_ids");
4552 if (unlinkat(open_tree_fd, FILE1, 0))
4553 die("failure: unlinkat");
4555 if (unlinkat(open_tree_fd, FILE2, 0))
4556 die("failure: unlinkat");
4560 if (wait_for_pid(pid)) {
4561 log_stderr("failure: wait_for_pid");
4565 /* set sticky bit */
4566 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4567 log_stderr("failure: fchmod");
4571 /* validate sticky bit is set */
4572 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4573 log_stderr("failure: is_sticky");
4577 /* create regular file via mknod */
4578 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4579 log_stderr("failure: mknodat");
4582 if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4583 log_stderr("failure: fchownat");
4586 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4587 log_stderr("failure: fchmodat");
4591 /* create regular file via mknod */
4592 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4593 log_stderr("failure: mknodat");
4596 if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4597 log_stderr("failure: fchownat");
4600 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4601 log_stderr("failure: fchmodat");
4605 /* The sticky bit is set so we must not be able to delete files not
4610 log_stderr("failure: fork");
4614 if (!switch_ids(1000, 1000))
4615 die("failure: switch_ids");
4617 if (!unlinkat(open_tree_fd, FILE1, 0))
4618 die("failure: unlinkat");
4620 die("failure: errno");
4622 if (!unlinkat(open_tree_fd, FILE2, 0))
4623 die("failure: unlinkat");
4625 die("failure: errno");
4629 if (wait_for_pid(pid)) {
4630 log_stderr("failure: wait_for_pid");
4634 /* The sticky bit is set and we own the files so we must be able to
4635 * delete the files now.
4639 log_stderr("failure: fork");
4643 /* change ownership */
4644 if (fchownat(dir_fd, FILE1, 11000, -1, 0))
4645 die("failure: fchownat");
4646 if (!expected_uid_gid(dir_fd, FILE1, 0, 11000, 10000))
4647 die("failure: expected_uid_gid");
4648 if (fchownat(dir_fd, FILE2, 11000, -1, 0))
4649 die("failure: fchownat");
4650 if (!expected_uid_gid(dir_fd, FILE2, 0, 11000, 12000))
4651 die("failure: expected_uid_gid");
4653 if (!switch_ids(1000, 1000))
4654 die("failure: switch_ids");
4656 if (unlinkat(open_tree_fd, FILE1, 0))
4657 die("failure: unlinkat");
4659 if (unlinkat(open_tree_fd, FILE2, 0))
4660 die("failure: unlinkat");
4664 if (wait_for_pid(pid)) {
4665 log_stderr("failure: wait_for_pid");
4669 /* change uid to unprivileged user */
4670 if (fchown(dir_fd, 11000, -1)) {
4671 log_stderr("failure: fchown");
4674 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4675 log_stderr("failure: fchmod");
4678 /* validate sticky bit is set */
4679 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4680 log_stderr("failure: is_sticky");
4684 /* create regular file via mknod */
4685 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4686 log_stderr("failure: mknodat");
4689 if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4690 log_stderr("failure: fchownat");
4693 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4694 log_stderr("failure: fchmodat");
4698 /* create regular file via mknod */
4699 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4700 log_stderr("failure: mknodat");
4703 if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4704 log_stderr("failure: fchownat");
4707 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4708 log_stderr("failure: fchmodat");
4712 /* The sticky bit is set and we own the directory so we must be able to
4713 * delete the files now.
4717 log_stderr("failure: fork");
4721 if (!switch_ids(1000, 1000))
4722 die("failure: switch_ids");
4724 if (unlinkat(open_tree_fd, FILE1, 0))
4725 die("failure: unlinkat");
4727 if (unlinkat(open_tree_fd, FILE2, 0))
4728 die("failure: unlinkat");
4732 if (wait_for_pid(pid)) {
4733 log_stderr("failure: wait_for_pid");
4738 log_debug("Ran test");
4740 safe_close(attr.userns_fd);
4742 safe_close(open_tree_fd);
4747 /* Validate that the sticky bit behaves correctly on idmapped mounts for unlink
4748 * operations in a user namespace.
4750 static int sticky_bit_unlink_idmapped_mounts_in_userns(void)
4753 int dir_fd = -EBADF, open_tree_fd = -EBADF;
4754 struct mount_attr attr = {
4755 .attr_set = MOUNT_ATTR_IDMAP,
4759 if (!caps_supported())
4762 /* create directory */
4763 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4764 log_stderr("failure: mkdirat");
4768 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4770 log_stderr("failure: openat");
4773 if (fchown(dir_fd, 0, 0)) {
4774 log_stderr("failure: fchown");
4777 if (fchmod(dir_fd, 0777)) {
4778 log_stderr("failure: fchmod");
4782 /* create regular file via mknod */
4783 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4784 log_stderr("failure: mknodat");
4787 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4788 log_stderr("failure: fchownat");
4791 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4792 log_stderr("failure: fchmodat");
4796 /* create regular file via mknod */
4797 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4798 log_stderr("failure: mknodat");
4801 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4802 log_stderr("failure: fchownat");
4805 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4806 log_stderr("failure: fchmodat");
4810 /* Changing mount properties on a detached mount. */
4811 attr.userns_fd = get_userns_fd(0, 10000, 10000);
4812 if (attr.userns_fd < 0) {
4813 log_stderr("failure: get_userns_fd");
4817 open_tree_fd = sys_open_tree(dir_fd, "",
4820 AT_SYMLINK_NOFOLLOW |
4823 if (open_tree_fd < 0) {
4824 log_stderr("failure: sys_open_tree");
4828 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
4829 log_stderr("failure: sys_mount_setattr");
4833 /* The sticky bit is not set so we must be able to delete files not
4838 log_stderr("failure: fork");
4842 if (!caps_supported()) {
4843 log_debug("skip: capability library not installed");
4847 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4848 die("failure: switch_userns");
4850 if (unlinkat(dir_fd, FILE1, 0))
4851 die("failure: unlinkat");
4853 if (unlinkat(dir_fd, FILE2, 0))
4854 die("failure: unlinkat");
4858 if (wait_for_pid(pid)) {
4859 log_stderr("failure: wait_for_pid");
4863 /* set sticky bit */
4864 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4865 log_stderr("failure: fchmod");
4869 /* validate sticky bit is set */
4870 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4871 log_stderr("failure: is_sticky");
4875 /* create regular file via mknod */
4876 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4877 log_stderr("failure: mknodat");
4880 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4881 log_stderr("failure: fchownat");
4884 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4885 log_stderr("failure: fchmodat");
4889 /* create regular file via mknod */
4890 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4891 log_stderr("failure: mknodat");
4894 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4895 log_stderr("failure: fchownat");
4898 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4899 log_stderr("failure: fchmodat");
4903 /* The sticky bit is set so we must not be able to delete files not
4908 log_stderr("failure: fork");
4912 if (!caps_supported()) {
4913 log_debug("skip: capability library not installed");
4917 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4918 die("failure: switch_userns");
4920 if (!unlinkat(dir_fd, FILE1, 0))
4921 die("failure: unlinkat");
4923 die("failure: errno");
4925 if (!unlinkat(dir_fd, FILE2, 0))
4926 die("failure: unlinkat");
4928 die("failure: errno");
4930 if (!unlinkat(open_tree_fd, FILE1, 0))
4931 die("failure: unlinkat");
4933 die("failure: errno");
4935 if (!unlinkat(open_tree_fd, FILE2, 0))
4936 die("failure: unlinkat");
4938 die("failure: errno");
4942 if (wait_for_pid(pid)) {
4943 log_stderr("failure: wait_for_pid");
4947 /* The sticky bit is set and we own the files so we must be able to
4948 * delete the files now.
4952 log_stderr("failure: fork");
4956 /* change ownership */
4957 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
4958 die("failure: fchownat");
4959 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
4960 die("failure: expected_uid_gid");
4961 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
4962 die("failure: fchownat");
4963 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
4964 die("failure: expected_uid_gid");
4966 if (!caps_supported()) {
4967 log_debug("skip: capability library not installed");
4971 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4972 die("failure: switch_userns");
4974 if (!unlinkat(dir_fd, FILE1, 0))
4975 die("failure: unlinkat");
4977 die("failure: errno");
4979 if (!unlinkat(dir_fd, FILE2, 0))
4980 die("failure: unlinkat");
4982 die("failure: errno");
4984 if (unlinkat(open_tree_fd, FILE1, 0))
4985 die("failure: unlinkat");
4987 if (unlinkat(open_tree_fd, FILE2, 0))
4988 die("failure: unlinkat");
4992 if (wait_for_pid(pid)) {
4993 log_stderr("failure: wait_for_pid");
4997 /* change uid to unprivileged user */
4998 if (fchown(dir_fd, 1000, -1)) {
4999 log_stderr("failure: fchown");
5002 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5003 log_stderr("failure: fchmod");
5006 /* validate sticky bit is set */
5007 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5008 log_stderr("failure: is_sticky");
5012 /* create regular file via mknod */
5013 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5014 log_stderr("failure: mknodat");
5017 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5018 log_stderr("failure: fchownat");
5021 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5022 log_stderr("failure: fchmodat");
5026 /* create regular file via mknod */
5027 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5028 log_stderr("failure: mknodat");
5031 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5032 log_stderr("failure: fchownat");
5035 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5036 log_stderr("failure: fchmodat");
5040 /* The sticky bit is set and we own the directory so we must be able to
5041 * delete the files now.
5045 log_stderr("failure: fork");
5049 if (!caps_supported()) {
5050 log_debug("skip: capability library not installed");
5054 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5055 die("failure: switch_userns");
5057 /* we don't own the directory from the original mount */
5058 if (!unlinkat(dir_fd, FILE1, 0))
5059 die("failure: unlinkat");
5061 die("failure: errno");
5063 if (!unlinkat(dir_fd, FILE2, 0))
5064 die("failure: unlinkat");
5066 die("failure: errno");
5068 /* we own the file from the idmapped mount */
5069 if (unlinkat(open_tree_fd, FILE1, 0))
5070 die("failure: unlinkat");
5071 if (unlinkat(open_tree_fd, FILE2, 0))
5072 die("failure: unlinkat");
5076 if (wait_for_pid(pid)) {
5077 log_stderr("failure: wait_for_pid");
5082 log_debug("Ran test");
5084 safe_close(attr.userns_fd);
5086 safe_close(open_tree_fd);
5091 static int sticky_bit_rename(void)
5094 int dir_fd = -EBADF;
5097 if (!caps_supported())
5100 /* create directory */
5101 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5102 log_stderr("failure: mkdirat");
5106 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5108 log_stderr("failure: openat");
5111 if (fchown(dir_fd, 0, 0)) {
5112 log_stderr("failure: fchown");
5115 if (fchmod(dir_fd, 0777)) {
5116 log_stderr("failure: fchmod");
5120 /* create regular file via mknod */
5121 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5122 log_stderr("failure: mknodat");
5125 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5126 log_stderr("failure: fchownat");
5129 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5130 log_stderr("failure: fchmodat");
5134 /* create regular file via mknod */
5135 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5136 log_stderr("failure: mknodat");
5139 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5140 log_stderr("failure: fchownat");
5143 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5144 log_stderr("failure: fchmodat");
5148 /* The sticky bit is not set so we must be able to delete files not
5153 log_stderr("failure: fork");
5157 if (!switch_ids(1000, 1000))
5158 die("failure: switch_ids");
5160 if (renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5161 die("failure: renameat2");
5163 if (renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5164 die("failure: renameat2");
5166 if (renameat2(dir_fd, FILE1_RENAME, dir_fd, FILE1, 0))
5167 die("failure: renameat2");
5169 if (renameat2(dir_fd, FILE2_RENAME, dir_fd, FILE2, 0))
5170 die("failure: renameat2");
5174 if (wait_for_pid(pid)) {
5175 log_stderr("failure: wait_for_pid");
5179 /* set sticky bit */
5180 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5181 log_stderr("failure: fchmod");
5185 /* validate sticky bit is set */
5186 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5187 log_stderr("failure: is_sticky");
5191 /* The sticky bit is set so we must not be able to delete files not
5196 log_stderr("failure: fork");
5200 if (!switch_ids(1000, 1000))
5201 die("failure: switch_ids");
5203 if (!renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5204 die("failure: renameat2");
5206 die("failure: errno");
5208 if (!renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5209 die("failure: renameat2");
5211 die("failure: errno");
5215 if (wait_for_pid(pid)) {
5216 log_stderr("failure: wait_for_pid");
5220 /* The sticky bit is set and we own the files so we must be able to
5221 * delete the files now.
5225 log_stderr("failure: fork");
5229 /* change ownership */
5230 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
5231 die("failure: fchownat");
5232 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
5233 die("failure: expected_uid_gid");
5234 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
5235 die("failure: fchownat");
5236 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
5237 die("failure: expected_uid_gid");
5239 if (!switch_ids(1000, 1000))
5240 die("failure: switch_ids");
5242 if (renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5243 die("failure: renameat2");
5245 if (renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5246 die("failure: renameat2");
5248 if (renameat2(dir_fd, FILE1_RENAME, dir_fd, FILE1, 0))
5249 die("failure: renameat2");
5251 if (renameat2(dir_fd, FILE2_RENAME, dir_fd, FILE2, 0))
5252 die("failure: renameat2");
5256 if (wait_for_pid(pid)) {
5257 log_stderr("failure: wait_for_pid");
5261 /* change uid to unprivileged user */
5262 if (fchown(dir_fd, 1000, -1)) {
5263 log_stderr("failure: fchown");
5266 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5267 log_stderr("failure: fchmod");
5270 /* validate sticky bit is set */
5271 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5272 log_stderr("failure: is_sticky");
5277 /* The sticky bit is set and we own the directory so we must be able to
5278 * delete the files now.
5282 log_stderr("failure: fork");
5286 if (!switch_ids(1000, 1000))
5287 die("failure: switch_ids");
5289 if (renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5290 die("failure: renameat2");
5292 if (renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5293 die("failure: renameat2");
5295 if (renameat2(dir_fd, FILE1_RENAME, dir_fd, FILE1, 0))
5296 die("failure: renameat2");
5298 if (renameat2(dir_fd, FILE2_RENAME, dir_fd, FILE2, 0))
5299 die("failure: renameat2");
5303 if (wait_for_pid(pid)) {
5304 log_stderr("failure: wait_for_pid");
5309 log_debug("Ran test");
5316 static int sticky_bit_rename_idmapped_mounts(void)
5319 int dir_fd = -EBADF, open_tree_fd = -EBADF;
5320 struct mount_attr attr = {
5321 .attr_set = MOUNT_ATTR_IDMAP,
5325 if (!caps_supported())
5328 /* create directory */
5329 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5330 log_stderr("failure: mkdirat");
5334 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5336 log_stderr("failure: openat");
5340 if (fchown(dir_fd, 10000, 10000)) {
5341 log_stderr("failure: fchown");
5345 if (fchmod(dir_fd, 0777)) {
5346 log_stderr("failure: fchmod");
5350 /* create regular file via mknod */
5351 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5352 log_stderr("failure: mknodat");
5355 if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
5356 log_stderr("failure: fchownat");
5359 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5360 log_stderr("failure: fchmodat");
5364 /* create regular file via mknod */
5365 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5366 log_stderr("failure: mknodat");
5369 if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
5370 log_stderr("failure: fchownat");
5373 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5374 log_stderr("failure: fchmodat");
5378 /* Changing mount properties on a detached mount. */
5379 attr.userns_fd = get_userns_fd(10000, 0, 10000);
5380 if (attr.userns_fd < 0) {
5381 log_stderr("failure: get_userns_fd");
5385 open_tree_fd = sys_open_tree(dir_fd, "",
5388 AT_SYMLINK_NOFOLLOW |
5391 if (open_tree_fd < 0) {
5392 log_stderr("failure: sys_open_tree");
5396 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
5397 log_stderr("failure: sys_mount_setattr");
5401 /* The sticky bit is not set so we must be able to delete files not
5406 log_stderr("failure: fork");
5410 if (!switch_ids(1000, 1000))
5411 die("failure: switch_ids");
5413 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5414 die("failure: renameat2");
5416 if (renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5417 die("failure: renameat2");
5419 if (renameat2(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1, 0))
5420 die("failure: renameat2");
5422 if (renameat2(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2, 0))
5423 die("failure: renameat2");
5427 if (wait_for_pid(pid)) {
5428 log_stderr("failure: wait_for_pid");
5432 /* set sticky bit */
5433 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5434 log_stderr("failure: fchmod");
5438 /* validate sticky bit is set */
5439 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5440 log_stderr("failure: is_sticky");
5444 /* The sticky bit is set so we must not be able to delete files not
5449 log_stderr("failure: fork");
5453 if (!switch_ids(1000, 1000))
5454 die("failure: switch_ids");
5456 if (!renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5457 die("failure: renameat2");
5459 die("failure: errno");
5461 if (!renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5462 die("failure: renameat2");
5464 die("failure: errno");
5468 if (wait_for_pid(pid)) {
5469 log_stderr("failure: wait_for_pid");
5473 /* The sticky bit is set and we own the files so we must be able to
5474 * delete the files now.
5478 log_stderr("failure: fork");
5482 /* change ownership */
5483 if (fchownat(dir_fd, FILE1, 11000, -1, 0))
5484 die("failure: fchownat");
5485 if (!expected_uid_gid(dir_fd, FILE1, 0, 11000, 10000))
5486 die("failure: expected_uid_gid");
5487 if (fchownat(dir_fd, FILE2, 11000, -1, 0))
5488 die("failure: fchownat");
5489 if (!expected_uid_gid(dir_fd, FILE2, 0, 11000, 12000))
5490 die("failure: expected_uid_gid");
5492 if (!switch_ids(1000, 1000))
5493 die("failure: switch_ids");
5495 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5496 die("failure: renameat2");
5498 if (renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5499 die("failure: renameat2");
5501 if (renameat2(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1, 0))
5502 die("failure: renameat2");
5504 if (renameat2(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2, 0))
5505 die("failure: renameat2");
5509 if (wait_for_pid(pid)) {
5510 log_stderr("failure: wait_for_pid");
5514 /* change uid to unprivileged user */
5515 if (fchown(dir_fd, 11000, -1)) {
5516 log_stderr("failure: fchown");
5519 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5520 log_stderr("failure: fchmod");
5523 /* validate sticky bit is set */
5524 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5525 log_stderr("failure: is_sticky");
5529 /* The sticky bit is set and we own the directory so we must be able to
5530 * delete the files now.
5534 log_stderr("failure: fork");
5538 if (!switch_ids(1000, 1000))
5539 die("failure: switch_ids");
5541 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5542 die("failure: renameat2");
5544 if (renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5545 die("failure: renameat2");
5547 if (renameat2(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1, 0))
5548 die("failure: renameat2");
5550 if (renameat2(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2, 0))
5551 die("failure: renameat2");
5555 if (wait_for_pid(pid)) {
5556 log_stderr("failure: wait_for_pid");
5561 log_debug("Ran test");
5563 safe_close(attr.userns_fd);
5565 safe_close(open_tree_fd);
5570 /* Validate that the sticky bit behaves correctly on idmapped mounts for unlink
5571 * operations in a user namespace.
5573 static int sticky_bit_rename_idmapped_mounts_in_userns(void)
5576 int dir_fd = -EBADF, open_tree_fd = -EBADF;
5577 struct mount_attr attr = {
5578 .attr_set = MOUNT_ATTR_IDMAP,
5582 if (!caps_supported())
5585 /* create directory */
5586 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5587 log_stderr("failure: mkdirat");
5591 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5593 log_stderr("failure: openat");
5596 if (fchown(dir_fd, 0, 0)) {
5597 log_stderr("failure: fchown");
5600 if (fchmod(dir_fd, 0777)) {
5601 log_stderr("failure: fchmod");
5605 /* create regular file via mknod */
5606 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5607 log_stderr("failure: mknodat");
5610 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5611 log_stderr("failure: fchownat");
5614 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5615 log_stderr("failure: fchmodat");
5619 /* create regular file via mknod */
5620 if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5621 log_stderr("failure: mknodat");
5624 if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5625 log_stderr("failure: fchownat");
5628 if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5629 log_stderr("failure: fchmodat");
5633 /* Changing mount properties on a detached mount. */
5634 attr.userns_fd = get_userns_fd(0, 10000, 10000);
5635 if (attr.userns_fd < 0) {
5636 log_stderr("failure: get_userns_fd");
5640 open_tree_fd = sys_open_tree(dir_fd, "",
5643 AT_SYMLINK_NOFOLLOW |
5646 if (open_tree_fd < 0) {
5647 log_stderr("failure: sys_open_tree");
5651 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
5652 log_stderr("failure: sys_mount_setattr");
5656 /* The sticky bit is not set so we must be able to delete files not
5661 log_stderr("failure: fork");
5665 if (!caps_supported()) {
5666 log_debug("skip: capability library not installed");
5670 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5671 die("failure: switch_userns");
5673 if (renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5674 die("failure: renameat2");
5676 if (renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5677 die("failure: renameat2");
5679 if (renameat2(dir_fd, FILE1_RENAME, dir_fd, FILE1, 0))
5680 die("failure: renameat2");
5682 if (renameat2(dir_fd, FILE2_RENAME, dir_fd, FILE2, 0))
5683 die("failure: renameat2");
5687 if (wait_for_pid(pid)) {
5688 log_stderr("failure: wait_for_pid");
5692 /* set sticky bit */
5693 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5694 log_stderr("failure: fchmod");
5698 /* validate sticky bit is set */
5699 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5700 log_stderr("failure: is_sticky");
5704 /* The sticky bit is set so we must not be able to delete files not
5709 log_stderr("failure: fork");
5713 if (!caps_supported()) {
5714 log_debug("skip: capability library not installed");
5718 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5719 die("failure: switch_userns");
5721 if (!renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5722 die("failure: renameat2");
5724 die("failure: errno");
5726 if (!renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5727 die("failure: renameat2");
5729 die("failure: errno");
5731 if (!renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5732 die("failure: renameat2");
5734 die("failure: errno");
5736 if (!renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5737 die("failure: renameat2");
5739 die("failure: errno");
5743 if (wait_for_pid(pid)) {
5744 log_stderr("failure: wait_for_pid");
5748 /* The sticky bit is set and we own the files so we must be able to
5749 * delete the files now.
5753 log_stderr("failure: fork");
5757 /* change ownership */
5758 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
5759 die("failure: fchownat");
5760 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
5761 die("failure: expected_uid_gid");
5762 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
5763 die("failure: fchownat");
5764 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
5765 die("failure: expected_uid_gid");
5767 if (!caps_supported()) {
5768 log_debug("skip: capability library not installed");
5772 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5773 die("failure: switch_userns");
5775 if (!renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5776 die("failure: renameat2");
5778 die("failure: errno");
5780 if (!renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5781 die("failure: renameat2");
5783 die("failure: errno");
5785 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5786 die("failure: renameat2");
5788 if (renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5789 die("failure: renameat2");
5791 if (renameat2(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1, 0))
5792 die("failure: renameat2");
5794 if (renameat2(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2, 0))
5795 die("failure: renameat2");
5799 if (wait_for_pid(pid)) {
5800 log_stderr("failure: wait_for_pid");
5804 /* change uid to unprivileged user */
5805 if (fchown(dir_fd, 1000, -1)) {
5806 log_stderr("failure: fchown");
5809 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5810 log_stderr("failure: fchmod");
5813 /* validate sticky bit is set */
5814 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5815 log_stderr("failure: is_sticky");
5819 /* The sticky bit is set and we own the directory so we must be able to
5820 * delete the files now.
5824 log_stderr("failure: fork");
5828 if (!caps_supported()) {
5829 log_debug("skip: capability library not installed");
5833 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5834 die("failure: switch_userns");
5836 /* we don't own the directory from the original mount */
5837 if (!renameat2(dir_fd, FILE1, dir_fd, FILE1_RENAME, 0))
5838 die("failure: renameat2");
5840 die("failure: errno");
5842 if (!renameat2(dir_fd, FILE2, dir_fd, FILE2_RENAME, 0))
5843 die("failure: renameat2");
5845 die("failure: errno");
5847 /* we own the file from the idmapped mount */
5848 if (renameat2(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME, 0))
5849 die("failure: renameat2");
5851 if (renameat2(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME, 0))
5852 die("failure: renameat2");
5854 if (renameat2(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1, 0))
5855 die("failure: renameat2");
5857 if (renameat2(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2, 0))
5858 die("failure: renameat2");
5862 if (wait_for_pid(pid)) {
5863 log_stderr("failure: wait_for_pid");
5868 log_debug("Ran test");
5870 safe_close(open_tree_fd);
5871 safe_close(attr.userns_fd);
5877 /* Validate that protected symlinks work correctly. */
5878 static int protected_symlinks(void)
5881 int dir_fd = -EBADF, fd = -EBADF;
5884 if (!protected_symlinks_enabled())
5887 if (!caps_supported())
5890 /* create directory */
5891 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5892 log_stderr("failure: mkdirat");
5896 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5898 log_stderr("failure: openat");
5901 if (fchown(dir_fd, 0, 0)) {
5902 log_stderr("failure: fchown");
5905 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5906 log_stderr("failure: fchmod");
5909 /* validate sticky bit is set */
5910 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5911 log_stderr("failure: is_sticky");
5915 /* create regular file via mknod */
5916 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5917 log_stderr("failure: mknodat");
5920 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5921 log_stderr("failure: fchownat");
5924 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5925 log_stderr("failure: fchmodat");
5929 /* create symlinks */
5930 if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
5931 log_stderr("failure: symlinkat");
5934 if (fchownat(dir_fd, SYMLINK_USER1, 0, 0, AT_SYMLINK_NOFOLLOW)) {
5935 log_stderr("failure: fchownat");
5938 if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
5939 log_stderr("failure: expected_uid_gid");
5942 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5943 log_stderr("failure: expected_uid_gid");
5947 if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
5948 log_stderr("failure: symlinkat");
5951 if (fchownat(dir_fd, SYMLINK_USER2, 1000, 1000, AT_SYMLINK_NOFOLLOW)) {
5952 log_stderr("failure: fchownat");
5955 if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 1000, 1000)) {
5956 log_stderr("failure: expected_uid_gid");
5959 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5960 log_stderr("failure: expected_uid_gid");
5964 if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
5965 log_stderr("failure: symlinkat");
5968 if (fchownat(dir_fd, SYMLINK_USER3, 2000, 2000, AT_SYMLINK_NOFOLLOW)) {
5969 log_stderr("failure: fchownat");
5972 if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
5973 log_stderr("failure: expected_uid_gid");
5976 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5977 log_stderr("failure: expected_uid_gid");
5981 /* validate file can be directly read */
5982 fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
5984 log_stderr("failure: openat");
5989 /* validate file can be read through own symlink */
5990 fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
5992 log_stderr("failure: openat");
5999 log_stderr("failure: fork");
6003 if (!switch_ids(1000, 1000))
6004 die("failure: switch_ids");
6006 /* validate file can be directly read */
6007 fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
6009 die("failure: openat");
6012 /* validate file can be read through own symlink */
6013 fd = openat(dir_fd, SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6015 die("failure: openat");
6018 /* validate file can be read through root symlink */
6019 fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6021 die("failure: openat");
6024 /* validate file can't be read through other users symlink */
6025 fd = openat(dir_fd, SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6027 die("failure: openat");
6028 if (errno != EACCES)
6029 die("failure: errno");
6033 if (wait_for_pid(pid)) {
6034 log_stderr("failure: wait_for_pid");
6040 log_stderr("failure: fork");
6044 if (!switch_ids(2000, 2000))
6045 die("failure: switch_ids");
6047 /* validate file can be directly read */
6048 fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
6050 die("failure: openat");
6053 /* validate file can be read through own symlink */
6054 fd = openat(dir_fd, SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6056 die("failure: openat");
6059 /* validate file can be read through root symlink */
6060 fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6062 die("failure: openat");
6065 /* validate file can't be read through other users symlink */
6066 fd = openat(dir_fd, SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6068 die("failure: openat");
6069 if (errno != EACCES)
6070 die("failure: errno");
6074 if (wait_for_pid(pid)) {
6075 log_stderr("failure: wait_for_pid");
6080 log_debug("Ran test");
6088 /* Validate that protected symlinks work correctly on idmapped mounts. */
6089 static int protected_symlinks_idmapped_mounts(void)
6092 int dir_fd = -EBADF, fd = -EBADF, open_tree_fd = -EBADF;
6093 struct mount_attr attr = {
6094 .attr_set = MOUNT_ATTR_IDMAP,
6098 if (!protected_symlinks_enabled())
6101 if (!caps_supported())
6104 /* create directory */
6105 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
6106 log_stderr("failure: mkdirat");
6110 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6112 log_stderr("failure: openat");
6115 if (fchown(dir_fd, 10000, 10000)) {
6116 log_stderr("failure: fchown");
6119 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
6120 log_stderr("failure: fchmod");
6123 /* validate sticky bit is set */
6124 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
6125 log_stderr("failure: is_sticky");
6129 /* create regular file via mknod */
6130 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
6131 log_stderr("failure: mknodat");
6134 if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
6135 log_stderr("failure: fchownat");
6138 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
6139 log_stderr("failure: fchmodat");
6143 /* create symlinks */
6144 if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
6145 log_stderr("failure: symlinkat");
6148 if (fchownat(dir_fd, SYMLINK_USER1, 10000, 10000, AT_SYMLINK_NOFOLLOW)) {
6149 log_stderr("failure: fchownat");
6152 if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 10000, 10000)) {
6153 log_stderr("failure: expected_uid_gid");
6156 if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6157 log_stderr("failure: expected_uid_gid");
6161 if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
6162 log_stderr("failure: symlinkat");
6165 if (fchownat(dir_fd, SYMLINK_USER2, 11000, 11000, AT_SYMLINK_NOFOLLOW)) {
6166 log_stderr("failure: fchownat");
6169 if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 11000, 11000)) {
6170 log_stderr("failure: expected_uid_gid");
6173 if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6174 log_stderr("failure: expected_uid_gid");
6178 if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
6179 log_stderr("failure: symlinkat");
6182 if (fchownat(dir_fd, SYMLINK_USER3, 12000, 12000, AT_SYMLINK_NOFOLLOW)) {
6183 log_stderr("failure: fchownat");
6186 if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
6187 log_stderr("failure: expected_uid_gid");
6190 if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6191 log_stderr("failure: expected_uid_gid");
6195 /* Changing mount properties on a detached mount. */
6196 attr.userns_fd = get_userns_fd(10000, 0, 10000);
6197 if (attr.userns_fd < 0) {
6198 log_stderr("failure: get_userns_fd");
6202 open_tree_fd = sys_open_tree(t_dir1_fd, "",
6205 AT_SYMLINK_NOFOLLOW |
6208 if (open_tree_fd < 0) {
6209 log_stderr("failure: open_tree_fd");
6213 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6214 log_stderr("failure: sys_mount_setattr");
6218 /* validate file can be directly read */
6219 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6221 log_stderr("failure: openat");
6226 /* validate file can be read through own symlink */
6227 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6229 log_stderr("failure: openat");
6236 log_stderr("failure: fork");
6240 if (!switch_ids(1000, 1000))
6241 die("failure: switch_ids");
6243 /* validate file can be directly read */
6244 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6246 die("failure: openat");
6249 /* validate file can be read through own symlink */
6250 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6252 die("failure: openat");
6255 /* validate file can be read through root symlink */
6256 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6258 die("failure: openat");
6261 /* validate file can't be read through other users symlink */
6262 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6264 die("failure: openat");
6265 if (errno != EACCES)
6266 die("failure: errno");
6270 if (wait_for_pid(pid)) {
6271 log_stderr("failure: wait_for_pid");
6277 log_stderr("failure: fork");
6281 if (!switch_ids(2000, 2000))
6282 die("failure: switch_ids");
6284 /* validate file can be directly read */
6285 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6287 die("failure: openat");
6290 /* validate file can be read through own symlink */
6291 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6293 die("failure: openat");
6296 /* validate file can be read through root symlink */
6297 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6299 die("failure: openat");
6302 /* validate file can't be read through other users symlink */
6303 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6305 die("failure: openat");
6306 if (errno != EACCES)
6307 die("failure: errno");
6311 if (wait_for_pid(pid)) {
6312 log_stderr("failure: wait_for_pid");
6317 log_debug("Ran test");
6319 safe_close(attr.userns_fd);
6322 safe_close(open_tree_fd);
6327 /* Validate that protected symlinks work correctly on idmapped mounts inside a
6330 static int protected_symlinks_idmapped_mounts_in_userns(void)
6333 int dir_fd = -EBADF, fd = -EBADF, open_tree_fd = -EBADF;
6334 struct mount_attr attr = {
6335 .attr_set = MOUNT_ATTR_IDMAP,
6339 if (!protected_symlinks_enabled())
6342 if (!caps_supported())
6345 /* create directory */
6346 if (mkdirat(t_dir1_fd, DIR1, 0000)) {
6347 log_stderr("failure: mkdirat");
6351 dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6353 log_stderr("failure: openat");
6356 if (fchown(dir_fd, 0, 0)) {
6357 log_stderr("failure: fchown");
6360 if (fchmod(dir_fd, 0777 | S_ISVTX)) {
6361 log_stderr("failure: fchmod");
6364 /* validate sticky bit is set */
6365 if (!is_sticky(t_dir1_fd, DIR1, 0)) {
6366 log_stderr("failure: is_sticky");
6370 /* create regular file via mknod */
6371 if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
6372 log_stderr("failure: mknodat");
6375 if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
6376 log_stderr("failure: fchownat");
6379 if (fchmodat(dir_fd, FILE1, 0644, 0)) {
6380 log_stderr("failure: fchmodat");
6384 /* create symlinks */
6385 if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
6386 log_stderr("failure: symlinkat");
6389 if (fchownat(dir_fd, SYMLINK_USER1, 0, 0, AT_SYMLINK_NOFOLLOW)) {
6390 log_stderr("failure: fchownat");
6393 if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
6394 log_stderr("failure: expected_uid_gid");
6397 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6398 log_stderr("failure: expected_uid_gid");
6402 if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
6403 log_stderr("failure: symlinkat");
6406 if (fchownat(dir_fd, SYMLINK_USER2, 1000, 1000, AT_SYMLINK_NOFOLLOW)) {
6407 log_stderr("failure: fchownat");
6410 if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 1000, 1000)) {
6411 log_stderr("failure: expected_uid_gid");
6414 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6415 log_stderr("failure: expected_uid_gid");
6419 if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
6420 log_stderr("failure: symlinkat");
6423 if (fchownat(dir_fd, SYMLINK_USER3, 2000, 2000, AT_SYMLINK_NOFOLLOW)) {
6424 log_stderr("failure: fchownat");
6427 if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
6428 log_stderr("failure: expected_uid_gid");
6431 if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6432 log_stderr("failure: expected_uid_gid");
6436 /* Changing mount properties on a detached mount. */
6437 attr.userns_fd = get_userns_fd(0, 10000, 10000);
6438 if (attr.userns_fd < 0) {
6439 log_stderr("failure: get_userns_fd");
6443 open_tree_fd = sys_open_tree(t_dir1_fd, "",
6446 AT_SYMLINK_NOFOLLOW |
6449 if (open_tree_fd < 0) {
6450 log_stderr("failure: sys_open_tree");
6454 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6455 log_stderr("failure: sys_mount_setattr");
6459 /* validate file can be directly read */
6460 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6462 log_stderr("failure: openat");
6467 /* validate file can be read through own symlink */
6468 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6470 log_stderr("failure: openat");
6477 log_stderr("failure: fork");
6481 if (!caps_supported()) {
6482 log_debug("skip: capability library not installed");
6486 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
6487 die("failure: switch_userns");
6489 /* validate file can be directly read */
6490 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6492 die("failure: openat");
6495 /* validate file can be read through own symlink */
6496 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6498 die("failure: openat");
6501 /* validate file can be read through root symlink */
6502 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6504 die("failure: openat");
6507 /* validate file can't be read through other users symlink */
6508 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6510 die("failure: openat");
6511 if (errno != EACCES)
6512 die("failure: errno");
6516 if (wait_for_pid(pid)) {
6517 log_stderr("failure: wait_for_pid");
6523 log_stderr("failure: fork");
6527 if (!caps_supported()) {
6528 log_debug("skip: capability library not installed");
6532 if (!switch_userns(attr.userns_fd, 2000, 2000, true))
6533 die("failure: switch_userns");
6535 /* validate file can be directly read */
6536 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6538 die("failure: openat");
6541 /* validate file can be read through own symlink */
6542 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6544 die("failure: openat");
6547 /* validate file can be read through root symlink */
6548 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6550 die("failure: openat");
6553 /* validate file can't be read through other users symlink */
6554 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6556 die("failure: openat");
6557 if (errno != EACCES)
6558 die("failure: errno");
6562 if (wait_for_pid(pid)) {
6563 log_stderr("failure: wait_for_pid");
6568 log_debug("Ran test");
6571 safe_close(open_tree_fd);
6572 safe_close(attr.userns_fd);
6577 static int acls(void)
6580 int dir1_fd = -EBADF, open_tree_fd = -EBADF;
6581 struct mount_attr attr = {
6582 .attr_set = MOUNT_ATTR_IDMAP,
6586 if (mkdirat(t_dir1_fd, DIR1, 0777)) {
6587 log_stderr("failure: mkdirat");
6590 if (fchmodat(t_dir1_fd, DIR1, 0777, 0)) {
6591 log_stderr("failure: fchmodat");
6595 if (mkdirat(t_dir1_fd, DIR2, 0777)) {
6596 log_stderr("failure: mkdirat");
6599 if (fchmodat(t_dir1_fd, DIR2, 0777, 0)) {
6600 log_stderr("failure: fchmodat");
6604 /* Changing mount properties on a detached mount. */
6605 attr.userns_fd = get_userns_fd(100010, 100020, 5);
6606 if (attr.userns_fd < 0) {
6607 log_stderr("failure: get_userns_fd");
6611 open_tree_fd = sys_open_tree(t_dir1_fd, DIR1,
6613 AT_SYMLINK_NOFOLLOW |
6616 if (open_tree_fd < 0) {
6617 log_stderr("failure: sys_open_tree");
6621 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6622 log_stderr("failure: sys_mount_setattr");
6626 if (sys_move_mount(open_tree_fd, "", t_dir1_fd, DIR2, MOVE_MOUNT_F_EMPTY_PATH)) {
6627 log_stderr("failure: sys_move_mount");
6631 dir1_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6633 log_stderr("failure: openat");
6637 if (mkdirat(dir1_fd, DIR3, 0000)) {
6638 log_stderr("failure: mkdirat");
6641 if (fchown(dir1_fd, 100010, 100010)) {
6642 log_stderr("failure: fchown");
6645 if (fchmod(dir1_fd, 0777)) {
6646 log_stderr("failure: fchmod");
6650 snprintf(t_buf, sizeof(t_buf), "setfacl -m u:100010:rwx %s/%s/%s/%s", t_mountpoint, T_DIR1, DIR1, DIR3);
6651 if (system(t_buf)) {
6652 log_stderr("failure: system");
6656 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:100010:rwx", t_mountpoint, T_DIR1, DIR1, DIR3);
6657 if (system(t_buf)) {
6658 log_stderr("failure: system");
6662 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:100020:rwx", t_mountpoint, T_DIR1, DIR2, DIR3);
6663 if (system(t_buf)) {
6664 log_stderr("failure: system");
6670 log_stderr("failure: fork");
6674 if (!caps_supported()) {
6675 log_debug("skip: capability library not installed");
6679 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6680 die("failure: switch_userns");
6682 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:%lu:rwx",
6683 t_mountpoint, T_DIR1, DIR1, DIR3, 4294967295LU);
6685 die("failure: system");
6689 if (wait_for_pid(pid)) {
6690 log_stderr("failure: wait_for_pid");
6696 log_stderr("failure: fork");
6700 if (!caps_supported()) {
6701 log_debug("skip: capability library not installed");
6705 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6706 die("failure: switch_userns");
6708 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:%lu:rwx",
6709 t_mountpoint, T_DIR1, DIR2, DIR3, 100010LU);
6711 die("failure: system");
6715 if (wait_for_pid(pid)) {
6716 log_stderr("failure: wait_for_pid");
6720 /* Now, dir is owned by someone else in the user namespace, but we can
6721 * still read it because of acls.
6723 if (fchown(dir1_fd, 100012, 100012)) {
6724 log_stderr("failure: fchown");
6730 log_stderr("failure: fork");
6736 if (!caps_supported()) {
6737 log_debug("skip: capability library not installed");
6741 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6742 die("failure: switch_userns");
6744 fd = openat(open_tree_fd, DIR3, O_CLOEXEC | O_DIRECTORY);
6746 die("failure: openat");
6750 if (wait_for_pid(pid)) {
6751 log_stderr("failure: wait_for_pid");
6755 /* if we delete the acls, the ls should fail because it's 700. */
6756 snprintf(t_buf, sizeof(t_buf), "%s/%s/%s/%s", t_mountpoint, T_DIR1, DIR1, DIR3);
6757 if (removexattr(t_buf, "system.posix_acl_access")) {
6758 log_stderr("failure: removexattr");
6764 log_stderr("failure: fork");
6770 if (!caps_supported()) {
6771 log_debug("skip: capability library not installed");
6775 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6776 die("failure: switch_userns");
6778 fd = openat(open_tree_fd, DIR3, O_CLOEXEC | O_DIRECTORY);
6780 die("failure: openat");
6784 if (wait_for_pid(pid)) {
6785 log_stderr("failure: wait_for_pid");
6789 snprintf(t_buf, sizeof(t_buf), "%s/" T_DIR1 "/" DIR2, t_mountpoint);
6790 sys_umount2(t_buf, MNT_DETACH);
6793 log_debug("Ran test");
6795 safe_close(attr.userns_fd);
6796 safe_close(dir1_fd);
6797 safe_close(open_tree_fd);
6802 #ifdef HAVE_LIBURING_H
6803 static int io_uring_openat_with_creds(struct io_uring *ring, int dfd, const char *path, int cred_id,
6804 bool with_link, int *ret_cqe)
6806 struct io_uring_cqe *cqe;
6807 struct io_uring_sqe *sqe;
6808 int ret, i, to_submit = 1;
6811 sqe = io_uring_get_sqe(ring);
6813 return log_error_errno(-EINVAL, EINVAL, "failure: io_uring_sqe");
6814 io_uring_prep_nop(sqe);
6815 sqe->flags |= IOSQE_IO_LINK;
6820 sqe = io_uring_get_sqe(ring);
6822 return log_error_errno(-EINVAL, EINVAL, "failure: io_uring_sqe");
6823 io_uring_prep_openat(sqe, dfd, path, O_RDONLY | O_CLOEXEC, 0);
6827 sqe->personality = cred_id;
6829 ret = io_uring_submit(ring);
6830 if (ret != to_submit) {
6831 log_stderr("failure: io_uring_submit");
6835 for (i = 0; i < to_submit; i++) {
6836 ret = io_uring_wait_cqe(ring, &cqe);
6838 log_stderr("failure: io_uring_wait_cqe");
6844 * Make sure caller can identify that this is a proper io_uring
6845 * failure and not some earlier error.
6849 io_uring_cqe_seen(ring, cqe);
6851 log_debug("Ran test");
6856 static int io_uring(void)
6859 int file1_fd = -EBADF;
6860 struct io_uring *ring;
6861 int cred_id, ret, ret_cqe;
6864 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
6865 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
6867 return log_errno(-1, "failure: io_uring_queue_init");
6869 ret = io_uring_queue_init(8, ring, 0);
6871 log_stderr("failure: io_uring_queue_init");
6875 ret = io_uring_register_personality(ring);
6878 goto out_unmap; /* personalities not supported */
6882 /* create file only owner can open */
6883 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
6885 log_stderr("failure: openat");
6888 if (fchown(file1_fd, 0, 0)) {
6889 log_stderr("failure: fchown");
6892 if (fchmod(file1_fd, 0600)) {
6893 log_stderr("failure: fchmod");
6896 safe_close(file1_fd);
6900 log_stderr("failure: fork");
6904 /* Verify we can open it with our current credentials. */
6905 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6908 die("failure: io_uring_open_file");
6912 if (wait_for_pid(pid)) {
6913 log_stderr("failure: wait_for_pid");
6919 log_stderr("failure: fork");
6923 if (!switch_ids(1000, 1000))
6924 die("failure: switch_ids");
6926 /* Verify we can't open it with our current credentials. */
6928 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6929 -1, false, &ret_cqe);
6931 die("failure: io_uring_open_file");
6933 die("failure: non-open() related io_uring_open_file failure %d", ret_cqe);
6934 if (ret_cqe != -EACCES)
6935 die("failure: errno(%d)", abs(ret_cqe));
6939 if (wait_for_pid(pid)) {
6940 log_stderr("failure: wait_for_pid");
6946 log_stderr("failure: fork");
6950 if (!switch_ids(1000, 1000))
6951 die("failure: switch_ids");
6953 /* Verify we can open it with the registered credentials. */
6954 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6955 cred_id, false, NULL);
6957 die("failure: io_uring_open_file");
6959 /* Verify we can open it with the registered credentials and as
6962 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6963 cred_id, true, NULL);
6965 die("failure: io_uring_open_file");
6969 if (wait_for_pid(pid)) {
6970 log_stderr("failure: wait_for_pid");
6975 log_debug("Ran test");
6977 ret = io_uring_unregister_personality(ring, cred_id);
6979 log_stderr("failure: io_uring_unregister_personality");
6982 munmap(ring, sizeof(struct io_uring));
6984 safe_close(file1_fd);
6989 static int io_uring_userns(void)
6992 int file1_fd = -EBADF, userns_fd = -EBADF;
6993 struct io_uring *ring;
6994 int cred_id, ret, ret_cqe;
6997 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
6998 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7000 return log_errno(-1, "failure: io_uring_queue_init");
7002 ret = io_uring_queue_init(8, ring, 0);
7004 log_stderr("failure: io_uring_queue_init");
7008 ret = io_uring_register_personality(ring);
7011 goto out_unmap; /* personalities not supported */
7015 /* create file only owner can open */
7016 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7018 log_stderr("failure: openat");
7021 if (fchown(file1_fd, 0, 0)) {
7022 log_stderr("failure: fchown");
7025 if (fchmod(file1_fd, 0600)) {
7026 log_stderr("failure: fchmod");
7029 safe_close(file1_fd);
7031 userns_fd = get_userns_fd(0, 10000, 10000);
7032 if (userns_fd < 0) {
7033 log_stderr("failure: get_userns_fd");
7039 log_stderr("failure: fork");
7043 /* Verify we can open it with our current credentials. */
7044 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7047 die("failure: io_uring_open_file");
7051 if (wait_for_pid(pid)) {
7052 log_stderr("failure: wait_for_pid");
7058 log_stderr("failure: fork");
7062 if (!switch_userns(userns_fd, 0, 0, false))
7063 die("failure: switch_userns");
7065 /* Verify we can't open it with our current credentials. */
7067 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7068 -1, false, &ret_cqe);
7070 die("failure: io_uring_open_file");
7072 die("failure: non-open() related io_uring_open_file failure");
7073 if (ret_cqe != -EACCES)
7074 die("failure: errno(%d)", abs(ret_cqe));
7078 if (wait_for_pid(pid)) {
7079 log_stderr("failure: wait_for_pid");
7085 log_stderr("failure: fork");
7089 if (!switch_userns(userns_fd, 0, 0, false))
7090 die("failure: switch_userns");
7092 /* Verify we can open it with the registered credentials. */
7093 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7094 cred_id, false, NULL);
7096 die("failure: io_uring_open_file");
7098 /* Verify we can open it with the registered credentials and as
7101 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7102 cred_id, true, NULL);
7104 die("failure: io_uring_open_file");
7108 if (wait_for_pid(pid)) {
7109 log_stderr("failure: wait_for_pid");
7114 log_debug("Ran test");
7116 ret = io_uring_unregister_personality(ring, cred_id);
7118 log_stderr("failure: io_uring_unregister_personality");
7121 munmap(ring, sizeof(struct io_uring));
7123 safe_close(file1_fd);
7124 safe_close(userns_fd);
7129 static int io_uring_idmapped(void)
7132 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7133 struct io_uring *ring;
7134 struct mount_attr attr = {
7135 .attr_set = MOUNT_ATTR_IDMAP,
7140 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7141 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7143 return log_errno(-1, "failure: io_uring_queue_init");
7145 ret = io_uring_queue_init(8, ring, 0);
7147 log_stderr("failure: io_uring_queue_init");
7151 ret = io_uring_register_personality(ring);
7154 goto out_unmap; /* personalities not supported */
7158 /* create file only owner can open */
7159 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7161 log_stderr("failure: openat");
7164 if (fchown(file1_fd, 0, 0)) {
7165 log_stderr("failure: fchown");
7168 if (fchmod(file1_fd, 0600)) {
7169 log_stderr("failure: fchmod");
7172 safe_close(file1_fd);
7174 /* Changing mount properties on a detached mount. */
7175 attr.userns_fd = get_userns_fd(0, 10000, 10000);
7176 if (attr.userns_fd < 0)
7177 return log_errno(-1, "failure: create user namespace");
7179 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7182 AT_SYMLINK_NOFOLLOW |
7185 if (open_tree_fd < 0)
7186 return log_errno(-1, "failure: create detached mount");
7188 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7189 return log_errno(-1, "failure: set mount attributes");
7193 log_stderr("failure: fork");
7197 if (!switch_ids(10000, 10000))
7198 die("failure: switch_ids");
7200 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7203 die("failure: io_uring_open_file");
7207 if (wait_for_pid(pid)) {
7208 log_stderr("failure: wait_for_pid");
7214 log_stderr("failure: fork");
7218 if (!switch_ids(10001, 10001))
7219 die("failure: switch_ids");
7221 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7222 cred_id, false, NULL);
7224 die("failure: io_uring_open_file");
7226 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7227 cred_id, true, NULL);
7229 die("failure: io_uring_open_file");
7233 if (wait_for_pid(pid)) {
7234 log_stderr("failure: wait_for_pid");
7239 log_debug("Ran test");
7241 ret = io_uring_unregister_personality(ring, cred_id);
7243 log_stderr("failure: io_uring_unregister_personality");
7246 munmap(ring, sizeof(struct io_uring));
7248 safe_close(attr.userns_fd);
7249 safe_close(file1_fd);
7250 safe_close(open_tree_fd);
7256 * Create an idmapped mount where the we leave the owner of the file unmapped.
7257 * In no circumstances, even with recorded credentials can it be allowed to
7260 static int io_uring_idmapped_unmapped(void)
7263 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7264 struct io_uring *ring;
7265 struct mount_attr attr = {
7266 .attr_set = MOUNT_ATTR_IDMAP,
7268 int cred_id, ret, ret_cqe;
7271 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7272 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7274 return log_errno(-1, "failure: io_uring_queue_init");
7276 ret = io_uring_queue_init(8, ring, 0);
7278 log_stderr("failure: io_uring_queue_init");
7282 ret = io_uring_register_personality(ring);
7285 goto out_unmap; /* personalities not supported */
7289 /* create file only owner can open */
7290 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7292 log_stderr("failure: openat");
7295 if (fchown(file1_fd, 0, 0)) {
7296 log_stderr("failure: fchown");
7299 if (fchmod(file1_fd, 0600)) {
7300 log_stderr("failure: fchmod");
7303 safe_close(file1_fd);
7305 /* Changing mount properties on a detached mount. */
7306 attr.userns_fd = get_userns_fd(1, 10000, 10000);
7307 if (attr.userns_fd < 0)
7308 return log_errno(-1, "failure: create user namespace");
7310 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7313 AT_SYMLINK_NOFOLLOW |
7316 if (open_tree_fd < 0)
7317 return log_errno(-1, "failure: create detached mount");
7319 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7320 return log_errno(-1, "failure: set mount attributes");
7324 log_stderr("failure: fork");
7328 if (!switch_ids(10000, 10000))
7329 die("failure: switch_ids");
7332 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7333 cred_id, false, &ret_cqe);
7335 die("failure: io_uring_open_file");
7337 die("failure: non-open() related io_uring_open_file failure");
7338 if (ret_cqe != -EACCES)
7339 die("failure: errno(%d)", abs(ret_cqe));
7342 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7343 cred_id, true, &ret_cqe);
7345 die("failure: io_uring_open_file");
7347 die("failure: non-open() related io_uring_open_file failure");
7348 if (ret_cqe != -EACCES)
7349 die("failure: errno(%d)", abs(ret_cqe));
7353 if (wait_for_pid(pid)) {
7354 log_stderr("failure: wait_for_pid");
7359 log_debug("Ran test");
7361 ret = io_uring_unregister_personality(ring, cred_id);
7363 log_stderr("failure: io_uring_unregister_personality");
7366 munmap(ring, sizeof(struct io_uring));
7368 safe_close(attr.userns_fd);
7369 safe_close(file1_fd);
7370 safe_close(open_tree_fd);
7375 static int io_uring_idmapped_userns(void)
7378 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7379 struct io_uring *ring;
7380 struct mount_attr attr = {
7381 .attr_set = MOUNT_ATTR_IDMAP,
7383 int cred_id, ret, ret_cqe;
7386 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7387 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7389 return log_errno(-1, "failure: io_uring_queue_init");
7391 ret = io_uring_queue_init(8, ring, 0);
7393 log_stderr("failure: io_uring_queue_init");
7397 ret = io_uring_register_personality(ring);
7400 goto out_unmap; /* personalities not supported */
7404 /* create file only owner can open */
7405 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7407 log_stderr("failure: openat");
7410 if (fchown(file1_fd, 0, 0)) {
7411 log_stderr("failure: fchown");
7414 if (fchmod(file1_fd, 0600)) {
7415 log_stderr("failure: fchmod");
7418 safe_close(file1_fd);
7420 /* Changing mount properties on a detached mount. */
7421 attr.userns_fd = get_userns_fd(0, 10000, 10000);
7422 if (attr.userns_fd < 0)
7423 return log_errno(-1, "failure: create user namespace");
7425 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7428 AT_SYMLINK_NOFOLLOW |
7431 if (open_tree_fd < 0)
7432 return log_errno(-1, "failure: create detached mount");
7434 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7435 return log_errno(-1, "failure: set mount attributes");
7439 log_stderr("failure: fork");
7443 if (!switch_userns(attr.userns_fd, 0, 0, false))
7444 die("failure: switch_userns");
7446 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7449 die("failure: io_uring_open_file");
7453 if (wait_for_pid(pid)) {
7454 log_stderr("failure: wait_for_pid");
7460 log_stderr("failure: fork");
7464 if (!caps_supported()) {
7465 log_debug("skip: capability library not installed");
7469 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
7470 die("failure: switch_userns");
7473 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7474 -1, false, &ret_cqe);
7476 die("failure: io_uring_open_file");
7478 die("failure: non-open() related io_uring_open_file failure");
7479 if (ret_cqe != -EACCES)
7480 die("failure: errno(%d)", abs(ret_cqe));
7483 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7484 -1, true, &ret_cqe);
7486 die("failure: io_uring_open_file");
7488 die("failure: non-open() related io_uring_open_file failure");
7489 if (ret_cqe != -EACCES)
7490 die("failure: errno(%d)", abs(ret_cqe));
7493 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7494 -1, false, &ret_cqe);
7496 die("failure: io_uring_open_file");
7498 die("failure: non-open() related io_uring_open_file failure");
7499 if (ret_cqe != -EACCES)
7500 die("failure: errno(%d)", abs(ret_cqe));
7503 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7504 -1, true, &ret_cqe);
7506 die("failure: io_uring_open_file");
7508 die("failure: non-open() related io_uring_open_file failure");
7509 if (ret_cqe != -EACCES)
7510 die("failure: errno(%d)", abs(ret_cqe));
7512 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7513 cred_id, false, NULL);
7515 die("failure: io_uring_open_file");
7517 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7518 cred_id, true, NULL);
7520 die("failure: io_uring_open_file");
7524 if (wait_for_pid(pid)) {
7525 log_stderr("failure: wait_for_pid");
7530 log_debug("Ran test");
7532 ret = io_uring_unregister_personality(ring, cred_id);
7534 log_stderr("failure: io_uring_unregister_personality");
7537 munmap(ring, sizeof(struct io_uring));
7539 safe_close(attr.userns_fd);
7540 safe_close(file1_fd);
7541 safe_close(open_tree_fd);
7546 static int io_uring_idmapped_unmapped_userns(void)
7549 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7550 struct io_uring *ring;
7551 struct mount_attr attr = {
7552 .attr_set = MOUNT_ATTR_IDMAP,
7554 int cred_id, ret, ret_cqe;
7557 ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7558 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7560 return log_errno(-1, "failure: io_uring_queue_init");
7562 ret = io_uring_queue_init(8, ring, 0);
7564 log_stderr("failure: io_uring_queue_init");
7568 ret = io_uring_register_personality(ring);
7571 goto out_unmap; /* personalities not supported */
7575 /* create file only owner can open */
7576 file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7578 log_stderr("failure: openat");
7581 if (fchown(file1_fd, 0, 0)) {
7582 log_stderr("failure: fchown");
7585 if (fchmod(file1_fd, 0600)) {
7586 log_stderr("failure: fchmod");
7589 safe_close(file1_fd);
7591 /* Changing mount properties on a detached mount. */
7592 attr.userns_fd = get_userns_fd(1, 10000, 10000);
7593 if (attr.userns_fd < 0)
7594 return log_errno(-1, "failure: create user namespace");
7596 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7599 AT_SYMLINK_NOFOLLOW |
7602 if (open_tree_fd < 0)
7603 return log_errno(-1, "failure: create detached mount");
7605 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7606 return log_errno(-1, "failure: set mount attributes");
7610 log_stderr("failure: fork");
7614 if (!caps_supported()) {
7615 log_debug("skip: capability library not installed");
7619 if (!switch_userns(attr.userns_fd, 10000, 10000, true))
7620 die("failure: switch_ids");
7623 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7624 cred_id, false, &ret_cqe);
7626 die("failure: io_uring_open_file");
7628 die("failure: non-open() related io_uring_open_file failure");
7629 if (ret_cqe != -EACCES)
7630 die("failure: errno(%d)", abs(ret_cqe));
7633 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7634 cred_id, true, &ret_cqe);
7636 die("failure: io_uring_open_file");
7638 die("failure: non-open() related io_uring_open_file failure");
7639 if (ret_cqe != -EACCES)
7640 die("failure: errno(%d)", abs(ret_cqe));
7644 if (wait_for_pid(pid)) {
7645 log_stderr("failure: wait_for_pid");
7650 log_debug("Ran test");
7652 ret = io_uring_unregister_personality(ring, cred_id);
7654 log_stderr("failure: io_uring_unregister_personality");
7657 munmap(ring, sizeof(struct io_uring));
7659 safe_close(attr.userns_fd);
7660 safe_close(file1_fd);
7661 safe_close(open_tree_fd);
7665 #endif /* HAVE_LIBURING_H */
7667 /* The following tests are concerned with setgid inheritance. These can be
7668 * filesystem type specific. For xfs, if a new file or directory is created
7669 * within a setgid directory and irix_sgid_inhiert is set then inherit the
7670 * setgid bit if the caller is in the group of the directory.
7672 static int setgid_create(void)
7675 int file1_fd = -EBADF;
7678 if (!caps_supported())
7681 if (fchmod(t_dir1_fd, S_IRUSR |
7691 log_stderr("failure: fchmod");
7695 /* Verify that the setgid bit got raised. */
7696 if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7697 log_stderr("failure: is_setgid");
7703 log_stderr("failure: fork");
7707 /* create regular file via open() */
7708 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7710 die("failure: create");
7712 /* We're capable_wrt_inode_uidgid() and also our fsgid matches
7713 * the directories gid.
7715 if (!is_setgid(t_dir1_fd, FILE1, 0))
7716 die("failure: is_setgid");
7718 /* create directory */
7719 if (mkdirat(t_dir1_fd, DIR1, 0000))
7720 die("failure: create");
7722 /* Directories always inherit the setgid bit. */
7723 if (!is_setgid(t_dir1_fd, DIR1, 0))
7724 die("failure: is_setgid");
7726 if (unlinkat(t_dir1_fd, FILE1, 0))
7727 die("failure: delete");
7729 if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
7730 die("failure: delete");
7734 if (wait_for_pid(pid))
7739 log_stderr("failure: fork");
7743 if (!switch_ids(0, 10000))
7744 die("failure: switch_ids");
7747 die("failure: caps_down");
7749 /* create regular file via open() */
7750 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7752 die("failure: create");
7754 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
7755 * bit needs to be stripped.
7757 if (is_setgid(t_dir1_fd, FILE1, 0))
7758 die("failure: is_setgid");
7760 /* create directory */
7761 if (mkdirat(t_dir1_fd, DIR1, 0000))
7762 die("failure: create");
7764 if (xfs_irix_sgid_inherit_enabled()) {
7765 /* We're not in_group_p(). */
7766 if (is_setgid(t_dir1_fd, DIR1, 0))
7767 die("failure: is_setgid");
7769 /* Directories always inherit the setgid bit. */
7770 if (!is_setgid(t_dir1_fd, DIR1, 0))
7771 die("failure: is_setgid");
7776 if (wait_for_pid(pid))
7780 log_debug("Ran test");
7782 safe_close(file1_fd);
7787 static int setgid_create_idmapped(void)
7790 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7791 struct mount_attr attr = {
7792 .attr_set = MOUNT_ATTR_IDMAP,
7796 if (!caps_supported())
7799 if (fchmod(t_dir1_fd, S_IRUSR |
7809 log_stderr("failure: fchmod");
7813 /* Verify that the sid bits got raised. */
7814 if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7815 log_stderr("failure: is_setgid");
7819 /* Changing mount properties on a detached mount. */
7820 attr.userns_fd = get_userns_fd(0, 10000, 10000);
7821 if (attr.userns_fd < 0) {
7822 log_stderr("failure: get_userns_fd");
7826 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7829 AT_SYMLINK_NOFOLLOW |
7832 if (open_tree_fd < 0) {
7833 log_stderr("failure: sys_open_tree");
7837 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
7838 log_stderr("failure: sys_mount_setattr");
7844 log_stderr("failure: fork");
7848 if (!switch_ids(10000, 11000))
7849 die("failure: switch fsids");
7851 /* create regular file via open() */
7852 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7854 die("failure: create");
7856 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
7857 * bit needs to be stripped.
7859 if (is_setgid(open_tree_fd, FILE1, 0))
7860 die("failure: is_setgid");
7862 /* create directory */
7863 if (mkdirat(open_tree_fd, DIR1, 0000))
7864 die("failure: create");
7866 if (xfs_irix_sgid_inherit_enabled()) {
7867 /* We're not in_group_p(). */
7868 if (is_setgid(open_tree_fd, DIR1, 0))
7869 die("failure: is_setgid");
7871 /* Directories always inherit the setgid bit. */
7872 if (!is_setgid(open_tree_fd, DIR1, 0))
7873 die("failure: is_setgid");
7878 if (wait_for_pid(pid))
7882 log_debug("Ran test");
7884 safe_close(attr.userns_fd);
7885 safe_close(file1_fd);
7886 safe_close(open_tree_fd);
7891 static int setgid_create_idmapped_in_userns(void)
7894 int file1_fd = -EBADF, open_tree_fd = -EBADF;
7895 struct mount_attr attr = {
7896 .attr_set = MOUNT_ATTR_IDMAP,
7900 if (!caps_supported())
7903 if (fchmod(t_dir1_fd, S_IRUSR |
7913 log_stderr("failure: fchmod");
7917 /* Verify that the sid bits got raised. */
7918 if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7919 log_stderr("failure: is_setgid");
7923 /* Changing mount properties on a detached mount. */
7924 attr.userns_fd = get_userns_fd(0, 10000, 10000);
7925 if (attr.userns_fd < 0) {
7926 log_stderr("failure: get_userns_fd");
7930 open_tree_fd = sys_open_tree(t_dir1_fd, "",
7933 AT_SYMLINK_NOFOLLOW |
7936 if (open_tree_fd < 0) {
7937 log_stderr("failure: sys_open_tree");
7941 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
7942 log_stderr("failure: sys_mount_setattr");
7948 log_stderr("failure: fork");
7952 if (!switch_userns(attr.userns_fd, 0, 0, false))
7953 die("failure: switch_userns");
7955 /* create regular file via open() */
7956 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7958 die("failure: create");
7960 /* We're in_group_p() and capable_wrt_inode_uidgid() so setgid
7961 * bit needs to be set.
7963 if (!is_setgid(open_tree_fd, FILE1, 0))
7964 die("failure: is_setgid");
7966 /* create directory */
7967 if (mkdirat(open_tree_fd, DIR1, 0000))
7968 die("failure: create");
7970 /* Directories always inherit the setgid bit. */
7971 if (!is_setgid(open_tree_fd, DIR1, 0))
7972 die("failure: is_setgid");
7974 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
7975 die("failure: check ownership");
7977 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
7978 die("failure: check ownership");
7980 if (unlinkat(open_tree_fd, FILE1, 0))
7981 die("failure: delete");
7983 if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
7984 die("failure: delete");
7988 if (wait_for_pid(pid))
7991 if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
7992 log_stderr("failure: fchownat");
7996 if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
7997 log_stderr("failure: fchownat");
8003 log_stderr("failure: fork");
8007 if (!caps_supported()) {
8008 log_debug("skip: capability library not installed");
8012 if (!switch_userns(attr.userns_fd, 0, 0, true))
8013 die("failure: switch_userns");
8015 /* create regular file via open() */
8016 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
8018 die("failure: create");
8020 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
8021 * bit needs to be stripped.
8023 if (is_setgid(open_tree_fd, FILE1, 0))
8024 die("failure: is_setgid");
8026 /* create directory */
8027 if (mkdirat(open_tree_fd, DIR1, 0000))
8028 die("failure: create");
8030 if (xfs_irix_sgid_inherit_enabled()) {
8031 /* We're not in_group_p(). */
8032 if (is_setgid(open_tree_fd, DIR1, 0))
8033 die("failure: is_setgid");
8035 /* Directories always inherit the setgid bit. */
8036 if (!is_setgid(open_tree_fd, DIR1, 0))
8037 die("failure: is_setgid");
8040 /* Files and directories created in setgid directories inherit
8041 * the i_gid of the parent directory.
8043 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8044 die("failure: check ownership");
8046 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 1000))
8047 die("failure: check ownership");
8049 if (unlinkat(open_tree_fd, FILE1, 0))
8050 die("failure: delete");
8052 if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
8053 die("failure: delete");
8057 if (wait_for_pid(pid))
8060 if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8061 log_stderr("failure: fchownat");
8065 if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8066 log_stderr("failure: fchownat");
8072 log_stderr("failure: fork");
8076 if (!caps_supported()) {
8077 log_debug("skip: capability library not installed");
8081 if (!switch_userns(attr.userns_fd, 0, 1000, true))
8082 die("failure: switch_userns");
8084 /* create regular file via open() */
8085 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
8087 die("failure: create");
8089 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
8090 * bit needs to be stripped.
8092 if (is_setgid(open_tree_fd, FILE1, 0))
8093 die("failure: is_setgid");
8095 /* create directory */
8096 if (mkdirat(open_tree_fd, DIR1, 0000))
8097 die("failure: create");
8099 /* Directories always inherit the setgid bit. */
8100 if (xfs_irix_sgid_inherit_enabled()) {
8101 /* We're not in_group_p(). */
8102 if (is_setgid(open_tree_fd, DIR1, 0))
8103 die("failure: is_setgid");
8105 /* Directories always inherit the setgid bit. */
8106 if (!is_setgid(open_tree_fd, DIR1, 0))
8107 die("failure: is_setgid");
8110 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8111 die("failure: check ownership");
8113 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
8114 die("failure: check ownership");
8118 if (wait_for_pid(pid))
8122 log_debug("Ran test");
8124 safe_close(attr.userns_fd);
8125 safe_close(file1_fd);
8126 safe_close(open_tree_fd);
8131 #define PTR_TO_INT(p) ((int)((intptr_t)(p)))
8132 #define INT_TO_PTR(u) ((void *)((intptr_t)(u)))
8134 static void *idmapped_mount_create_cb(void *data)
8136 int fret = EXIT_FAILURE, open_tree_fd = PTR_TO_INT(data);
8137 struct mount_attr attr = {
8138 .attr_set = MOUNT_ATTR_IDMAP,
8141 /* Changing mount properties on a detached mount. */
8142 attr.userns_fd = get_userns_fd(0, 10000, 10000);
8143 if (attr.userns_fd < 0) {
8144 log_stderr("failure: get_userns_fd");
8148 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8149 log_stderr("failure: sys_mount_setattr");
8153 fret = EXIT_SUCCESS;
8156 safe_close(attr.userns_fd);
8157 pthread_exit(INT_TO_PTR(fret));
8160 /* This tries to verify that we never see an inconistent ownership on-disk and
8161 * can't write invalid ids to disk. To do this we create a race between
8162 * idmapping a mount and creating files on it.
8163 * Note, while it is perfectly fine to see overflowuid and overflowgid as owner
8164 * if we create files through the open_tree_fd before the mount is idmapped but
8165 * look at the files after the mount has been idmapped in this test it can never
8166 * be the case that we see overflowuid and overflowgid when we access the file
8167 * through a non-idmapped mount (in the initial user namespace).
8169 static void *idmapped_mount_operations_cb(void *data)
8171 int file1_fd = -EBADF, file2_fd = -EBADF, dir1_fd = -EBADF,
8172 dir1_fd2 = -EBADF, fret = EXIT_FAILURE,
8173 open_tree_fd = PTR_TO_INT(data);
8175 if (!switch_fsids(10000, 10000)) {
8176 log_stderr("failure: switch fsids");
8180 file1_fd = openat(open_tree_fd, FILE1,
8181 O_CREAT | O_EXCL | O_CLOEXEC, 0644);
8183 log_stderr("failure: openat");
8187 file2_fd = openat(open_tree_fd, FILE2,
8188 O_CREAT | O_EXCL | O_CLOEXEC, 0644);
8190 log_stderr("failure: openat");
8194 if (mkdirat(open_tree_fd, DIR1, 0777)) {
8195 log_stderr("failure: mkdirat");
8199 dir1_fd = openat(open_tree_fd, DIR1,
8200 O_RDONLY | O_DIRECTORY | O_CLOEXEC);
8202 log_stderr("failure: openat");
8206 if (!__expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0, false) &&
8207 !__expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000, false) &&
8208 !__expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid, false)) {
8209 log_stderr("failure: expected_uid_gid");
8213 if (!__expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0, false) &&
8214 !__expected_uid_gid(open_tree_fd, FILE2, 0, 10000, 10000, false) &&
8215 !__expected_uid_gid(open_tree_fd, FILE2, 0, t_overflowuid, t_overflowgid, false)) {
8216 log_stderr("failure: expected_uid_gid");
8220 if (!__expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0, false) &&
8221 !__expected_uid_gid(open_tree_fd, DIR1, 0, 10000, 10000, false) &&
8222 !__expected_uid_gid(open_tree_fd, DIR1, 0, t_overflowuid, t_overflowgid, false)) {
8223 log_stderr("failure: expected_uid_gid");
8227 if (!__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, 0, 0, false) &&
8228 !__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, 10000, 10000, false) &&
8229 !__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, t_overflowuid, t_overflowgid, false)) {
8230 log_stderr("failure: expected_uid_gid");
8234 dir1_fd2 = openat(t_dir1_fd, DIR1,
8235 O_RDONLY | O_DIRECTORY | O_CLOEXEC);
8237 log_stderr("failure: openat");
8241 if (!__expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0, false) &&
8242 !__expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000, false)) {
8243 log_stderr("failure: expected_uid_gid");
8247 if (!__expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0, false) &&
8248 !__expected_uid_gid(t_dir1_fd, FILE2, 0, 10000, 10000, false)) {
8249 log_stderr("failure: expected_uid_gid");
8253 if (!__expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0, false) &&
8254 !__expected_uid_gid(t_dir1_fd, DIR1, 0, 10000, 10000, false)) {
8255 log_stderr("failure: expected_uid_gid");
8259 if (!__expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0, false) &&
8260 !__expected_uid_gid(t_dir1_fd, DIR1, 0, 10000, 10000, false)) {
8261 log_stderr("failure: expected_uid_gid");
8265 if (!__expected_uid_gid(dir1_fd2, "", AT_EMPTY_PATH, 0, 0, false) &&
8266 !__expected_uid_gid(dir1_fd2, "", AT_EMPTY_PATH, 10000, 10000, false)) {
8267 log_stderr("failure: expected_uid_gid");
8271 fret = EXIT_SUCCESS;
8274 safe_close(file1_fd);
8275 safe_close(file2_fd);
8276 safe_close(dir1_fd);
8277 safe_close(dir1_fd2);
8279 pthread_exit(INT_TO_PTR(fret));
8282 static int threaded_idmapped_mount_interactions(void)
8287 pthread_attr_t thread_attr;
8288 pthread_t threads[2];
8290 pthread_attr_init(&thread_attr);
8292 for (i = 0; i < 1000; i++) {
8293 int ret1 = 0, ret2 = 0, tret1 = 0, tret2 = 0;
8297 log_stderr("failure: fork");
8301 int open_tree_fd = -EBADF;
8303 open_tree_fd = sys_open_tree(t_dir1_fd, "",
8306 AT_SYMLINK_NOFOLLOW |
8309 if (open_tree_fd < 0)
8310 die("failure: sys_open_tree");
8312 if (pthread_create(&threads[0], &thread_attr,
8313 idmapped_mount_create_cb,
8314 INT_TO_PTR(open_tree_fd)))
8315 die("failure: pthread_create");
8317 if (pthread_create(&threads[1], &thread_attr,
8318 idmapped_mount_operations_cb,
8319 INT_TO_PTR(open_tree_fd)))
8320 die("failure: pthread_create");
8322 ret1 = pthread_join(threads[0], INT_TO_PTR(tret1));
8323 ret2 = pthread_join(threads[1], INT_TO_PTR(tret2));
8327 die("failure: pthread_join");
8332 die("failure: pthread_join");
8342 if (wait_for_pid(pid)) {
8343 log_stderr("failure: iteration %d", i);
8347 rm_r(t_dir1_fd, ".");
8352 log_debug("Ran test");
8358 static int setattr_truncate(void)
8361 int file1_fd = -EBADF;
8363 /* create regular file via open() */
8364 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8366 log_stderr("failure: create");
8370 if (ftruncate(file1_fd, 10000)) {
8371 log_stderr("failure: ftruncate");
8375 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
8376 log_stderr("failure: check ownership");
8380 if (!expected_file_size(file1_fd, "", AT_EMPTY_PATH, 10000)) {
8381 log_stderr("failure: expected_file_size");
8385 if (ftruncate(file1_fd, 0)) {
8386 log_stderr("failure: ftruncate");
8390 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
8391 log_stderr("failure: check ownership");
8395 if (!expected_file_size(file1_fd, "", AT_EMPTY_PATH, 0)) {
8396 log_stderr("failure: expected_file_size");
8400 if (unlinkat(t_dir1_fd, FILE1, 0)) {
8401 log_stderr("failure: remove");
8406 log_debug("Ran test");
8408 safe_close(file1_fd);
8413 static int setattr_truncate_idmapped(void)
8416 int file1_fd = -EBADF, open_tree_fd = -EBADF;
8418 struct mount_attr attr = {
8419 .attr_set = MOUNT_ATTR_IDMAP,
8422 /* Changing mount properties on a detached mount. */
8423 attr.userns_fd = get_userns_fd(0, 10000, 10000);
8424 if (attr.userns_fd < 0) {
8425 log_stderr("failure: get_userns_fd");
8429 open_tree_fd = sys_open_tree(t_dir1_fd, "",
8432 AT_SYMLINK_NOFOLLOW |
8435 if (open_tree_fd < 0) {
8436 log_stderr("failure: sys_open_tree");
8440 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8441 log_stderr("failure: sys_mount_setattr");
8447 log_stderr("failure: fork");
8451 if (!switch_ids(10000, 10000))
8452 die("failure: switch_ids");
8454 /* create regular file via open() */
8455 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8457 die("failure: create");
8459 if (ftruncate(file1_fd, 10000))
8460 die("failure: ftruncate");
8462 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8463 die("failure: check ownership");
8465 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8466 die("failure: expected_file_size");
8468 if (ftruncate(file1_fd, 0))
8469 die("failure: ftruncate");
8471 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8472 die("failure: check ownership");
8474 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8475 die("failure: expected_file_size");
8479 if (wait_for_pid(pid))
8484 log_stderr("failure: fork");
8488 int file1_fd2 = -EBADF;
8490 /* create regular file via open() */
8491 file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8493 die("failure: create");
8495 if (ftruncate(file1_fd2, 10000))
8496 die("failure: ftruncate");
8498 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8499 die("failure: check ownership");
8501 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8502 die("failure: expected_file_size");
8504 if (ftruncate(file1_fd2, 0))
8505 die("failure: ftruncate");
8507 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8508 die("failure: check ownership");
8510 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8511 die("failure: expected_file_size");
8515 if (wait_for_pid(pid))
8519 log_debug("Ran test");
8521 safe_close(file1_fd);
8522 safe_close(open_tree_fd);
8527 static int setattr_truncate_idmapped_in_userns(void)
8530 int file1_fd = -EBADF, open_tree_fd = -EBADF;
8531 struct mount_attr attr = {
8532 .attr_set = MOUNT_ATTR_IDMAP,
8536 /* Changing mount properties on a detached mount. */
8537 attr.userns_fd = get_userns_fd(0, 10000, 10000);
8538 if (attr.userns_fd < 0) {
8539 log_stderr("failure: get_userns_fd");
8543 open_tree_fd = sys_open_tree(t_dir1_fd, "",
8546 AT_SYMLINK_NOFOLLOW |
8549 if (open_tree_fd < 0) {
8550 log_stderr("failure: sys_open_tree");
8554 if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8555 log_stderr("failure: sys_mount_setattr");
8561 log_stderr("failure: fork");
8565 if (!switch_userns(attr.userns_fd, 0, 0, false))
8566 die("failure: switch_userns");
8568 /* create regular file via open() */
8569 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8571 die("failure: create");
8573 if (ftruncate(file1_fd, 10000))
8574 die("failure: ftruncate");
8576 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8577 die("failure: check ownership");
8579 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8580 die("failure: expected_file_size");
8582 if (ftruncate(file1_fd, 0))
8583 die("failure: ftruncate");
8585 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8586 die("failure: check ownership");
8588 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8589 die("failure: expected_file_size");
8591 if (unlinkat(open_tree_fd, FILE1, 0))
8592 die("failure: delete");
8596 if (wait_for_pid(pid))
8599 if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8600 log_stderr("failure: fchownat");
8604 if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8605 log_stderr("failure: fchownat");
8611 log_stderr("failure: fork");
8615 if (!caps_supported()) {
8616 log_debug("skip: capability library not installed");
8620 if (!switch_userns(attr.userns_fd, 0, 0, true))
8621 die("failure: switch_userns");
8623 /* create regular file via open() */
8624 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8626 die("failure: create");
8628 if (ftruncate(file1_fd, 10000))
8629 die("failure: ftruncate");
8631 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8632 die("failure: check ownership");
8634 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8635 die("failure: expected_file_size");
8637 if (ftruncate(file1_fd, 0))
8638 die("failure: ftruncate");
8640 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8641 die("failure: check ownership");
8643 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8644 die("failure: expected_file_size");
8646 if (unlinkat(open_tree_fd, FILE1, 0))
8647 die("failure: delete");
8651 if (wait_for_pid(pid))
8654 if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8655 log_stderr("failure: fchownat");
8659 if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8660 log_stderr("failure: fchownat");
8666 log_stderr("failure: fork");
8670 if (!caps_supported()) {
8671 log_debug("skip: capability library not installed");
8675 if (!switch_userns(attr.userns_fd, 0, 1000, true))
8676 die("failure: switch_userns");
8678 /* create regular file via open() */
8679 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8681 die("failure: create");
8683 if (ftruncate(file1_fd, 10000))
8684 die("failure: ftruncate");
8686 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8687 die("failure: check ownership");
8689 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8690 die("failure: expected_file_size");
8692 if (ftruncate(file1_fd, 0))
8693 die("failure: ftruncate");
8695 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8696 die("failure: check ownership");
8698 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8699 die("failure: expected_file_size");
8701 if (unlinkat(open_tree_fd, FILE1, 0))
8702 die("failure: delete");
8706 if (wait_for_pid(pid))
8710 log_debug("Ran test");
8712 safe_close(attr.userns_fd);
8713 safe_close(file1_fd);
8714 safe_close(open_tree_fd);
8719 static void usage(void)
8721 fprintf(stderr, "Description:\n");
8722 fprintf(stderr, " Run idmapped mount tests\n\n");
8724 fprintf(stderr, "Arguments:\n");
8725 fprintf(stderr, "-d --device Device used in the tests\n");
8726 fprintf(stderr, "-m --mountpoint Mountpoint of device\n");
8728 _exit(EXIT_SUCCESS);
8731 static const struct option longopts[] = {
8732 {"device", required_argument, 0, 'd'},
8733 {"fstype", required_argument, 0, 'f'},
8734 {"mountpoint", required_argument, 0, 'm'},
8735 {"supported", no_argument, 0, 's'},
8736 {"help", no_argument, 0, 'h'},
8740 struct t_idmapped_mounts {
8742 const char *description;
8743 } t_idmapped_mounts[] = {
8744 { acls, "posix acls on regular mounts", },
8745 { create_in_userns, "create operations in user namespace", },
8746 { device_node_in_userns, "device node in user namespace", },
8747 { expected_uid_gid_idmapped_mounts, "expected ownership on idmapped mounts", },
8748 { fscaps, "fscaps on regular mounts", },
8749 { fscaps_idmapped_mounts, "fscaps on idmapped mounts", },
8750 { fscaps_idmapped_mounts_in_userns, "fscaps on idmapped mounts in user namespace", },
8751 { fscaps_idmapped_mounts_in_userns_separate_userns, "fscaps on idmapped mounts in user namespace with different id mappings ", },
8752 { fsids_mapped, "mapped fsids", },
8753 { fsids_unmapped, "unmapped fsids", },
8754 { hardlink_crossing_mounts, "cross mount hardlink", },
8755 { hardlink_crossing_idmapped_mounts, "cross idmapped mount hardlink", },
8756 { hardlink_from_idmapped_mount, "hardlinks from idmapped mounts", },
8757 { hardlink_from_idmapped_mount_in_userns, "hardlinks from idmapped mounts in user namespace", },
8758 #ifdef HAVE_LIBURING_H
8759 { io_uring, "io_uring", },
8760 { io_uring_userns, "io_uring in user namespace", },
8761 { io_uring_idmapped, "io_uring from idmapped mounts", },
8762 { io_uring_idmapped_userns, "io_uring from idmapped mounts in user namespace", },
8763 { io_uring_idmapped_unmapped, "io_uring from idmapped mounts with unmapped ids", },
8764 { io_uring_idmapped_unmapped_userns, "io_uring from idmapped mounts with unmapped ids in user namespace", },
8766 { protected_symlinks, "following protected symlinks on regular mounts", },
8767 { protected_symlinks_idmapped_mounts, "following protected symlinks on idmapped mounts", },
8768 { protected_symlinks_idmapped_mounts_in_userns, "following protected symlinks on idmapped mounts in user namespace", },
8769 { rename_crossing_mounts, "cross mount rename", },
8770 { rename_crossing_idmapped_mounts, "cross idmapped mount rename", },
8771 { rename_from_idmapped_mount, "rename from idmapped mounts", },
8772 { rename_from_idmapped_mount_in_userns, "rename from idmapped mounts in user namespace", },
8773 { setattr_truncate, "setattr truncate", },
8774 { setattr_truncate_idmapped, "setattr truncate on idmapped mounts", },
8775 { setattr_truncate_idmapped_in_userns, "setattr truncate on idmapped mounts in user namespace", },
8776 { setgid_create, "create operations in directories with setgid bit set", },
8777 { setgid_create_idmapped, "create operations in directories with setgid bit set on idmapped mounts", },
8778 { setgid_create_idmapped_in_userns, "create operations in directories with setgid bit set on idmapped mounts in user namespace", },
8779 { setid_binaries, "setid binaries on regular mounts", },
8780 { setid_binaries_idmapped_mounts, "setid binaries on idmapped mounts", },
8781 { setid_binaries_idmapped_mounts_in_userns, "setid binaries on idmapped mounts in user namespace", },
8782 { setid_binaries_idmapped_mounts_in_userns_separate_userns, "setid binaries on idmapped mounts in user namespace with different id mappings", },
8783 { sticky_bit_unlink, "sticky bit unlink operations on regular mounts", },
8784 { sticky_bit_unlink_idmapped_mounts, "sticky bit unlink operations on idmapped mounts", },
8785 { sticky_bit_unlink_idmapped_mounts_in_userns, "sticky bit unlink operations on idmapped mounts in user namespace", },
8786 { sticky_bit_rename, "sticky bit rename operations on regular mounts", },
8787 { sticky_bit_rename_idmapped_mounts, "sticky bit rename operations on idmapped mounts", },
8788 { sticky_bit_rename_idmapped_mounts_in_userns, "sticky bit rename operations on idmapped mounts in user namespace", },
8789 { symlink_regular_mounts, "symlink from regular mounts", },
8790 { symlink_idmapped_mounts, "symlink from idmapped mounts", },
8791 { symlink_idmapped_mounts_in_userns, "symlink from idmapped mounts in user namespace", },
8792 { threaded_idmapped_mount_interactions, "threaded operations on idmapped mounts", },
8795 int main(int argc, char *argv[])
8799 bool supported = false;
8801 while ((ret = getopt_long(argc, argv, "", longopts, &index)) != -1) {
8810 t_mountpoint = optarg;
8823 die_errno(EINVAL, "test device missing");
8826 die_errno(EINVAL, "test filesystem type missing");
8829 die_errno(EINVAL, "mountpoint of test device missing");
8831 /* create separate mount namespace */
8832 if (unshare(CLONE_NEWNS))
8833 die("failure: create new mount namespace");
8835 /* turn off mount propagation */
8836 if (sys_mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0))
8837 die("failure: turn mount propagation off");
8839 t_mnt_fd = openat(-EBADF, t_mountpoint, O_CLOEXEC | O_DIRECTORY);
8841 die("failed to open %s", t_mountpoint);
8844 * Caller just wants to know whether the filesystem we're on supports
8848 int open_tree_fd = -EBADF;
8849 struct mount_attr attr = {
8850 .attr_set = MOUNT_ATTR_IDMAP,
8851 .userns_fd = -EBADF,
8854 /* Changing mount properties on a detached mount. */
8855 attr.userns_fd = get_userns_fd(0, 1000, 1);
8856 if (attr.userns_fd < 0)
8859 open_tree_fd = sys_open_tree(t_mnt_fd, "",
8862 AT_SYMLINK_NOFOLLOW |
8865 if (open_tree_fd < 0)
8868 ret = sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr));
8870 close(open_tree_fd);
8871 close(attr.userns_fd);
8879 stash_overflowuid();
8880 stash_overflowgid();
8882 fret = EXIT_FAILURE;
8884 /* Proper test suite run. */
8885 for (i = 0; i < (sizeof(t_idmapped_mounts) / sizeof(t_idmapped_mounts[0])); i++) {
8886 struct t_idmapped_mounts *t = &t_idmapped_mounts[i];
8898 fprintf(stderr, "failure: %s\n", t->description);
8905 ret = wait_for_pid(pid);
8912 fret = EXIT_SUCCESS;