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