idmapped-mounts: remove unused set_cloexec() helper
[xfstests-dev.git] / src / idmapped-mounts / idmapped-mounts.c
1 // SPDX-License-Identifier: GPL-2.0
2 #ifndef _GNU_SOURCE
3 #define _GNU_SOURCE
4 #endif
5
6 #include "../global.h"
7
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <getopt.h>
12 #include <grp.h>
13 #include <limits.h>
14 #include <linux/limits.h>
15 #include <linux/types.h>
16 #include <pthread.h>
17 #include <sched.h>
18 #include <stdbool.h>
19 #include <sys/fsuid.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/xattr.h>
23 #include <unistd.h>
24
25 #ifdef HAVE_SYS_CAPABILITY_H
26 #include <sys/capability.h>
27 #endif
28
29 #ifdef HAVE_LIBURING_H
30 #include <liburing.h>
31 #endif
32
33 #include "missing.h"
34 #include "utils.h"
35
36 #define T_DIR1 "idmapped_mounts_1"
37 #define FILE1 "file1"
38 #define FILE1_RENAME "file1_rename"
39 #define FILE2 "file2"
40 #define FILE2_RENAME "file2_rename"
41 #define DIR1 "dir1"
42 #define DIR2 "dir2"
43 #define DIR3 "dir3"
44 #define DIR1_RENAME "dir1_rename"
45 #define HARDLINK1 "hardlink1"
46 #define SYMLINK1 "symlink1"
47 #define SYMLINK_USER1 "symlink_user1"
48 #define SYMLINK_USER2 "symlink_user2"
49 #define SYMLINK_USER3 "symlink_user3"
50 #define CHRDEV1 "chrdev1"
51
52 #define log_stderr(format, ...)                                                         \
53         fprintf(stderr, "%s: %d: %s - %m - " format "\n", __FILE__, __LINE__, __func__, \
54                 ##__VA_ARGS__)
55
56 #ifdef DEBUG_TRACE
57 #define log_debug(format, ...)                                           \
58         fprintf(stderr, "%s: %d: %s - " format "\n", __FILE__, __LINE__, \
59                 __func__, ##__VA_ARGS__)
60 #else
61 #define log_debug(format, ...)
62 #endif
63
64 #define log_error_errno(__ret__, __errno__, format, ...)      \
65         ({                                                    \
66                 typeof(__ret__) __internal_ret__ = (__ret__); \
67                 errno = (__errno__);                          \
68                 log_stderr(format, ##__VA_ARGS__);            \
69                 __internal_ret__;                             \
70         })
71
72 #define log_errno(__ret__, format, ...) log_error_errno(__ret__, errno, format, ##__VA_ARGS__)
73
74 #define die_errno(__errno__, format, ...)          \
75         ({                                         \
76                 errno = (__errno__);               \
77                 log_stderr(format, ##__VA_ARGS__); \
78                 exit(EXIT_FAILURE);                \
79         })
80
81 #define die(format, ...) die_errno(errno, format, ##__VA_ARGS__)
82
83 uid_t t_overflowuid = 65534;
84 gid_t t_overflowgid = 65534;
85
86 /* path of the test device */
87 const char *t_fstype;
88
89 /* path of the test device */
90 const char *t_device;
91
92 /* mountpoint of the test device */
93 const char *t_mountpoint;
94
95 /* fd for @t_mountpoint */
96 int t_mnt_fd;
97
98 /* fd for @T_DIR1 */
99 int t_dir1_fd;
100
101 /* temporary buffer */
102 char t_buf[PATH_MAX];
103
104 static void stash_overflowuid(void)
105 {
106         int fd;
107         ssize_t ret;
108         char buf[256];
109
110         fd = open("/proc/sys/fs/overflowuid", O_RDONLY | O_CLOEXEC);
111         if (fd < 0)
112                 return;
113
114         ret = read(fd, buf, sizeof(buf));
115         close(fd);
116         if (ret < 0)
117                 return;
118
119         t_overflowuid = atoi(buf);
120 }
121
122 static void stash_overflowgid(void)
123 {
124         int fd;
125         ssize_t ret;
126         char buf[256];
127
128         fd = open("/proc/sys/fs/overflowgid", O_RDONLY | O_CLOEXEC);
129         if (fd < 0)
130                 return;
131
132         ret = read(fd, buf, sizeof(buf));
133         close(fd);
134         if (ret < 0)
135                 return;
136
137         t_overflowgid = atoi(buf);
138 }
139
140 static bool is_xfs(void)
141 {
142         static int enabled = -1;
143
144         if (enabled == -1)
145                 enabled = !strcmp(t_fstype, "xfs");
146
147         return enabled;
148 }
149
150 static bool protected_symlinks_enabled(void)
151 {
152         static int enabled = -1;
153
154         if (enabled == -1) {
155                 int fd;
156                 ssize_t ret;
157                 char buf[256];
158
159                 enabled = 0;
160
161                 fd = open("/proc/sys/fs/protected_symlinks", O_RDONLY | O_CLOEXEC);
162                 if (fd < 0)
163                         return false;
164
165                 ret = read(fd, buf, sizeof(buf));
166                 close(fd);
167                 if (ret < 0)
168                         return false;
169
170                 if (atoi(buf) >= 1)
171                         enabled = 1;
172         }
173
174         return enabled == 1;
175 }
176
177 static bool xfs_irix_sgid_inherit_enabled(void)
178 {
179         static int enabled = -1;
180
181         if (enabled == -1) {
182                 int fd;
183                 ssize_t ret;
184                 char buf[256];
185
186                 enabled = 0;
187
188                 if (is_xfs()) {
189                         fd = open("/proc/sys/fs/xfs/irix_sgid_inherit", O_RDONLY | O_CLOEXEC);
190                         if (fd < 0)
191                                 return false;
192
193                         ret = read(fd, buf, sizeof(buf));
194                         close(fd);
195                         if (ret < 0)
196                                 return false;
197
198                         if (atoi(buf) >= 1)
199                                 enabled = 1;
200                 }
201         }
202
203         return enabled == 1;
204 }
205
206 static inline bool caps_supported(void)
207 {
208         bool ret = false;
209
210 #ifdef HAVE_SYS_CAPABILITY_H
211         ret = true;
212 #endif
213
214         return ret;
215 }
216
217 /* caps_down - lower all effective caps */
218 static int caps_down(void)
219 {
220         bool fret = false;
221 #ifdef HAVE_SYS_CAPABILITY_H
222         cap_t caps = NULL;
223         int ret = -1;
224
225         caps = cap_get_proc();
226         if (!caps)
227                 goto out;
228
229         ret = cap_clear_flag(caps, CAP_EFFECTIVE);
230         if (ret)
231                 goto out;
232
233         ret = cap_set_proc(caps);
234         if (ret)
235                 goto out;
236
237         fret = true;
238
239 out:
240         cap_free(caps);
241 #endif
242         return fret;
243 }
244
245 /* caps_up - raise all permitted caps */
246 static int caps_up(void)
247 {
248         bool fret = false;
249 #ifdef HAVE_SYS_CAPABILITY_H
250         cap_t caps = NULL;
251         cap_value_t cap;
252         int ret = -1;
253
254         caps = cap_get_proc();
255         if (!caps)
256                 goto out;
257
258         for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
259                 cap_flag_value_t flag;
260
261                 ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
262                 if (ret) {
263                         if (errno == EINVAL)
264                                 break;
265                         else
266                                 goto out;
267                 }
268
269                 ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
270                 if (ret)
271                         goto out;
272         }
273
274         ret = cap_set_proc(caps);
275         if (ret)
276                 goto out;
277
278         fret = true;
279 out:
280         cap_free(caps);
281 #endif
282         return fret;
283 }
284
285 /* __expected_uid_gid - check whether file is owned by the provided uid and gid */
286 static bool __expected_uid_gid(int dfd, const char *path, int flags,
287                                uid_t expected_uid, gid_t expected_gid, bool log)
288 {
289         int ret;
290         struct stat st;
291
292         ret = fstatat(dfd, path, &st, flags);
293         if (ret < 0)
294                 return log_errno(false, "failure: fstatat");
295
296         if (log && st.st_uid != expected_uid)
297                 log_stderr("failure: uid(%d) != expected_uid(%d)", st.st_uid, expected_uid);
298
299         if (log && st.st_gid != expected_gid)
300                 log_stderr("failure: gid(%d) != expected_gid(%d)", st.st_gid, expected_gid);
301
302         errno = 0; /* Don't report misleading errno. */
303         return st.st_uid == expected_uid && st.st_gid == expected_gid;
304 }
305
306 static bool expected_uid_gid(int dfd, const char *path, int flags,
307                              uid_t expected_uid, gid_t expected_gid)
308 {
309         return __expected_uid_gid(dfd, path, flags,
310                                   expected_uid, expected_gid, true);
311 }
312
313 static bool expected_file_size(int dfd, const char *path,
314                                int flags, off_t expected_size)
315 {
316         int ret;
317         struct stat st;
318
319         ret = fstatat(dfd, path, &st, flags);
320         if (ret < 0)
321                 return log_errno(false, "failure: fstatat");
322
323         if (st.st_size != expected_size)
324                 return log_errno(false, "failure: st_size(%zu) != expected_size(%zu)",
325                                  (size_t)st.st_size, (size_t)expected_size);
326
327         return true;
328 }
329
330 /* is_setid - check whether file is S_ISUID and S_ISGID */
331 static bool is_setid(int dfd, const char *path, int flags)
332 {
333         int ret;
334         struct stat st;
335
336         ret = fstatat(dfd, path, &st, flags);
337         if (ret < 0)
338                 return false;
339
340         errno = 0; /* Don't report misleading errno. */
341         return (st.st_mode & S_ISUID) || (st.st_mode & S_ISGID);
342 }
343
344 /* is_setgid - check whether file or directory is S_ISGID */
345 static bool is_setgid(int dfd, const char *path, int flags)
346 {
347         int ret;
348         struct stat st;
349
350         ret = fstatat(dfd, path, &st, flags);
351         if (ret < 0)
352                 return false;
353
354         errno = 0; /* Don't report misleading errno. */
355         return (st.st_mode & S_ISGID);
356 }
357
358 /* is_sticky - check whether file is S_ISVTX */
359 static bool is_sticky(int dfd, const char *path, int flags)
360 {
361         int ret;
362         struct stat st;
363
364         ret = fstatat(dfd, path, &st, flags);
365         if (ret < 0)
366                 return false;
367
368         errno = 0; /* Don't report misleading errno. */
369         return (st.st_mode & S_ISVTX) > 0;
370 }
371
372 static inline bool switch_fsids(uid_t fsuid, gid_t fsgid)
373 {
374         if (setfsgid(fsgid))
375                 return log_errno(false, "failure: setfsgid");
376
377         if (setfsgid(-1) != fsgid)
378                 return log_errno(false, "failure: setfsgid(-1)");
379
380         if (setfsuid(fsuid))
381                 return log_errno(false, "failure: setfsuid");
382
383         if (setfsuid(-1) != fsuid)
384                 return log_errno(false, "failure: setfsuid(-1)");
385
386         return true;
387 }
388
389 static inline bool switch_ids(uid_t uid, gid_t gid)
390 {
391         if (setgroups(0, NULL))
392                 return log_errno(false, "failure: setgroups");
393
394         if (setresgid(gid, gid, gid))
395                 return log_errno(false, "failure: setresgid");
396
397         if (setresuid(uid, uid, uid))
398                 return log_errno(false, "failure: setresuid");
399
400         return true;
401 }
402
403 static inline bool switch_userns(int fd, uid_t uid, gid_t gid, bool drop_caps)
404 {
405         if (setns(fd, CLONE_NEWUSER))
406                 return log_errno(false, "failure: setns");
407
408         if (!switch_ids(uid, gid))
409                 return log_errno(false, "failure: switch_ids");
410
411         if (drop_caps && !caps_down())
412                 return log_errno(false, "failure: caps_down");
413
414         return true;
415 }
416
417 /* rm_r - recursively remove all files */
418 static int rm_r(int fd, const char *path)
419 {
420         int dfd, ret;
421         DIR *dir;
422         struct dirent *direntp;
423
424         if (!path || strcmp(path, "") == 0)
425                 return -1;
426
427         dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
428         if (dfd < 0)
429                 return -1;
430
431         dir = fdopendir(dfd);
432         if (!dir) {
433                 close(dfd);
434                 return -1;
435         }
436
437         while ((direntp = readdir(dir))) {
438                 struct stat st;
439
440                 if (!strcmp(direntp->d_name, ".") ||
441                     !strcmp(direntp->d_name, ".."))
442                         continue;
443
444                 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
445                 if (ret < 0 && errno != ENOENT)
446                         break;
447
448                 if (S_ISDIR(st.st_mode))
449                         ret = rm_r(dfd, direntp->d_name);
450                 else
451                         ret = unlinkat(dfd, direntp->d_name, 0);
452                 if (ret < 0 && errno != ENOENT)
453                         break;
454         }
455
456         ret = unlinkat(fd, path, AT_REMOVEDIR);
457         closedir(dir);
458         return ret;
459 }
460
461 /* chown_r - recursively change ownership of all files */
462 static int chown_r(int fd, const char *path, uid_t uid, gid_t gid)
463 {
464         int dfd, ret;
465         DIR *dir;
466         struct dirent *direntp;
467
468         dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
469         if (dfd < 0)
470                 return -1;
471
472         dir = fdopendir(dfd);
473         if (!dir) {
474                 close(dfd);
475                 return -1;
476         }
477
478         while ((direntp = readdir(dir))) {
479                 struct stat st;
480
481                 if (!strcmp(direntp->d_name, ".") ||
482                     !strcmp(direntp->d_name, ".."))
483                         continue;
484
485                 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
486                 if (ret < 0 && errno != ENOENT)
487                         break;
488
489                 if (S_ISDIR(st.st_mode))
490                         ret = chown_r(dfd, direntp->d_name, uid, gid);
491                 else
492                         ret = fchownat(dfd, direntp->d_name, uid, gid, AT_SYMLINK_NOFOLLOW);
493                 if (ret < 0 && errno != ENOENT)
494                         break;
495         }
496
497         ret = fchownat(fd, path, uid, gid, AT_SYMLINK_NOFOLLOW);
498         closedir(dir);
499         return ret;
500 }
501
502 /*
503  * There'll be scenarios where you'll want to see the attributes associated with
504  * a directory tree during debugging or just to make sure things look correct.
505  * Simply uncomment and place the print_r() helper where you need it.
506  */
507 #ifdef DEBUG_TRACE
508 static int fd_cloexec(int fd, bool cloexec)
509 {
510         int oflags, nflags;
511
512         oflags = fcntl(fd, F_GETFD, 0);
513         if (oflags < 0)
514                 return -errno;
515
516         if (cloexec)
517                 nflags = oflags | FD_CLOEXEC;
518         else
519                 nflags = oflags & ~FD_CLOEXEC;
520
521         if (nflags == oflags)
522                 return 0;
523
524         if (fcntl(fd, F_SETFD, nflags) < 0)
525                 return -errno;
526
527         return 0;
528 }
529
530 static inline int dup_cloexec(int fd)
531 {
532         int fd_dup;
533
534         fd_dup = dup(fd);
535         if (fd_dup < 0)
536                 return -errno;
537
538         if (fd_cloexec(fd_dup, true)) {
539                 close(fd_dup);
540                 return -errno;
541         }
542
543         return fd_dup;
544 }
545
546 __attribute__((unused)) static int print_r(int fd, const char *path)
547 {
548         int ret = 0;
549         int dfd, dfd_dup;
550         DIR *dir;
551         struct dirent *direntp;
552         struct stat st;
553
554         if (!path || *path == '\0') {
555                 char buf[sizeof("/proc/self/fd/") + 30];
556
557                 ret = snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
558                 if (ret < 0 || (size_t)ret >= sizeof(buf))
559                         return -1;
560
561                 /*
562                  * O_PATH file descriptors can't be used so we need to re-open
563                  * just in case.
564                  */
565                 dfd = openat(-EBADF, buf, O_CLOEXEC | O_DIRECTORY, 0);
566         } else {
567                 dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY, 0);
568         }
569         if (dfd < 0)
570                 return -1;
571
572         /*
573          * When fdopendir() below succeeds it assumes ownership of the fd so we
574          * to make sure we always have an fd that fdopendir() can own which is
575          * why we dup() in the case where the caller wants us to operate on the
576          * fd directly.
577          */
578         dfd_dup = dup_cloexec(dfd);
579         if (dfd_dup < 0) {
580                 close(dfd);
581                 return -1;
582         }
583
584         dir = fdopendir(dfd);
585         if (!dir) {
586                 close(dfd);
587                 close(dfd_dup);
588                 return -1;
589         }
590         /* Transfer ownership to fdopendir(). */
591         dfd = -EBADF;
592
593         while ((direntp = readdir(dir))) {
594                 if (!strcmp(direntp->d_name, ".") ||
595                     !strcmp(direntp->d_name, ".."))
596                         continue;
597
598                 ret = fstatat(dfd_dup, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
599                 if (ret < 0 && errno != ENOENT)
600                         break;
601
602                 ret = 0;
603                 if (S_ISDIR(st.st_mode))
604                         ret = print_r(dfd_dup, direntp->d_name);
605                 else
606                         fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %d/%s\n",
607                                 (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
608                                 dfd_dup, direntp->d_name);
609                 if (ret < 0 && errno != ENOENT)
610                         break;
611         }
612
613         if (!path || *path == '\0')
614                 ret = fstatat(fd, "", &st,
615                               AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW |
616                               AT_EMPTY_PATH);
617         else
618                 ret = fstatat(fd, path, &st,
619                               AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW);
620         if (!ret)
621                 fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %s",
622                         (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
623                         (path && *path) ? path : "(null)");
624
625         close(dfd_dup);
626         closedir(dir);
627
628         return ret;
629 }
630 #endif
631
632 /* fd_to_fd - transfer data from one fd to another */
633 static int fd_to_fd(int from, int to)
634 {
635         for (;;) {
636                 uint8_t buf[PATH_MAX];
637                 uint8_t *p = buf;
638                 ssize_t bytes_to_write;
639                 ssize_t bytes_read;
640
641                 bytes_read = read_nointr(from, buf, sizeof buf);
642                 if (bytes_read < 0)
643                         return -1;
644                 if (bytes_read == 0)
645                         break;
646
647                 bytes_to_write = (size_t)bytes_read;
648                 do {
649                         ssize_t bytes_written;
650
651                         bytes_written = write_nointr(to, p, bytes_to_write);
652                         if (bytes_written < 0)
653                                 return -1;
654
655                         bytes_to_write -= bytes_written;
656                         p += bytes_written;
657                 } while (bytes_to_write > 0);
658         }
659
660         return 0;
661 }
662
663 static int sys_execveat(int fd, const char *path, char **argv, char **envp,
664                         int flags)
665 {
666 #ifdef __NR_execveat
667         return syscall(__NR_execveat, fd, path, argv, envp, flags);
668 #else
669         errno = ENOSYS;
670         return -1;
671 #endif
672 }
673
674 #ifndef CAP_NET_RAW
675 #define CAP_NET_RAW 13
676 #endif
677
678 #ifndef VFS_CAP_FLAGS_EFFECTIVE
679 #define VFS_CAP_FLAGS_EFFECTIVE 0x000001
680 #endif
681
682 #ifndef VFS_CAP_U32_3
683 #define VFS_CAP_U32_3 2
684 #endif
685
686 #ifndef VFS_CAP_U32
687 #define VFS_CAP_U32 VFS_CAP_U32_3
688 #endif
689
690 #ifndef VFS_CAP_REVISION_1
691 #define VFS_CAP_REVISION_1 0x01000000
692 #endif
693
694 #ifndef VFS_CAP_REVISION_2
695 #define VFS_CAP_REVISION_2 0x02000000
696 #endif
697
698 #ifndef VFS_CAP_REVISION_3
699 #define VFS_CAP_REVISION_3 0x03000000
700 struct vfs_ns_cap_data {
701         __le32 magic_etc;
702         struct {
703                 __le32 permitted;
704                 __le32 inheritable;
705         } data[VFS_CAP_U32];
706         __le32 rootid;
707 };
708 #endif
709
710 #if __BYTE_ORDER == __BIG_ENDIAN
711 #define cpu_to_le16(w16) le16_to_cpu(w16)
712 #define le16_to_cpu(w16) ((u_int16_t)((u_int16_t)(w16) >> 8) | (u_int16_t)((u_int16_t)(w16) << 8))
713 #define cpu_to_le32(w32) le32_to_cpu(w32)
714 #define le32_to_cpu(w32)                                                                       \
715         ((u_int32_t)((u_int32_t)(w32) >> 24) | (u_int32_t)(((u_int32_t)(w32) >> 8) & 0xFF00) | \
716          (u_int32_t)(((u_int32_t)(w32) << 8) & 0xFF0000) | (u_int32_t)((u_int32_t)(w32) << 24))
717 #elif __BYTE_ORDER == __LITTLE_ENDIAN
718 #define cpu_to_le16(w16) ((u_int16_t)(w16))
719 #define le16_to_cpu(w16) ((u_int16_t)(w16))
720 #define cpu_to_le32(w32) ((u_int32_t)(w32))
721 #define le32_to_cpu(w32) ((u_int32_t)(w32))
722 #else
723 #error Expected endianess macro to be set
724 #endif
725
726 /* expected_dummy_vfs_caps_uid - check vfs caps are stored with the provided uid */
727 static bool expected_dummy_vfs_caps_uid(int fd, uid_t expected_uid)
728 {
729 #define __cap_raised_permitted(x, ns_cap_data)                                 \
730         ((ns_cap_data.data[(x) >> 5].permitted) & (1 << ((x)&31)))
731         struct vfs_ns_cap_data ns_xattr = {};
732         ssize_t ret;
733
734         ret = fgetxattr(fd, "security.capability", &ns_xattr, sizeof(ns_xattr));
735         if (ret < 0 || ret == 0)
736                 return false;
737
738         if (ns_xattr.magic_etc & VFS_CAP_REVISION_3) {
739
740                 if (le32_to_cpu(ns_xattr.rootid) != expected_uid) {
741                         errno = EINVAL;
742                         log_stderr("failure: rootid(%d) != expected_rootid(%d)", le32_to_cpu(ns_xattr.rootid), expected_uid);
743                 }
744
745                 return (le32_to_cpu(ns_xattr.rootid) == expected_uid) &&
746                        (__cap_raised_permitted(CAP_NET_RAW, ns_xattr) > 0);
747         } else {
748                 log_stderr("failure: fscaps version");
749         }
750
751         return false;
752 }
753
754 /* set_dummy_vfs_caps - set dummy vfs caps for the provided uid */
755 static int set_dummy_vfs_caps(int fd, int flags, int rootuid)
756 {
757 #define __raise_cap_permitted(x, ns_cap_data)                                  \
758         ns_cap_data.data[(x) >> 5].permitted |= (1 << ((x)&31))
759
760         struct vfs_ns_cap_data ns_xattr;
761
762         memset(&ns_xattr, 0, sizeof(ns_xattr));
763         __raise_cap_permitted(CAP_NET_RAW, ns_xattr);
764         ns_xattr.magic_etc |= VFS_CAP_REVISION_3 | VFS_CAP_FLAGS_EFFECTIVE;
765         ns_xattr.rootid = cpu_to_le32(rootuid);
766
767         return fsetxattr(fd, "security.capability",
768                          &ns_xattr, sizeof(ns_xattr), flags);
769 }
770
771 #define safe_close(fd)      \
772         if (fd >= 0) {           \
773                 int _e_ = errno; \
774                 close(fd);       \
775                 errno = _e_;     \
776                 fd = -EBADF;     \
777         }
778
779 static void test_setup(void)
780 {
781         if (mkdirat(t_mnt_fd, T_DIR1, 0777))
782                 die("failure: mkdirat");
783
784         t_dir1_fd = openat(t_mnt_fd, T_DIR1, O_CLOEXEC | O_DIRECTORY);
785         if (t_dir1_fd < 0)
786                 die("failure: openat");
787
788         if (fchmod(t_dir1_fd, 0777))
789                 die("failure: fchmod");
790 }
791
792 static void test_cleanup(void)
793 {
794         safe_close(t_dir1_fd);
795         if (rm_r(t_mnt_fd, T_DIR1))
796                 die("failure: rm_r");
797 }
798
799 /* Validate that basic file operations on idmapped mounts. */
800 static int fsids_unmapped(void)
801 {
802         int fret = -1;
803         int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
804         struct mount_attr attr = {
805                 .attr_set = MOUNT_ATTR_IDMAP,
806         };
807
808         /* create hardlink target */
809         hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
810         if (hardlink_target_fd < 0) {
811                 log_stderr("failure: openat");
812                 goto out;
813         }
814
815         /* create directory for rename test */
816         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
817                 log_stderr("failure: mkdirat");
818                 goto out;
819         }
820
821         /* change ownership of all files to uid 0 */
822         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
823                 log_stderr("failure: chown_r");
824                 goto out;
825         }
826
827         /* Changing mount properties on a detached mount. */
828         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
829         if (attr.userns_fd < 0) {
830                 log_stderr("failure: get_userns_fd");
831                 goto out;
832         }
833
834         open_tree_fd = sys_open_tree(t_dir1_fd, "",
835                                      AT_EMPTY_PATH |
836                                      AT_NO_AUTOMOUNT |
837                                      AT_SYMLINK_NOFOLLOW |
838                                      OPEN_TREE_CLOEXEC |
839                                      OPEN_TREE_CLONE);
840         if (open_tree_fd < 0) {
841                 log_stderr("failure: sys_open_tree");
842                 goto out;
843         }
844
845         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
846                 log_stderr("failure: sys_mount_setattr");
847                 goto out;
848         }
849
850         if (!switch_fsids(0, 0)) {
851                 log_stderr("failure: switch_fsids");
852                 goto out;
853         }
854
855         /* The caller's fsids don't have a mappings in the idmapped mount so any
856          * file creation must fail.
857          */
858
859         /* create hardlink */
860         if (!linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
861                 log_stderr("failure: linkat");
862                 goto out;
863         }
864         if (errno != EOVERFLOW) {
865                 log_stderr("failure: errno");
866                 goto out;
867         }
868
869         /* try to rename a file */
870         if (!renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME)) {
871                 log_stderr("failure: renameat");
872                 goto out;
873         }
874         if (errno != EOVERFLOW) {
875                 log_stderr("failure: errno");
876                 goto out;
877         }
878
879         /* try to rename a directory */
880         if (!renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME)) {
881                 log_stderr("failure: renameat");
882                 goto out;
883         }
884         if (errno != EOVERFLOW) {
885                 log_stderr("failure: errno");
886                 goto out;
887         }
888
889         /* The caller is privileged over the inode so file deletion must work. */
890
891         /* remove file */
892         if (unlinkat(open_tree_fd, FILE1, 0)) {
893                 log_stderr("failure: unlinkat");
894                 goto out;
895         }
896
897         /* remove directory */
898         if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR)) {
899                 log_stderr("failure: unlinkat");
900                 goto out;
901         }
902
903         /* The caller's fsids don't have a mappings in the idmapped mount so
904          * any file creation must fail.
905          */
906
907         /* create regular file via open() */
908         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
909         if (file1_fd >= 0) {
910                 log_stderr("failure: create");
911                 goto out;
912         }
913         if (errno != EOVERFLOW) {
914                 log_stderr("failure: errno");
915                 goto out;
916         }
917
918         /* create regular file via mknod */
919         if (!mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0)) {
920                 log_stderr("failure: mknodat");
921                 goto out;
922         }
923         if (errno != EOVERFLOW) {
924                 log_stderr("failure: errno");
925                 goto out;
926         }
927
928         /* create character device */
929         if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
930                 log_stderr("failure: mknodat");
931                 goto out;
932         }
933         if (errno != EOVERFLOW) {
934                 log_stderr("failure: errno");
935                 goto out;
936         }
937
938         /* create symlink */
939         if (!symlinkat(FILE2, open_tree_fd, SYMLINK1)) {
940                 log_stderr("failure: symlinkat");
941                 goto out;
942         }
943         if (errno != EOVERFLOW) {
944                 log_stderr("failure: errno");
945                 goto out;
946         }
947
948         /* create directory */
949         if (!mkdirat(open_tree_fd, DIR1, 0700)) {
950                 log_stderr("failure: mkdirat");
951                 goto out;
952         }
953         if (errno != EOVERFLOW) {
954                 log_stderr("failure: errno");
955                 goto out;
956         }
957
958         fret = 0;
959         log_debug("Ran test");
960 out:
961         safe_close(attr.userns_fd);
962         safe_close(hardlink_target_fd);
963         safe_close(file1_fd);
964         safe_close(open_tree_fd);
965
966         return fret;
967 }
968
969 static int fsids_mapped(void)
970 {
971         int fret = -1;
972         int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
973         struct mount_attr attr = {
974                 .attr_set = MOUNT_ATTR_IDMAP,
975         };
976         pid_t pid;
977
978         if (!caps_supported())
979                 return 0;
980
981         /* create hardlink target */
982         hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
983         if (hardlink_target_fd < 0) {
984                 log_stderr("failure: openat");
985                 goto out;
986         }
987
988         /* create directory for rename test */
989         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
990                 log_stderr("failure: mkdirat");
991                 goto out;
992         }
993
994         /* change ownership of all files to uid 0 */
995         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
996                 log_stderr("failure: chown_r");
997                 goto out;
998         }
999
1000         /* Changing mount properties on a detached mount. */
1001         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1002         if (attr.userns_fd < 0) {
1003                 log_stderr("failure: get_userns_fd");
1004                 goto out;
1005         }
1006
1007         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1008                                      AT_EMPTY_PATH |
1009                                      AT_NO_AUTOMOUNT |
1010                                      AT_SYMLINK_NOFOLLOW |
1011                                      OPEN_TREE_CLOEXEC |
1012                                      OPEN_TREE_CLONE);
1013         if (open_tree_fd < 0) {
1014                 log_stderr("failure: sys_open_tree");
1015                 goto out;
1016         }
1017
1018         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1019                 log_stderr("failure: sys_mount_setattr");
1020                 goto out;
1021         }
1022
1023         pid = fork();
1024         if (pid < 0) {
1025                 log_stderr("failure: fork");
1026                 goto out;
1027         }
1028         if (pid == 0) {
1029                 if (!switch_fsids(10000, 10000))
1030                         die("failure: switch fsids");
1031
1032                 if (!caps_up())
1033                         die("failure: raise caps");
1034
1035                 /* The caller's fsids now have mappings in the idmapped mount so
1036                  * any file creation must fail.
1037                  */
1038
1039                 /* create hardlink */
1040                 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1041                         die("failure: create hardlink");
1042
1043                 /* try to rename a file */
1044                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1045                         die("failure: rename");
1046
1047                 /* try to rename a directory */
1048                 if (renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME))
1049                         die("failure: rename");
1050
1051                 /* remove file */
1052                 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1053                         die("failure: delete");
1054
1055                 /* remove directory */
1056                 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1057                         die("failure: delete");
1058
1059                 /* The caller's fsids have mappings in the idmapped mount so any
1060                  * file creation must fail.
1061                  */
1062
1063                 /* create regular file via open() */
1064                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1065                 if (file1_fd < 0)
1066                         die("failure: create");
1067
1068                 /* create regular file via mknod */
1069                 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1070                         die("failure: create");
1071
1072                 /* create character device */
1073                 if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
1074                         die("failure: create");
1075
1076                 /* create symlink */
1077                 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1078                         die("failure: create");
1079
1080                 /* create directory */
1081                 if (mkdirat(open_tree_fd, DIR1, 0700))
1082                         die("failure: create");
1083
1084                 exit(EXIT_SUCCESS);
1085         }
1086         if (wait_for_pid(pid))
1087                 goto out;
1088
1089         fret = 0;
1090         log_debug("Ran test");
1091 out:
1092         safe_close(attr.userns_fd);
1093         safe_close(file1_fd);
1094         safe_close(hardlink_target_fd);
1095         safe_close(open_tree_fd);
1096
1097         return fret;
1098 }
1099
1100 /* Validate that basic file operations on idmapped mounts from a user namespace. */
1101 static int create_in_userns(void)
1102 {
1103         int fret = -1;
1104         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1105         struct mount_attr attr = {
1106                 .attr_set = MOUNT_ATTR_IDMAP,
1107         };
1108         pid_t pid;
1109
1110         /* change ownership of all files to uid 0 */
1111         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1112                 log_stderr("failure: chown_r");
1113                 goto out;
1114         }
1115
1116         /* Changing mount properties on a detached mount. */
1117         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1118         if (attr.userns_fd < 0) {
1119                 log_stderr("failure: get_userns_fd");
1120                 goto out;
1121         }
1122
1123         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1124                                      AT_EMPTY_PATH |
1125                                      AT_NO_AUTOMOUNT |
1126                                      AT_SYMLINK_NOFOLLOW |
1127                                      OPEN_TREE_CLOEXEC |
1128                                      OPEN_TREE_CLONE);
1129         if (open_tree_fd < 0) {
1130                 log_stderr("failure: sys_open_tree");
1131                 goto out;
1132         }
1133
1134         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1135                 log_stderr("failure: sys_mount_setattr");
1136                 goto out;
1137         }
1138
1139         pid = fork();
1140         if (pid < 0) {
1141                 log_stderr("failure: fork");
1142                 goto out;
1143         }
1144         if (pid == 0) {
1145                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1146                         die("failure: switch_userns");
1147
1148                 /* create regular file via open() */
1149                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1150                 if (file1_fd < 0)
1151                         die("failure: open file");
1152                 safe_close(file1_fd);
1153
1154                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1155                         die("failure: check ownership");
1156
1157                 /* create regular file via mknod */
1158                 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1159                         die("failure: create");
1160
1161                 if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
1162                         die("failure: check ownership");
1163
1164                 /* create symlink */
1165                 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1166                         die("failure: create");
1167
1168                 if (!expected_uid_gid(open_tree_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0))
1169                         die("failure: check ownership");
1170
1171                 /* create directory */
1172                 if (mkdirat(open_tree_fd, DIR1, 0700))
1173                         die("failure: create");
1174
1175                 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
1176                         die("failure: check ownership");
1177
1178                 /* try to rename a file */
1179                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1180                         die("failure: create");
1181
1182                 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1183                         die("failure: check ownership");
1184
1185                 /* try to rename a file */
1186                 if (renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME))
1187                         die("failure: create");
1188
1189                 if (!expected_uid_gid(open_tree_fd, DIR1_RENAME, 0, 0, 0))
1190                         die("failure: check ownership");
1191
1192                 /* remove file */
1193                 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1194                         die("failure: remove");
1195
1196                 /* remove directory */
1197                 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1198                         die("failure: remove");
1199
1200                 exit(EXIT_SUCCESS);
1201         }
1202
1203         if (wait_for_pid(pid))
1204                 goto out;
1205
1206         fret = 0;
1207         log_debug("Ran test");
1208 out:
1209         safe_close(attr.userns_fd);
1210         safe_close(file1_fd);
1211         safe_close(open_tree_fd);
1212
1213         return fret;
1214 }
1215
1216 static int hardlink_crossing_mounts(void)
1217 {
1218         int fret = -1;
1219         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1220
1221         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1222                 log_stderr("failure: chown_r");
1223                 goto out;
1224         }
1225
1226         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1227                                      AT_EMPTY_PATH |
1228                                      AT_NO_AUTOMOUNT |
1229                                      AT_SYMLINK_NOFOLLOW |
1230                                      OPEN_TREE_CLOEXEC |
1231                                      OPEN_TREE_CLONE);
1232         if (open_tree_fd < 0) {
1233                 log_stderr("failure: sys_open_tree");
1234                 goto out;
1235         }
1236
1237         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1238         if (file1_fd < 0) {
1239                 log_stderr("failure: openat");
1240                 goto out;
1241         }
1242
1243         if (mkdirat(open_tree_fd, DIR1, 0777)) {
1244                 log_stderr("failure: mkdirat");
1245                 goto out;
1246         }
1247
1248         /* We're crossing a mountpoint so this must fail.
1249          *
1250          * Note that this must also fail for non-idmapped mounts but here we're
1251          * interested in making sure we're not introducing an accidental way to
1252          * violate that restriction or that suddenly this becomes possible.
1253          */
1254         if (!linkat(open_tree_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
1255                 log_stderr("failure: linkat");
1256                 goto out;
1257         }
1258         if (errno != EXDEV) {
1259                 log_stderr("failure: errno");
1260                 goto out;
1261         }
1262
1263         fret = 0;
1264         log_debug("Ran test");
1265 out:
1266         safe_close(file1_fd);
1267         safe_close(open_tree_fd);
1268
1269         return fret;
1270 }
1271
1272 static int hardlink_crossing_idmapped_mounts(void)
1273 {
1274         int fret = -1;
1275         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1276         struct mount_attr attr = {
1277                 .attr_set = MOUNT_ATTR_IDMAP,
1278         };
1279
1280         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1281                 log_stderr("failure: chown_r");
1282                 goto out;
1283         }
1284
1285         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1286         if (attr.userns_fd < 0) {
1287                 log_stderr("failure: get_userns_fd");
1288                 goto out;
1289         }
1290
1291         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1292                                      AT_EMPTY_PATH |
1293                                      AT_NO_AUTOMOUNT |
1294                                      AT_SYMLINK_NOFOLLOW |
1295                                      OPEN_TREE_CLOEXEC |
1296                                      OPEN_TREE_CLONE);
1297         if (open_tree_fd1 < 0) {
1298                 log_stderr("failure: sys_open_tree");
1299                 goto out;
1300         }
1301
1302         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1303                 log_stderr("failure: sys_mount_setattr");
1304                 goto out;
1305         }
1306
1307         file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1308         if (file1_fd < 0) {
1309                 log_stderr("failure: openat");
1310                 goto out;
1311         }
1312
1313         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1314                 log_stderr("failure: expected_uid_gid");
1315                 goto out;
1316         }
1317
1318         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1319                 log_stderr("failure: expected_uid_gid");
1320                 goto out;
1321         }
1322
1323         safe_close(file1_fd);
1324
1325         if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1326                 log_stderr("failure: mkdirat");
1327                 goto out;
1328         }
1329
1330         open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1331                                       AT_NO_AUTOMOUNT |
1332                                       AT_SYMLINK_NOFOLLOW |
1333                                       OPEN_TREE_CLOEXEC |
1334                                       OPEN_TREE_CLONE |
1335                                       AT_RECURSIVE);
1336         if (open_tree_fd2 < 0) {
1337                 log_stderr("failure: sys_open_tree");
1338                 goto out;
1339         }
1340
1341         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1342                 log_stderr("failure: sys_mount_setattr");
1343                 goto out;
1344         }
1345
1346         /* We're crossing a mountpoint so this must fail.
1347          *
1348          * Note that this must also fail for non-idmapped mounts but here we're
1349          * interested in making sure we're not introducing an accidental way to
1350          * violate that restriction or that suddenly this becomes possible.
1351          */
1352         if (!linkat(open_tree_fd1, FILE1, open_tree_fd2, HARDLINK1, 0)) {
1353                 log_stderr("failure: linkat");
1354                 goto out;
1355         }
1356         if (errno != EXDEV) {
1357                 log_stderr("failure: errno");
1358                 goto out;
1359         }
1360
1361         fret = 0;
1362         log_debug("Ran test");
1363 out:
1364         safe_close(attr.userns_fd);
1365         safe_close(file1_fd);
1366         safe_close(open_tree_fd1);
1367         safe_close(open_tree_fd2);
1368
1369         return fret;
1370 }
1371
1372 static int hardlink_from_idmapped_mount(void)
1373 {
1374         int fret = -1;
1375         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1376         struct mount_attr attr = {
1377                 .attr_set = MOUNT_ATTR_IDMAP,
1378         };
1379
1380         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1381                 log_stderr("failure: chown_r");
1382                 goto out;
1383         }
1384
1385         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1386         if (attr.userns_fd < 0) {
1387                 log_stderr("failure: get_userns_fd");
1388                 goto out;
1389         }
1390
1391         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1392                                      AT_EMPTY_PATH |
1393                                      AT_NO_AUTOMOUNT |
1394                                      AT_SYMLINK_NOFOLLOW |
1395                                      OPEN_TREE_CLOEXEC |
1396                                      OPEN_TREE_CLONE);
1397         if (open_tree_fd < 0) {
1398                 log_stderr("failure: sys_open_tree");
1399                 goto out;
1400         }
1401
1402         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1403                 log_stderr("failure: sys_mount_setattr");
1404                 goto out;
1405         }
1406
1407         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1408         if (file1_fd < 0) {
1409                 log_stderr("failure: openat");
1410                 goto out;
1411         }
1412         safe_close(file1_fd);
1413
1414         if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1415                 log_stderr("failure: expected_uid_gid");
1416                 goto out;
1417         }
1418
1419         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1420                 log_stderr("failure: expected_uid_gid");
1421                 goto out;
1422         }
1423
1424         /* We're not crossing a mountpoint so this must succeed. */
1425         if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
1426                 log_stderr("failure: linkat");
1427                 goto out;
1428         }
1429
1430
1431         fret = 0;
1432         log_debug("Ran test");
1433 out:
1434         safe_close(attr.userns_fd);
1435         safe_close(file1_fd);
1436         safe_close(open_tree_fd);
1437
1438         return fret;
1439 }
1440
1441 static int hardlink_from_idmapped_mount_in_userns(void)
1442 {
1443         int fret = -1;
1444         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1445         struct mount_attr attr = {
1446                 .attr_set = MOUNT_ATTR_IDMAP,
1447         };
1448         pid_t pid;
1449
1450         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1451                 log_stderr("failure: chown_r");
1452                 goto out;
1453         }
1454
1455         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1456         if (attr.userns_fd < 0) {
1457                 log_stderr("failure: get_userns_fd");
1458                 goto out;
1459         }
1460
1461         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1462                                      AT_EMPTY_PATH |
1463                                      AT_NO_AUTOMOUNT |
1464                                      AT_SYMLINK_NOFOLLOW |
1465                                      OPEN_TREE_CLOEXEC |
1466                                      OPEN_TREE_CLONE);
1467         if (open_tree_fd < 0) {
1468                 log_stderr("failure: sys_open_tree");
1469                 goto out;
1470         }
1471
1472         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1473                 log_stderr("failure: sys_mount_setattr");
1474                 goto out;
1475         }
1476
1477         pid = fork();
1478         if (pid < 0) {
1479                 log_stderr("failure: fork");
1480                 goto out;
1481         }
1482         if (pid == 0) {
1483                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1484                         die("failure: switch_userns");
1485
1486                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1487                 if (file1_fd < 0)
1488                         die("failure: create");
1489
1490                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1491                         die("failure: check ownership");
1492
1493                 /* We're not crossing a mountpoint so this must succeed. */
1494                 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1495                         die("failure: create");
1496
1497                 if (!expected_uid_gid(open_tree_fd, HARDLINK1, 0, 0, 0))
1498                         die("failure: check ownership");
1499
1500                 exit(EXIT_SUCCESS);
1501         }
1502
1503         if (wait_for_pid(pid))
1504                 goto out;
1505
1506         fret = 0;
1507         log_debug("Ran test");
1508 out:
1509         safe_close(attr.userns_fd);
1510         safe_close(file1_fd);
1511         safe_close(open_tree_fd);
1512
1513         return fret;
1514 }
1515
1516 static int rename_crossing_mounts(void)
1517 {
1518         int fret = -1;
1519         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1520
1521         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1522                 log_stderr("failure: chown_r");
1523                 goto out;
1524         }
1525
1526         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1527                                      AT_EMPTY_PATH |
1528                                      AT_NO_AUTOMOUNT |
1529                                      AT_SYMLINK_NOFOLLOW |
1530                                      OPEN_TREE_CLOEXEC |
1531                                      OPEN_TREE_CLONE);
1532         if (open_tree_fd < 0) {
1533                 log_stderr("failure: sys_open_tree");
1534                 goto out;
1535         }
1536
1537         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1538         if (file1_fd < 0) {
1539                 log_stderr("failure: openat");
1540                 goto out;
1541         }
1542
1543         if (mkdirat(open_tree_fd, DIR1, 0777)) {
1544                 log_stderr("failure: mkdirat");
1545                 goto out;
1546         }
1547
1548         /* We're crossing a mountpoint so this must fail.
1549          *
1550          * Note that this must also fail for non-idmapped mounts but here we're
1551          * interested in making sure we're not introducing an accidental way to
1552          * violate that restriction or that suddenly this becomes possible.
1553          */
1554         if (!renameat(open_tree_fd, FILE1, t_dir1_fd, FILE1_RENAME)) {
1555                 log_stderr("failure: renameat");
1556                 goto out;
1557         }
1558         if (errno != EXDEV) {
1559                 log_stderr("failure: errno");
1560                 goto out;
1561         }
1562
1563         fret = 0;
1564         log_debug("Ran test");
1565 out:
1566         safe_close(file1_fd);
1567         safe_close(open_tree_fd);
1568
1569         return fret;
1570 }
1571
1572 static int rename_crossing_idmapped_mounts(void)
1573 {
1574         int fret = -1;
1575         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1576         struct mount_attr attr = {
1577                 .attr_set = MOUNT_ATTR_IDMAP,
1578         };
1579
1580         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1581                 log_stderr("failure: chown_r");
1582                 goto out;
1583         }
1584
1585         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1586         if (attr.userns_fd < 0) {
1587                 log_stderr("failure: get_userns_fd");
1588                 goto out;
1589         }
1590
1591         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1592                                      AT_EMPTY_PATH |
1593                                      AT_NO_AUTOMOUNT |
1594                                      AT_SYMLINK_NOFOLLOW |
1595                                      OPEN_TREE_CLOEXEC |
1596                                      OPEN_TREE_CLONE);
1597         if (open_tree_fd1 < 0) {
1598                 log_stderr("failure: sys_open_tree");
1599                 goto out;
1600         }
1601
1602         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1603                 log_stderr("failure: sys_mount_setattr");
1604                 goto out;
1605         }
1606
1607         file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1608         if (file1_fd < 0) {
1609                 log_stderr("failure: openat");
1610                 goto out;
1611         }
1612
1613         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1614                 log_stderr("failure: expected_uid_gid");
1615                 goto out;
1616         }
1617
1618         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1619                 log_stderr("failure: expected_uid_gid");
1620                 goto out;
1621         }
1622
1623         if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1624                 log_stderr("failure: mkdirat");
1625                 goto out;
1626         }
1627
1628         open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1629                                       AT_NO_AUTOMOUNT |
1630                                       AT_SYMLINK_NOFOLLOW |
1631                                       OPEN_TREE_CLOEXEC |
1632                                       OPEN_TREE_CLONE |
1633                                       AT_RECURSIVE);
1634         if (open_tree_fd2 < 0) {
1635                 log_stderr("failure: sys_open_tree");
1636                 goto out;
1637         }
1638
1639         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1640                 log_stderr("failure: sys_mount_setattr");
1641                 goto out;
1642         }
1643
1644         /* We're crossing a mountpoint so this must fail.
1645          *
1646          * Note that this must also fail for non-idmapped mounts but here we're
1647          * interested in making sure we're not introducing an accidental way to
1648          * violate that restriction or that suddenly this becomes possible.
1649          */
1650         if (!renameat(open_tree_fd1, FILE1, open_tree_fd2, FILE1_RENAME)) {
1651                 log_stderr("failure: renameat");
1652                 goto out;
1653         }
1654         if (errno != EXDEV) {
1655                 log_stderr("failure: errno");
1656                 goto out;
1657         }
1658
1659         fret = 0;
1660         log_debug("Ran test");
1661 out:
1662         safe_close(attr.userns_fd);
1663         safe_close(file1_fd);
1664         safe_close(open_tree_fd1);
1665         safe_close(open_tree_fd2);
1666
1667         return fret;
1668 }
1669
1670 static int rename_from_idmapped_mount(void)
1671 {
1672         int fret = -1;
1673         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1674         struct mount_attr attr = {
1675                 .attr_set = MOUNT_ATTR_IDMAP,
1676         };
1677
1678         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1679                 log_stderr("failure: chown_r");
1680                 goto out;
1681         }
1682
1683         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1684         if (attr.userns_fd < 0) {
1685                 log_stderr("failure: get_userns_fd");
1686                 goto out;
1687         }
1688
1689         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1690                                      AT_EMPTY_PATH |
1691                                      AT_NO_AUTOMOUNT |
1692                                      AT_SYMLINK_NOFOLLOW |
1693                                      OPEN_TREE_CLOEXEC |
1694                                      OPEN_TREE_CLONE);
1695         if (open_tree_fd < 0) {
1696                 log_stderr("failure: sys_open_tree");
1697                 goto out;
1698         }
1699
1700         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1701                 log_stderr("failure: sys_mount_setattr");
1702                 goto out;
1703         }
1704
1705         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1706         if (file1_fd < 0) {
1707                 log_stderr("failure: openat");
1708                 goto out;
1709         }
1710
1711         if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1712                 log_stderr("failure: expected_uid_gid");
1713                 goto out;
1714         }
1715
1716         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1717                 log_stderr("failure: expected_uid_gid");
1718                 goto out;
1719         }
1720
1721         /* We're not crossing a mountpoint so this must succeed. */
1722         if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME)) {
1723                 log_stderr("failure: renameat");
1724                 goto out;
1725         }
1726
1727         fret = 0;
1728         log_debug("Ran test");
1729 out:
1730         safe_close(attr.userns_fd);
1731         safe_close(file1_fd);
1732         safe_close(open_tree_fd);
1733
1734         return fret;
1735 }
1736
1737 static int rename_from_idmapped_mount_in_userns(void)
1738 {
1739         int fret = -1;
1740         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1741         pid_t pid;
1742         struct mount_attr attr = {
1743                 .attr_set = MOUNT_ATTR_IDMAP,
1744         };
1745
1746         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1747                 log_stderr("failure: chown_r");
1748                 goto out;
1749         }
1750
1751         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1752         if (attr.userns_fd < 0) {
1753                 log_stderr("failure: get_userns_fd");
1754                 goto out;
1755         }
1756
1757         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1758                                      AT_EMPTY_PATH |
1759                                      AT_NO_AUTOMOUNT |
1760                                      AT_SYMLINK_NOFOLLOW |
1761                                      OPEN_TREE_CLOEXEC |
1762                                      OPEN_TREE_CLONE);
1763         if (open_tree_fd < 0) {
1764                 log_stderr("failure: sys_open_tree");
1765                 goto out;
1766         }
1767
1768         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1769                 log_stderr("failure: sys_mount_setattr");
1770                 goto out;
1771         }
1772
1773         pid = fork();
1774         if (pid < 0) {
1775                 log_stderr("failure: fork");
1776                 goto out;
1777         }
1778         if (pid == 0) {
1779                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1780                         die("failure: switch_userns");
1781
1782                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1783                 if (file1_fd < 0)
1784                         die("failure: create");
1785
1786                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1787                         die("failure: check ownership");
1788
1789                 /* We're not crossing a mountpoint so this must succeed. */
1790                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1791                         die("failure: create");
1792
1793                 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1794                         die("failure: check ownership");
1795
1796                 exit(EXIT_SUCCESS);
1797         }
1798
1799         if (wait_for_pid(pid))
1800                 goto out;
1801
1802         fret = 0;
1803         log_debug("Ran test");
1804 out:
1805         safe_close(attr.userns_fd);
1806         safe_close(file1_fd);
1807         safe_close(open_tree_fd);
1808
1809         return fret;
1810 }
1811
1812 static int symlink_regular_mounts(void)
1813 {
1814         int fret = -1;
1815         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1816         struct stat st;
1817
1818         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1819         if (file1_fd < 0) {
1820                 log_stderr("failure: openat");
1821                 goto out;
1822         }
1823
1824         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1825                 log_stderr("failure: chown_r");
1826                 goto out;
1827         }
1828
1829         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1830                                      AT_EMPTY_PATH |
1831                                      AT_NO_AUTOMOUNT |
1832                                      AT_SYMLINK_NOFOLLOW |
1833                                      OPEN_TREE_CLOEXEC |
1834                                      OPEN_TREE_CLONE);
1835         if (open_tree_fd < 0) {
1836                 log_stderr("failure: sys_open_tree");
1837                 goto out;
1838         }
1839
1840         if (symlinkat(FILE1, open_tree_fd, FILE2)) {
1841                 log_stderr("failure: symlinkat");
1842                 goto out;
1843         }
1844
1845         if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW)) {
1846                 log_stderr("failure: fchownat");
1847                 goto out;
1848         }
1849
1850         if (fstatat(open_tree_fd, FILE2, &st, AT_SYMLINK_NOFOLLOW)) {
1851                 log_stderr("failure: fstatat");
1852                 goto out;
1853         }
1854
1855         if (st.st_uid != 15000 || st.st_gid != 15000) {
1856                 log_stderr("failure: compare ids");
1857                 goto out;
1858         }
1859
1860         if (fstatat(open_tree_fd, FILE1, &st, 0)) {
1861                 log_stderr("failure: fstatat");
1862                 goto out;
1863         }
1864
1865         if (st.st_uid != 10000 || st.st_gid != 10000) {
1866                 log_stderr("failure: compare ids");
1867                 goto out;
1868         }
1869
1870         fret = 0;
1871         log_debug("Ran test");
1872 out:
1873         safe_close(file1_fd);
1874         safe_close(open_tree_fd);
1875
1876         return fret;
1877 }
1878
1879 static int symlink_idmapped_mounts(void)
1880 {
1881         int fret = -1;
1882         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1883         struct mount_attr attr = {
1884                 .attr_set = MOUNT_ATTR_IDMAP,
1885         };
1886         pid_t pid;
1887
1888         if (!caps_supported())
1889                 return 0;
1890
1891         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1892         if (file1_fd < 0) {
1893                 log_stderr("failure: openat");
1894                 goto out;
1895         }
1896
1897         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1898                 log_stderr("failure: chown_r");
1899                 goto out;
1900         }
1901
1902         /* Changing mount properties on a detached mount. */
1903         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1904         if (attr.userns_fd < 0) {
1905                 log_stderr("failure: get_userns_fd");
1906                 goto out;
1907         }
1908
1909         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1910                                      AT_EMPTY_PATH |
1911                                      AT_NO_AUTOMOUNT |
1912                                      AT_SYMLINK_NOFOLLOW |
1913                                      OPEN_TREE_CLOEXEC |
1914                                      OPEN_TREE_CLONE);
1915         if (open_tree_fd < 0) {
1916                 log_stderr("failure: sys_open_tree");
1917                 goto out;
1918         }
1919
1920         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1921                 log_stderr("failure: sys_mount_setattr");
1922                 goto out;
1923         }
1924
1925         pid = fork();
1926         if (pid < 0) {
1927                 log_stderr("failure: fork");
1928                 goto out;
1929         }
1930         if (pid == 0) {
1931                 if (!switch_fsids(10000, 10000))
1932                         die("failure: switch fsids");
1933
1934                 if (!caps_up())
1935                         die("failure: raise caps");
1936
1937                 if (symlinkat(FILE1, open_tree_fd, FILE2))
1938                         die("failure: create");
1939
1940                 if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW))
1941                         die("failure: change ownership");
1942
1943                 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 15000, 15000))
1944                         die("failure: check ownership");
1945
1946                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
1947                         die("failure: check ownership");
1948
1949                 exit(EXIT_SUCCESS);
1950         }
1951         if (wait_for_pid(pid))
1952                 goto out;
1953
1954         fret = 0;
1955         log_debug("Ran test");
1956 out:
1957         safe_close(attr.userns_fd);
1958         safe_close(file1_fd);
1959         safe_close(open_tree_fd);
1960
1961         return fret;
1962 }
1963
1964 static int symlink_idmapped_mounts_in_userns(void)
1965 {
1966         int fret = -1;
1967         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1968         struct mount_attr attr = {
1969                 .attr_set = MOUNT_ATTR_IDMAP,
1970         };
1971         pid_t pid;
1972
1973         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1974                 log_stderr("failure: chown_r");
1975                 goto out;
1976         }
1977
1978         /* Changing mount properties on a detached mount. */
1979         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1980         if (attr.userns_fd < 0) {
1981                 log_stderr("failure: get_userns_fd");
1982                 goto out;
1983         }
1984
1985         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1986                                      AT_EMPTY_PATH |
1987                                      AT_NO_AUTOMOUNT |
1988                                      AT_SYMLINK_NOFOLLOW |
1989                                      OPEN_TREE_CLOEXEC |
1990                                      OPEN_TREE_CLONE);
1991         if (open_tree_fd < 0) {
1992                 log_stderr("failure: sys_open_tree");
1993                 goto out;
1994         }
1995
1996         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1997                 log_stderr("failure: sys_mount_setattr");
1998                 goto out;
1999         }
2000
2001         pid = fork();
2002         if (pid < 0) {
2003                 log_stderr("failure: fork");
2004                 goto out;
2005         }
2006         if (pid == 0) {
2007                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2008                         die("failure: switch_userns");
2009
2010                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2011                 if (file1_fd < 0)
2012                         die("failure: create");
2013                 safe_close(file1_fd);
2014
2015                 if (symlinkat(FILE1, open_tree_fd, FILE2))
2016                         die("failure: create");
2017
2018                 if (fchownat(open_tree_fd, FILE2, 5000, 5000, AT_SYMLINK_NOFOLLOW))
2019                         die("failure: change ownership");
2020
2021                 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000))
2022                         die("failure: check ownership");
2023
2024                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
2025                         die("failure: check ownership");
2026
2027                 exit(EXIT_SUCCESS);
2028         }
2029
2030         if (wait_for_pid(pid))
2031                 goto out;
2032
2033         if (!expected_uid_gid(t_dir1_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000)) {
2034                 log_stderr("failure: expected_uid_gid");
2035                 goto out;
2036         }
2037
2038         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2039                 log_stderr("failure: expected_uid_gid");
2040                 goto out;
2041         }
2042
2043         fret = 0;
2044         log_debug("Ran test");
2045 out:
2046         safe_close(attr.userns_fd);
2047         safe_close(file1_fd);
2048         safe_close(open_tree_fd);
2049
2050         return fret;
2051 }
2052
2053 /* Validate that a caller whose fsids map into the idmapped mount within it's
2054  * user namespace cannot create any device nodes.
2055  */
2056 static int device_node_in_userns(void)
2057 {
2058         int fret = -1;
2059         int open_tree_fd = -EBADF;
2060         struct mount_attr attr = {
2061                 .attr_set = MOUNT_ATTR_IDMAP,
2062         };
2063         pid_t pid;
2064
2065         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2066         if (attr.userns_fd < 0) {
2067                 log_stderr("failure: get_userns_fd");
2068                 goto out;
2069         }
2070
2071         open_tree_fd = sys_open_tree(t_dir1_fd, "",
2072                                      AT_EMPTY_PATH |
2073                                      AT_NO_AUTOMOUNT |
2074                                      AT_SYMLINK_NOFOLLOW |
2075                                      OPEN_TREE_CLOEXEC |
2076                                      OPEN_TREE_CLONE);
2077         if (open_tree_fd < 0) {
2078                 log_stderr("failure: sys_open_tree");
2079                 goto out;
2080         }
2081
2082         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2083                 log_stderr("failure: sys_mount_setattr");
2084                 goto out;
2085         }
2086
2087         pid = fork();
2088         if (pid < 0) {
2089                 log_stderr("failure: fork");
2090                 goto out;
2091         }
2092         if (pid == 0) {
2093                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2094                         die("failure: switch_userns");
2095
2096                 /* create character device */
2097                 if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
2098                         die("failure: create");
2099
2100                 exit(EXIT_SUCCESS);
2101         }
2102
2103         if (wait_for_pid(pid))
2104                 goto out;
2105
2106         fret = 0;
2107         log_debug("Ran test");
2108 out:
2109         safe_close(attr.userns_fd);
2110         safe_close(open_tree_fd);
2111
2112         return fret;
2113 }
2114
2115
2116 /* Validate that changing file ownership works correctly on idmapped mounts. */
2117 static int expected_uid_gid_idmapped_mounts(void)
2118 {
2119         int fret = -1;
2120         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
2121         struct mount_attr attr1 = {
2122                 .attr_set = MOUNT_ATTR_IDMAP,
2123         };
2124         struct mount_attr attr2 = {
2125                 .attr_set = MOUNT_ATTR_IDMAP,
2126         };
2127         pid_t pid;
2128
2129         if (!switch_fsids(0, 0)) {
2130                 log_stderr("failure: switch_fsids");
2131                 goto out;
2132         }
2133
2134         /* create regular file via open() */
2135         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2136         if (file1_fd < 0) {
2137                 log_stderr("failure: openat");
2138                 goto out;
2139         }
2140
2141         /* create regular file via mknod */
2142         if (mknodat(t_dir1_fd, FILE2, S_IFREG | 0000, 0)) {
2143                 log_stderr("failure: mknodat");
2144                 goto out;
2145         }
2146
2147         /* create character device */
2148         if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
2149                 log_stderr("failure: mknodat");
2150                 goto out;
2151         }
2152
2153         /* create hardlink */
2154         if (linkat(t_dir1_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
2155                 log_stderr("failure: linkat");
2156                 goto out;
2157         }
2158
2159         /* create symlink */
2160         if (symlinkat(FILE2, t_dir1_fd, SYMLINK1)) {
2161                 log_stderr("failure: symlinkat");
2162                 goto out;
2163         }
2164
2165         /* create directory */
2166         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
2167                 log_stderr("failure: mkdirat");
2168                 goto out;
2169         }
2170
2171         /* Changing mount properties on a detached mount. */
2172         attr1.userns_fd = get_userns_fd(0, 10000, 10000);
2173         if (attr1.userns_fd < 0) {
2174                 log_stderr("failure: get_userns_fd");
2175                 goto out;
2176         }
2177
2178         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
2179                                      AT_EMPTY_PATH |
2180                                      AT_NO_AUTOMOUNT |
2181                                      AT_SYMLINK_NOFOLLOW |
2182                                      OPEN_TREE_CLOEXEC |
2183                                      OPEN_TREE_CLONE);
2184         if (open_tree_fd1 < 0) {
2185                 log_stderr("failure: sys_open_tree");
2186                 goto out;
2187         }
2188
2189         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr1, sizeof(attr1))) {
2190                 log_stderr("failure: sys_mount_setattr");
2191                 goto out;
2192         }
2193
2194         /* Validate that all files created through the image mountpoint are
2195          * owned by the callers fsuid and fsgid.
2196          */
2197         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2198                 log_stderr("failure: expected_uid_gid");
2199                 goto out;
2200         }
2201         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2202                 log_stderr("failure: expected_uid_gid");
2203                 goto out;
2204         }
2205         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2206                 log_stderr("failure: expected_uid_gid");
2207                 goto out;
2208         }
2209         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2210                 log_stderr("failure: expected_uid_gid");
2211                 goto out;
2212         }
2213         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
2214                 log_stderr("failure: expected_uid_gid");
2215                 goto out;
2216         }
2217         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2218                 log_stderr("failure: expected_uid_gid");
2219                 goto out;
2220         }
2221         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2222                 log_stderr("failure: expected_uid_gid");
2223                 goto out;
2224         }
2225
2226         /* Validate that all files are owned by the uid and gid specified in
2227          * the idmapping of the mount they are accessed from.
2228          */
2229         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2230                 log_stderr("failure: expected_uid_gid");
2231                 goto out;
2232         }
2233         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2234                 log_stderr("failure: expected_uid_gid");
2235                 goto out;
2236         }
2237         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2238                 log_stderr("failure: expected_uid_gid");
2239                 goto out;
2240         }
2241         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2242                 log_stderr("failure: expected_uid_gid");
2243                 goto out;
2244         }
2245         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 10000, 10000)) {
2246                 log_stderr("failure: expected_uid_gid");
2247                 goto out;
2248         }
2249         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2250                 log_stderr("failure: expected_uid_gid");
2251                 goto out;
2252         }
2253         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2254                 log_stderr("failure: expected_uid_gid");
2255                 goto out;
2256         }
2257
2258         /* Changing mount properties on a detached mount. */
2259         attr2.userns_fd = get_userns_fd(0, 30000, 2001);
2260         if (attr2.userns_fd < 0) {
2261                 log_stderr("failure: get_userns_fd");
2262                 goto out;
2263         }
2264
2265         open_tree_fd2 = sys_open_tree(t_dir1_fd, "",
2266                                      AT_EMPTY_PATH |
2267                                      AT_NO_AUTOMOUNT |
2268                                      AT_SYMLINK_NOFOLLOW |
2269                                      OPEN_TREE_CLOEXEC |
2270                                      OPEN_TREE_CLONE);
2271         if (open_tree_fd2 < 0) {
2272                 log_stderr("failure: sys_open_tree");
2273                 goto out;
2274         }
2275
2276         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr2, sizeof(attr2))) {
2277                 log_stderr("failure: sys_mount_setattr");
2278                 goto out;
2279         }
2280
2281         /* Validate that all files are owned by the uid and gid specified in
2282          * the idmapping of the mount they are accessed from.
2283          */
2284         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2285                 log_stderr("failure: expected_uid_gid");
2286                 goto out;
2287         }
2288         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2289                 log_stderr("failure: expected_uid_gid");
2290                 goto out;
2291         }
2292         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2293                 log_stderr("failure: expected_uid_gid");
2294                 goto out;
2295         }
2296         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2297                 log_stderr("failure: expected_uid_gid");
2298                 goto out;
2299         }
2300         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 30000, 30000)) {
2301                 log_stderr("failure: expected_uid_gid");
2302                 goto out;
2303         }
2304         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2305                 log_stderr("failure: expected_uid_gid");
2306                 goto out;
2307         }
2308         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2309                 log_stderr("failure: expected_uid_gid");
2310                 goto out;
2311         }
2312
2313         /* Change ownership throught original image mountpoint. */
2314         if (fchownat(t_dir1_fd, FILE1, 2000, 2000, 0)) {
2315                 log_stderr("failure: fchownat");
2316                 goto out;
2317         }
2318         if (fchownat(t_dir1_fd, FILE2, 2000, 2000, 0)) {
2319                 log_stderr("failure: fchownat");
2320                 goto out;
2321         }
2322         if (fchownat(t_dir1_fd, HARDLINK1, 2000, 2000, 0)) {
2323                 log_stderr("failure: fchownat");
2324                 goto out;
2325         }
2326         if (fchownat(t_dir1_fd, CHRDEV1, 2000, 2000, 0)) {
2327                 log_stderr("failure: fchownat");
2328                 goto out;
2329         }
2330         if (fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)) {
2331                 log_stderr("failure: fchownat");
2332                 goto out;
2333         }
2334         if (fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH)) {
2335                 log_stderr("failure: fchownat");
2336                 goto out;
2337         }
2338         if (fchownat(t_dir1_fd, DIR1, 2000, 2000, AT_EMPTY_PATH)) {
2339                 log_stderr("failure: fchownat");
2340                 goto out;
2341         }
2342
2343         /* Check ownership through original mount. */
2344         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 2000, 2000)) {
2345                 log_stderr("failure: expected_uid_gid");
2346                 goto out;
2347         }
2348         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 2000, 2000)) {
2349                 log_stderr("failure: expected_uid_gid");
2350                 goto out;
2351         }
2352         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 2000, 2000)) {
2353                 log_stderr("failure: expected_uid_gid");
2354                 goto out;
2355         }
2356         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 2000, 2000)) {
2357                 log_stderr("failure: expected_uid_gid");
2358                 goto out;
2359         }
2360         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 3000, 3000)) {
2361                 log_stderr("failure: expected_uid_gid");
2362                 goto out;
2363         }
2364         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 2000, 2000)) {
2365                 log_stderr("failure: expected_uid_gid");
2366                 goto out;
2367         }
2368         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 2000, 2000)) {
2369                 log_stderr("failure: expected_uid_gid");
2370                 goto out;
2371         }
2372
2373         /* Check ownership through first idmapped mount. */
2374         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 12000, 12000)) {
2375                 log_stderr("failure:expected_uid_gid ");
2376                 goto out;
2377         }
2378         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 12000, 12000)) {
2379                 log_stderr("failure: expected_uid_gid");
2380                 goto out;
2381         }
2382         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 12000, 12000)) {
2383                 log_stderr("failure: expected_uid_gid");
2384                 goto out;
2385         }
2386         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 12000, 12000)) {
2387                 log_stderr("failure: expected_uid_gid");
2388                 goto out;
2389         }
2390         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 13000, 13000)) {
2391                 log_stderr("failure: expected_uid_gid");
2392                 goto out;
2393         }
2394         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 12000, 12000)) {
2395                 log_stderr("failure:expected_uid_gid ");
2396                 goto out;
2397         }
2398         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 12000, 12000)) {
2399                 log_stderr("failure: expected_uid_gid");
2400                 goto out;
2401         }
2402
2403         /* Check ownership through second idmapped mount. */
2404         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 32000, 32000)) {
2405                 log_stderr("failure: expected_uid_gid");
2406                 goto out;
2407         }
2408         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 32000, 32000)) {
2409                 log_stderr("failure: expected_uid_gid");
2410                 goto out;
2411         }
2412         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 32000, 32000)) {
2413                 log_stderr("failure: expected_uid_gid");
2414                 goto out;
2415         }
2416         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 32000, 32000)) {
2417                 log_stderr("failure: expected_uid_gid");
2418                 goto out;
2419         }
2420         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid)) {
2421                 log_stderr("failure: expected_uid_gid");
2422                 goto out;
2423         }
2424         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 32000, 32000)) {
2425                 log_stderr("failure: expected_uid_gid");
2426                 goto out;
2427         }
2428         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 32000, 32000)) {
2429                 log_stderr("failure: expected_uid_gid");
2430                 goto out;
2431         }
2432
2433         pid = fork();
2434         if (pid < 0) {
2435                 log_stderr("failure: fork");
2436                 goto out;
2437         }
2438         if (pid == 0) {
2439                 if (!switch_userns(attr1.userns_fd, 0, 0, false))
2440                         die("failure: switch_userns");
2441
2442                 if (!fchownat(t_dir1_fd, FILE1, 1000, 1000, 0))
2443                         die("failure: fchownat");
2444                 if (!fchownat(t_dir1_fd, FILE2, 1000, 1000, 0))
2445                         die("failure: fchownat");
2446                 if (!fchownat(t_dir1_fd, HARDLINK1, 1000, 1000, 0))
2447                         die("failure: fchownat");
2448                 if (!fchownat(t_dir1_fd, CHRDEV1, 1000, 1000, 0))
2449                         die("failure: fchownat");
2450                 if (!fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2451                         die("failure: fchownat");
2452                 if (!fchownat(t_dir1_fd, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2453                         die("failure: fchownat");
2454                 if (!fchownat(t_dir1_fd, DIR1, 1000, 1000, AT_EMPTY_PATH))
2455                         die("failure: fchownat");
2456
2457                 if (!fchownat(open_tree_fd2, FILE1, 1000, 1000, 0))
2458                         die("failure: fchownat");
2459                 if (!fchownat(open_tree_fd2, FILE2, 1000, 1000, 0))
2460                         die("failure: fchownat");
2461                 if (!fchownat(open_tree_fd2, HARDLINK1, 1000, 1000, 0))
2462                         die("failure: fchownat");
2463                 if (!fchownat(open_tree_fd2, CHRDEV1, 1000, 1000, 0))
2464                         die("failure: fchownat");
2465                 if (!fchownat(open_tree_fd2, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2466                         die("failure: fchownat");
2467                 if (!fchownat(open_tree_fd2, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2468                         die("failure: fchownat");
2469                 if (!fchownat(open_tree_fd2, DIR1, 1000, 1000, AT_EMPTY_PATH))
2470                         die("failure: fchownat");
2471
2472                 if (fchownat(open_tree_fd1, FILE1, 1000, 1000, 0))
2473                         die("failure: fchownat");
2474                 if (fchownat(open_tree_fd1, FILE2, 1000, 1000, 0))
2475                         die("failure: fchownat");
2476                 if (fchownat(open_tree_fd1, HARDLINK1, 1000, 1000, 0))
2477                         die("failure: fchownat");
2478                 if (fchownat(open_tree_fd1, CHRDEV1, 1000, 1000, 0))
2479                         die("failure: fchownat");
2480                 if (fchownat(open_tree_fd1, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2481                         die("failure: fchownat");
2482                 if (fchownat(open_tree_fd1, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2483                         die("failure: fchownat");
2484                 if (fchownat(open_tree_fd1, DIR1, 1000, 1000, AT_EMPTY_PATH))
2485                         die("failure: fchownat");
2486
2487                 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2488                         die("failure: expected_uid_gid");
2489                 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2490                         die("failure: expected_uid_gid");
2491                 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2492                         die("failure: expected_uid_gid");
2493                 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2494                         die("failure: expected_uid_gid");
2495                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2496                         die("failure: expected_uid_gid");
2497                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2498                         die("failure: expected_uid_gid");
2499                 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2500                         die("failure: expected_uid_gid");
2501
2502                 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, t_overflowuid, t_overflowgid))
2503                         die("failure: expected_uid_gid");
2504                 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, t_overflowuid, t_overflowgid))
2505                         die("failure: expected_uid_gid");
2506                 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2507                         die("failure: expected_uid_gid");
2508                 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2509                         die("failure: expected_uid_gid");
2510                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2511                         die("failure: expected_uid_gid");
2512                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2513                         die("failure: expected_uid_gid");
2514                 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, t_overflowuid, t_overflowgid))
2515                         die("failure: expected_uid_gid");
2516
2517                 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 1000, 1000))
2518                         die("failure: expected_uid_gid");
2519                 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 1000, 1000))
2520                         die("failure: expected_uid_gid");
2521                 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 1000, 1000))
2522                         die("failure: expected_uid_gid");
2523                 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 1000, 1000))
2524                         die("failure: expected_uid_gid");
2525                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2526                         die("failure: expected_uid_gid");
2527                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 1000, 1000))
2528                         die("failure: expected_uid_gid");
2529                 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 1000, 1000))
2530                         die("failure: expected_uid_gid");
2531
2532                 exit(EXIT_SUCCESS);
2533         }
2534
2535         if (wait_for_pid(pid))
2536                 goto out;
2537
2538         /* Check ownership through original mount. */
2539         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 1000, 1000)) {
2540                 log_stderr("failure: expected_uid_gid");
2541                 goto out;
2542         }
2543         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 1000, 1000)) {
2544                 log_stderr("failure: expected_uid_gid");
2545                 goto out;
2546         }
2547         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 1000, 1000)) {
2548                 log_stderr("failure: expected_uid_gid");
2549                 goto out;
2550         }
2551         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 1000, 1000)) {
2552                 log_stderr("failure: expected_uid_gid");
2553                 goto out;
2554         }
2555         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2556                 log_stderr("failure: expected_uid_gid");
2557                 goto out;
2558         }
2559         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 1000, 1000)) {
2560                 log_stderr("failure: expected_uid_gid");
2561                 goto out;
2562         }
2563         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 1000, 1000)) {
2564                 log_stderr("failure: expected_uid_gid");
2565                 goto out;
2566         }
2567
2568         /* Check ownership through first idmapped mount. */
2569         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 11000, 11000)) {
2570                 log_stderr("failure: expected_uid_gid");
2571                 goto out;
2572         }
2573         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 11000, 11000)) {
2574                 log_stderr("failure: expected_uid_gid");
2575                 goto out;
2576         }
2577         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 11000, 11000)) {
2578                 log_stderr("failure: expected_uid_gid");
2579                 goto out;
2580         }
2581         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 11000, 11000)) {
2582                 log_stderr("failure: expected_uid_gid");
2583                 goto out;
2584         }
2585         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2586                 log_stderr("failure: expected_uid_gid");
2587                 goto out;
2588         }
2589         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 11000, 11000)) {
2590                 log_stderr("failure: expected_uid_gid");
2591                 goto out;
2592         }
2593         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 11000, 11000)) {
2594                 log_stderr("failure: expected_uid_gid");
2595                 goto out;
2596         }
2597
2598         /* Check ownership through second idmapped mount. */
2599         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 31000, 31000)) {
2600                 log_stderr("failure: expected_uid_gid");
2601                 goto out;
2602         }
2603         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 31000, 31000)) {
2604                 log_stderr("failure: expected_uid_gid");
2605                 goto out;
2606         }
2607         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 31000, 31000)) {
2608                 log_stderr("failure: expected_uid_gid");
2609                 goto out;
2610         }
2611         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 31000, 31000)) {
2612                 log_stderr("failure: expected_uid_gid");
2613                 goto out;
2614         }
2615         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2616                 log_stderr("failure: expected_uid_gid");
2617                 goto out;
2618         }
2619         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 31000, 31000)) {
2620                 log_stderr("failure: expected_uid_gid");
2621                 goto out;
2622         }
2623         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 31000, 31000)) {
2624                 log_stderr("failure: expected_uid_gid");
2625                 goto out;
2626         }
2627
2628         pid = fork();
2629         if (pid < 0) {
2630                 log_stderr("failure: fork");
2631                 goto out;
2632         }
2633         if (pid == 0) {
2634                 if (!switch_userns(attr2.userns_fd, 0, 0, false))
2635                         die("failure: switch_userns");
2636
2637                 if (!fchownat(t_dir1_fd, FILE1, 0, 0, 0))
2638                         die("failure: fchownat");
2639                 if (!fchownat(t_dir1_fd, FILE2, 0, 0, 0))
2640                         die("failure: fchownat");
2641                 if (!fchownat(t_dir1_fd, HARDLINK1, 0, 0, 0))
2642                         die("failure: fchownat");
2643                 if (!fchownat(t_dir1_fd, CHRDEV1, 0, 0, 0))
2644                         die("failure: fchownat");
2645                 if (!fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2646                         die("failure: fchownat");
2647                 if (!fchownat(t_dir1_fd, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2648                         die("failure: fchownat");
2649                 if (!fchownat(t_dir1_fd, DIR1, 0, 0, AT_EMPTY_PATH))
2650                         die("failure: fchownat");
2651
2652                 if (!fchownat(open_tree_fd1, FILE1, 0, 0, 0))
2653                         die("failure: fchownat");
2654                 if (!fchownat(open_tree_fd1, FILE2, 0, 0, 0))
2655                         die("failure: fchownat");
2656                 if (!fchownat(open_tree_fd1, HARDLINK1, 0, 0, 0))
2657                         die("failure: fchownat");
2658                 if (!fchownat(open_tree_fd1, CHRDEV1, 0, 0, 0))
2659                         die("failure: fchownat");
2660                 if (!fchownat(open_tree_fd1, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2661                         die("failure: fchownat");
2662                 if (!fchownat(open_tree_fd1, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2663                         die("failure: fchownat");
2664                 if (!fchownat(open_tree_fd1, DIR1, 0, 0, AT_EMPTY_PATH))
2665                         die("failure: fchownat");
2666
2667                 if (fchownat(open_tree_fd2, FILE1, 0, 0, 0))
2668                         die("failure: fchownat");
2669                 if (fchownat(open_tree_fd2, FILE2, 0, 0, 0))
2670                         die("failure: fchownat");
2671                 if (fchownat(open_tree_fd2, HARDLINK1, 0, 0, 0))
2672                         die("failure: fchownat");
2673                 if (fchownat(open_tree_fd2, CHRDEV1, 0, 0, 0))
2674                         die("failure: fchownat");
2675                 if (!fchownat(open_tree_fd2, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2676                         die("failure: fchownat");
2677                 if (fchownat(open_tree_fd2, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2678                         die("failure: fchownat");
2679                 if (fchownat(open_tree_fd2, DIR1, 0, 0, AT_EMPTY_PATH))
2680                         die("failure: fchownat");
2681
2682                 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2683                         die("failure: expected_uid_gid");
2684                 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2685                         die("failure: expected_uid_gid");
2686                 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2687                         die("failure: expected_uid_gid");
2688                 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2689                         die("failure: expected_uid_gid");
2690                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2691                         die("failure: expected_uid_gid");
2692                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2693                         die("failure: expected_uid_gid");
2694                 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2695                         die("failure: expected_uid_gid");
2696
2697                 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, t_overflowuid, t_overflowgid))
2698                         die("failure: expected_uid_gid");
2699                 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, t_overflowuid, t_overflowgid))
2700                         die("failure: expected_uid_gid");
2701                 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2702                         die("failure: expected_uid_gid");
2703                 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2704                         die("failure: expected_uid_gid");
2705                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2706                         die("failure: expected_uid_gid");
2707                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2708                         die("failure: expected_uid_gid");
2709                 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, t_overflowuid, t_overflowgid))
2710                         die("failure: expected_uid_gid");
2711
2712                 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 0, 0))
2713                         die("failure: expected_uid_gid");
2714                 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 0, 0))
2715                         die("failure: expected_uid_gid");
2716                 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 0, 0))
2717                         die("failure: expected_uid_gid");
2718                 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 0, 0))
2719                         die("failure: expected_uid_gid");
2720                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2721                         die("failure: expected_uid_gid");
2722                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 0, 0))
2723                         die("failure: expected_uid_gid");
2724                 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 0, 0))
2725                         die("failure: expected_uid_gid");
2726
2727                 exit(EXIT_SUCCESS);
2728         }
2729
2730         if (wait_for_pid(pid))
2731                 goto out;
2732
2733         /* Check ownership through original mount. */
2734         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2735                 log_stderr("failure: expected_uid_gid");
2736                 goto out;
2737         }
2738         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2739                 log_stderr("failure: expected_uid_gid");
2740                 goto out;
2741         }
2742         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2743                 log_stderr("failure: expected_uid_gid");
2744                 goto out;
2745         }
2746         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2747                 log_stderr("failure: expected_uid_gid");
2748                 goto out;
2749         }
2750         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2751                 log_stderr("failure: expected_uid_gid");
2752                 goto out;
2753         }
2754         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2755                 log_stderr("failure: expected_uid_gid");
2756                 goto out;
2757         }
2758         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2759                 log_stderr("failure: expected_uid_gid");
2760                 goto out;
2761         }
2762
2763         /* Check ownership through first idmapped mount. */
2764         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2765                 log_stderr("failure: expected_uid_gid");
2766                 goto out;
2767         }
2768         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2769                 log_stderr("failure: expected_uid_gid");
2770                 goto out;
2771         }
2772         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2773                 log_stderr("failure: expected_uid_gid");
2774                 goto out;
2775         }
2776         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2777                 log_stderr("failure: expected_uid_gid");
2778                 goto out;
2779         }
2780         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2781                 log_stderr("failure: expected_uid_gid");
2782                 goto out;
2783         }
2784         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2785                 log_stderr("failure: expected_uid_gid");
2786                 goto out;
2787         }
2788         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2789                 log_stderr("failure: expected_uid_gid");
2790                 goto out;
2791         }
2792
2793         /* Check ownership through second idmapped mount. */
2794         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2795                 log_stderr("failure: expected_uid_gid");
2796                 goto out;
2797         }
2798         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2799                 log_stderr("failure: expected_uid_gid");
2800                 goto out;
2801         }
2802         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2803                 log_stderr("failure: expected_uid_gid");
2804                 goto out;
2805         }
2806         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2807                 log_stderr("failure: expected_uid_gid");
2808                 goto out;
2809         }
2810         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2811                 log_stderr("failure: expected_uid_gid");
2812                 goto out;
2813         }
2814         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2815                 log_stderr("failure: expected_uid_gid");
2816                 goto out;
2817         }
2818         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2819                 log_stderr("failure: expected_uid_gid");
2820                 goto out;
2821         }
2822
2823         fret = 0;
2824         log_debug("Ran test");
2825 out:
2826         safe_close(attr1.userns_fd);
2827         safe_close(attr2.userns_fd);
2828         safe_close(file1_fd);
2829         safe_close(open_tree_fd1);
2830         safe_close(open_tree_fd2);
2831
2832         return fret;
2833 }
2834
2835 static int fscaps(void)
2836 {
2837         int fret = -1;
2838         int file1_fd = -EBADF;
2839         struct mount_attr attr = {
2840                 .attr_set = MOUNT_ATTR_IDMAP,
2841         };
2842         pid_t pid;
2843
2844         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2845         if (file1_fd < 0) {
2846                 log_stderr("failure: openat");
2847                 goto out;
2848         }
2849
2850         /* Skip if vfs caps are unsupported. */
2851         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2852                 return 0;
2853
2854         /* Changing mount properties on a detached mount. */
2855         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2856         if (attr.userns_fd < 0) {
2857                 log_stderr("failure: get_userns_fd");
2858                 goto out;
2859         }
2860
2861         if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
2862                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2863                 goto out;
2864         }
2865
2866         pid = fork();
2867         if (pid < 0) {
2868                 log_stderr("failure: fork");
2869                 goto out;
2870         }
2871         if (pid == 0) {
2872                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2873                         die("failure: switch_userns");
2874
2875                 /*
2876                  * On kernels before 5.12 this would succeed and return the
2877                  * unconverted caps. Then - for whatever reason - this behavior
2878                  * got changed and since 5.12 EOVERFLOW is returned when the
2879                  * rootid stored alongside the vfs caps does not map to uid 0 in
2880                  * the caller's user namespace.
2881                  */
2882                 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
2883                         die("failure: expected_dummy_vfs_caps_uid");
2884
2885                 exit(EXIT_SUCCESS);
2886         }
2887
2888         if (wait_for_pid(pid))
2889                 goto out;
2890
2891         if (fremovexattr(file1_fd, "security.capability")) {
2892                 log_stderr("failure: fremovexattr");
2893                 goto out;
2894         }
2895         if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2896                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2897                 goto out;
2898         }
2899         if (errno != ENODATA) {
2900                 log_stderr("failure: errno");
2901                 goto out;
2902         }
2903
2904         if (set_dummy_vfs_caps(file1_fd, 0, 10000)) {
2905                 log_stderr("failure: set_dummy_vfs_caps");
2906                 goto out;
2907         }
2908
2909         if (!expected_dummy_vfs_caps_uid(file1_fd, 10000)) {
2910                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2911                 goto out;
2912         }
2913
2914         pid = fork();
2915         if (pid < 0) {
2916                 log_stderr("failure: fork");
2917                 goto out;
2918         }
2919         if (pid == 0) {
2920                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2921                         die("failure: switch_userns");
2922
2923                 if (!expected_dummy_vfs_caps_uid(file1_fd, 0))
2924                         die("failure: expected_dummy_vfs_caps_uid");
2925
2926                 exit(EXIT_SUCCESS);
2927         }
2928
2929         if (wait_for_pid(pid))
2930                 goto out;
2931
2932         if (fremovexattr(file1_fd, "security.capability")) {
2933                 log_stderr("failure: fremovexattr");
2934                 goto out;
2935         }
2936         if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2937                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2938                 goto out;
2939         }
2940         if (errno != ENODATA) {
2941                 log_stderr("failure: errno");
2942                 goto out;
2943         }
2944
2945         fret = 0;
2946         log_debug("Ran test");
2947 out:
2948         safe_close(attr.userns_fd);
2949         safe_close(file1_fd);
2950
2951         return fret;
2952 }
2953
2954 static int fscaps_idmapped_mounts(void)
2955 {
2956         int fret = -1;
2957         int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
2958         struct mount_attr attr = {
2959                 .attr_set = MOUNT_ATTR_IDMAP,
2960         };
2961         pid_t pid;
2962
2963         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2964         if (file1_fd < 0) {
2965                 log_stderr("failure: openat");
2966                 goto out;
2967         }
2968
2969         /* Skip if vfs caps are unsupported. */
2970         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2971                 return 0;
2972
2973         if (fremovexattr(file1_fd, "security.capability")) {
2974                 log_stderr("failure: fremovexattr");
2975                 goto out;
2976         }
2977
2978         /* Changing mount properties on a detached mount. */
2979         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2980         if (attr.userns_fd < 0) {
2981                 log_stderr("failure: get_userns_fd");
2982                 goto out;
2983         }
2984
2985         open_tree_fd = sys_open_tree(t_dir1_fd, "",
2986                                      AT_EMPTY_PATH |
2987                                      AT_NO_AUTOMOUNT |
2988                                      AT_SYMLINK_NOFOLLOW |
2989                                      OPEN_TREE_CLOEXEC |
2990                                      OPEN_TREE_CLONE);
2991         if (open_tree_fd < 0) {
2992                 log_stderr("failure: sys_open_tree");
2993                 goto out;
2994         }
2995
2996         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2997                 log_stderr("failure: sys_mount_setattr");
2998                 goto out;
2999         }
3000
3001         file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3002         if (file1_fd2 < 0) {
3003                 log_stderr("failure: openat");
3004                 goto out;
3005         }
3006
3007         if (!set_dummy_vfs_caps(file1_fd2, 0, 1000)) {
3008                 log_stderr("failure: set_dummy_vfs_caps");
3009                 goto out;
3010         }
3011
3012         if (set_dummy_vfs_caps(file1_fd2, 0, 10000)) {
3013                 log_stderr("failure: set_dummy_vfs_caps");
3014                 goto out;
3015         }
3016
3017         if (!expected_dummy_vfs_caps_uid(file1_fd2, 10000)) {
3018                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3019                 goto out;
3020         }
3021
3022         if (!expected_dummy_vfs_caps_uid(file1_fd, 0)) {
3023                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3024                 goto out;
3025         }
3026
3027         pid = fork();
3028         if (pid < 0) {
3029                 log_stderr("failure: fork");
3030                 goto out;
3031         }
3032         if (pid == 0) {
3033                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3034                         die("failure: switch_userns");
3035
3036                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 0))
3037                         die("failure: expected_dummy_vfs_caps_uid");
3038
3039                 exit(EXIT_SUCCESS);
3040         }
3041
3042         if (wait_for_pid(pid))
3043                 goto out;
3044
3045         if (fremovexattr(file1_fd2, "security.capability")) {
3046                 log_stderr("failure: fremovexattr");
3047                 goto out;
3048         }
3049         if (expected_dummy_vfs_caps_uid(file1_fd2, -1)) {
3050                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3051                 goto out;
3052         }
3053         if (errno != ENODATA) {
3054                 log_stderr("failure: errno");
3055                 goto out;
3056         }
3057
3058         if (set_dummy_vfs_caps(file1_fd2, 0, 12000)) {
3059                 log_stderr("failure: set_dummy_vfs_caps");
3060                 goto out;
3061         }
3062
3063         if (!expected_dummy_vfs_caps_uid(file1_fd2, 12000)) {
3064                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3065                 goto out;
3066         }
3067
3068         if (!expected_dummy_vfs_caps_uid(file1_fd, 2000)) {
3069                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3070                 goto out;
3071         }
3072
3073         pid = fork();
3074         if (pid < 0) {
3075                 log_stderr("failure: fork");
3076                 goto out;
3077         }
3078         if (pid == 0) {
3079                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3080                         die("failure: switch_userns");
3081
3082                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 2000))
3083                         die("failure: expected_dummy_vfs_caps_uid");
3084
3085                 exit(EXIT_SUCCESS);
3086         }
3087
3088         if (wait_for_pid(pid))
3089                 goto out;
3090
3091         fret = 0;
3092         log_debug("Ran test");
3093 out:
3094         safe_close(attr.userns_fd);
3095         safe_close(file1_fd);
3096         safe_close(file1_fd2);
3097         safe_close(open_tree_fd);
3098
3099         return fret;
3100 }
3101
3102 static int fscaps_idmapped_mounts_in_userns(void)
3103 {
3104         int fret = -1;
3105         int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
3106         struct mount_attr attr = {
3107                 .attr_set = MOUNT_ATTR_IDMAP,
3108         };
3109         pid_t pid;
3110
3111         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
3112         if (file1_fd < 0) {
3113                 log_stderr("failure: openat");
3114                 goto out;
3115         }
3116
3117         /* Skip if vfs caps are unsupported. */
3118         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
3119                 return 0;
3120
3121         if (fremovexattr(file1_fd, "security.capability")) {
3122                 log_stderr("failure: fremovexattr");
3123                 goto out;
3124         }
3125
3126         /* Changing mount properties on a detached mount. */
3127         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
3128         if (attr.userns_fd < 0) {
3129                 log_stderr("failure: get_userns_fd");
3130                 goto out;
3131         }
3132
3133         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3134                                      AT_EMPTY_PATH |
3135                                      AT_NO_AUTOMOUNT |
3136                                      AT_SYMLINK_NOFOLLOW |
3137                                      OPEN_TREE_CLOEXEC |
3138                                      OPEN_TREE_CLONE);
3139         if (open_tree_fd < 0) {
3140                 log_stderr("failure: sys_open_tree");
3141                 goto out;
3142         }
3143
3144         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3145                 log_stderr("failure: sys_mount_setattr");
3146                 goto out;
3147         }
3148
3149         file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3150         if (file1_fd2 < 0) {
3151                 log_stderr("failure: openat");
3152                 goto out;
3153         }
3154
3155         pid = fork();
3156         if (pid < 0) {
3157                 log_stderr("failure: fork");
3158                 goto out;
3159         }
3160         if (pid == 0) {
3161                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3162                         die("failure: switch_userns");
3163
3164                 if (expected_dummy_vfs_caps_uid(file1_fd2, -1))
3165                         die("failure: expected_dummy_vfs_caps_uid");
3166                 if (errno != ENODATA)
3167                         die("failure: errno");
3168
3169                 if (set_dummy_vfs_caps(file1_fd2, 0, 1000))
3170                         die("failure: set_dummy_vfs_caps");
3171
3172                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 1000))
3173                         die("failure: expected_dummy_vfs_caps_uid");
3174
3175                 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
3176                         die("failure: expected_dummy_vfs_caps_uid");
3177
3178                 exit(EXIT_SUCCESS);
3179         }
3180
3181         if (wait_for_pid(pid))
3182                 goto out;
3183
3184         if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
3185                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3186                 goto out;
3187         }
3188
3189         fret = 0;
3190         log_debug("Ran test");
3191 out:
3192         safe_close(attr.userns_fd);
3193         safe_close(file1_fd);
3194         safe_close(file1_fd2);
3195         safe_close(open_tree_fd);
3196
3197         return fret;
3198 }
3199
3200 static int fscaps_idmapped_mounts_in_userns_separate_userns(void)
3201 {
3202         int fret = -1;