src/idmapped-mounts: use renameat instead of renameat2
[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/acl.h>
20 #include <sys/fsuid.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/sysmacros.h>
24 #include <sys/xattr.h>
25 #include <unistd.h>
26
27 #ifdef HAVE_SYS_CAPABILITY_H
28 #include <sys/capability.h>
29 #endif
30
31 #ifdef HAVE_LIBURING_H
32 #include <liburing.h>
33 #endif
34
35 #include "missing.h"
36 #include "utils.h"
37
38 #define T_DIR1 "idmapped_mounts_1"
39 #define FILE1 "file1"
40 #define FILE1_RENAME "file1_rename"
41 #define FILE2 "file2"
42 #define FILE2_RENAME "file2_rename"
43 #define DIR1 "dir1"
44 #define DIR2 "dir2"
45 #define DIR3 "dir3"
46 #define DIR1_RENAME "dir1_rename"
47 #define HARDLINK1 "hardlink1"
48 #define SYMLINK1 "symlink1"
49 #define SYMLINK_USER1 "symlink_user1"
50 #define SYMLINK_USER2 "symlink_user2"
51 #define SYMLINK_USER3 "symlink_user3"
52 #define CHRDEV1 "chrdev1"
53
54 #define log_stderr(format, ...)                                                         \
55         fprintf(stderr, "%s: %d: %s - %m - " format "\n", __FILE__, __LINE__, __func__, \
56                 ##__VA_ARGS__)
57
58 #ifdef DEBUG_TRACE
59 #define log_debug(format, ...)                                           \
60         fprintf(stderr, "%s: %d: %s - " format "\n", __FILE__, __LINE__, \
61                 __func__, ##__VA_ARGS__)
62 #else
63 #define log_debug(format, ...)
64 #endif
65
66 #define log_error_errno(__ret__, __errno__, format, ...)      \
67         ({                                                    \
68                 typeof(__ret__) __internal_ret__ = (__ret__); \
69                 errno = (__errno__);                          \
70                 log_stderr(format, ##__VA_ARGS__);            \
71                 __internal_ret__;                             \
72         })
73
74 #define log_errno(__ret__, format, ...) log_error_errno(__ret__, errno, format, ##__VA_ARGS__)
75
76 #define die_errno(__errno__, format, ...)          \
77         ({                                         \
78                 errno = (__errno__);               \
79                 log_stderr(format, ##__VA_ARGS__); \
80                 exit(EXIT_FAILURE);                \
81         })
82
83 #define die(format, ...) die_errno(errno, format, ##__VA_ARGS__)
84
85 uid_t t_overflowuid = 65534;
86 gid_t t_overflowgid = 65534;
87
88 /* path of the test device */
89 const char *t_fstype;
90
91 /* path of the test device */
92 const char *t_device;
93
94 /* mountpoint of the test device */
95 const char *t_mountpoint;
96
97 /* fd for @t_mountpoint */
98 int t_mnt_fd;
99
100 /* fd for @T_DIR1 */
101 int t_dir1_fd;
102
103 /* temporary buffer */
104 char t_buf[PATH_MAX];
105
106 static void stash_overflowuid(void)
107 {
108         int fd;
109         ssize_t ret;
110         char buf[256];
111
112         fd = open("/proc/sys/fs/overflowuid", O_RDONLY | O_CLOEXEC);
113         if (fd < 0)
114                 return;
115
116         ret = read(fd, buf, sizeof(buf));
117         close(fd);
118         if (ret < 0)
119                 return;
120
121         t_overflowuid = atoi(buf);
122 }
123
124 static void stash_overflowgid(void)
125 {
126         int fd;
127         ssize_t ret;
128         char buf[256];
129
130         fd = open("/proc/sys/fs/overflowgid", O_RDONLY | O_CLOEXEC);
131         if (fd < 0)
132                 return;
133
134         ret = read(fd, buf, sizeof(buf));
135         close(fd);
136         if (ret < 0)
137                 return;
138
139         t_overflowgid = atoi(buf);
140 }
141
142 static bool is_xfs(void)
143 {
144         static int enabled = -1;
145
146         if (enabled == -1)
147                 enabled = !strcmp(t_fstype, "xfs");
148
149         return enabled;
150 }
151
152 static bool protected_symlinks_enabled(void)
153 {
154         static int enabled = -1;
155
156         if (enabled == -1) {
157                 int fd;
158                 ssize_t ret;
159                 char buf[256];
160
161                 enabled = 0;
162
163                 fd = open("/proc/sys/fs/protected_symlinks", O_RDONLY | O_CLOEXEC);
164                 if (fd < 0)
165                         return false;
166
167                 ret = read(fd, buf, sizeof(buf));
168                 close(fd);
169                 if (ret < 0)
170                         return false;
171
172                 if (atoi(buf) >= 1)
173                         enabled = 1;
174         }
175
176         return enabled == 1;
177 }
178
179 static bool xfs_irix_sgid_inherit_enabled(void)
180 {
181         static int enabled = -1;
182
183         if (enabled == -1) {
184                 int fd;
185                 ssize_t ret;
186                 char buf[256];
187
188                 enabled = 0;
189
190                 if (is_xfs()) {
191                         fd = open("/proc/sys/fs/xfs/irix_sgid_inherit", O_RDONLY | O_CLOEXEC);
192                         if (fd < 0)
193                                 return false;
194
195                         ret = read(fd, buf, sizeof(buf));
196                         close(fd);
197                         if (ret < 0)
198                                 return false;
199
200                         if (atoi(buf) >= 1)
201                                 enabled = 1;
202                 }
203         }
204
205         return enabled == 1;
206 }
207
208 static inline bool caps_supported(void)
209 {
210         bool ret = false;
211
212 #ifdef HAVE_SYS_CAPABILITY_H
213         ret = true;
214 #endif
215
216         return ret;
217 }
218
219 /* caps_down - lower all effective caps */
220 static int caps_down(void)
221 {
222         bool fret = false;
223 #ifdef HAVE_SYS_CAPABILITY_H
224         cap_t caps = NULL;
225         int ret = -1;
226
227         caps = cap_get_proc();
228         if (!caps)
229                 goto out;
230
231         ret = cap_clear_flag(caps, CAP_EFFECTIVE);
232         if (ret)
233                 goto out;
234
235         ret = cap_set_proc(caps);
236         if (ret)
237                 goto out;
238
239         fret = true;
240
241 out:
242         cap_free(caps);
243 #endif
244         return fret;
245 }
246
247 /* caps_up - raise all permitted caps */
248 static int caps_up(void)
249 {
250         bool fret = false;
251 #ifdef HAVE_SYS_CAPABILITY_H
252         cap_t caps = NULL;
253         cap_value_t cap;
254         int ret = -1;
255
256         caps = cap_get_proc();
257         if (!caps)
258                 goto out;
259
260         for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
261                 cap_flag_value_t flag;
262
263                 ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
264                 if (ret) {
265                         if (errno == EINVAL)
266                                 break;
267                         else
268                                 goto out;
269                 }
270
271                 ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
272                 if (ret)
273                         goto out;
274         }
275
276         ret = cap_set_proc(caps);
277         if (ret)
278                 goto out;
279
280         fret = true;
281 out:
282         cap_free(caps);
283 #endif
284         return fret;
285 }
286
287 /* __expected_uid_gid - check whether file is owned by the provided uid and gid */
288 static bool __expected_uid_gid(int dfd, const char *path, int flags,
289                                uid_t expected_uid, gid_t expected_gid, bool log)
290 {
291         int ret;
292         struct stat st;
293
294         ret = fstatat(dfd, path, &st, flags);
295         if (ret < 0)
296                 return log_errno(false, "failure: fstatat");
297
298         if (log && st.st_uid != expected_uid)
299                 log_stderr("failure: uid(%d) != expected_uid(%d)", st.st_uid, expected_uid);
300
301         if (log && st.st_gid != expected_gid)
302                 log_stderr("failure: gid(%d) != expected_gid(%d)", st.st_gid, expected_gid);
303
304         errno = 0; /* Don't report misleading errno. */
305         return st.st_uid == expected_uid && st.st_gid == expected_gid;
306 }
307
308 static bool expected_uid_gid(int dfd, const char *path, int flags,
309                              uid_t expected_uid, gid_t expected_gid)
310 {
311         return __expected_uid_gid(dfd, path, flags,
312                                   expected_uid, expected_gid, true);
313 }
314
315 static bool expected_file_size(int dfd, const char *path,
316                                int flags, off_t expected_size)
317 {
318         int ret;
319         struct stat st;
320
321         ret = fstatat(dfd, path, &st, flags);
322         if (ret < 0)
323                 return log_errno(false, "failure: fstatat");
324
325         if (st.st_size != expected_size)
326                 return log_errno(false, "failure: st_size(%zu) != expected_size(%zu)",
327                                  (size_t)st.st_size, (size_t)expected_size);
328
329         return true;
330 }
331
332 /* is_setid - check whether file is S_ISUID and S_ISGID */
333 static bool is_setid(int dfd, const char *path, int flags)
334 {
335         int ret;
336         struct stat st;
337
338         ret = fstatat(dfd, path, &st, flags);
339         if (ret < 0)
340                 return false;
341
342         errno = 0; /* Don't report misleading errno. */
343         return (st.st_mode & S_ISUID) || (st.st_mode & S_ISGID);
344 }
345
346 /* is_setgid - check whether file or directory is S_ISGID */
347 static bool is_setgid(int dfd, const char *path, int flags)
348 {
349         int ret;
350         struct stat st;
351
352         ret = fstatat(dfd, path, &st, flags);
353         if (ret < 0)
354                 return false;
355
356         errno = 0; /* Don't report misleading errno. */
357         return (st.st_mode & S_ISGID);
358 }
359
360 /* is_sticky - check whether file is S_ISVTX */
361 static bool is_sticky(int dfd, const char *path, int flags)
362 {
363         int ret;
364         struct stat st;
365
366         ret = fstatat(dfd, path, &st, flags);
367         if (ret < 0)
368                 return false;
369
370         errno = 0; /* Don't report misleading errno. */
371         return (st.st_mode & S_ISVTX) > 0;
372 }
373
374 static inline int set_cloexec(int fd)
375 {
376         return fcntl(fd, F_SETFD, FD_CLOEXEC);
377 }
378
379 static inline bool switch_fsids(uid_t fsuid, gid_t fsgid)
380 {
381         if (setfsgid(fsgid))
382                 return log_errno(false, "failure: setfsgid");
383
384         if (setfsgid(-1) != fsgid)
385                 return log_errno(false, "failure: setfsgid(-1)");
386
387         if (setfsuid(fsuid))
388                 return log_errno(false, "failure: setfsuid");
389
390         if (setfsuid(-1) != fsuid)
391                 return log_errno(false, "failure: setfsuid(-1)");
392
393         return true;
394 }
395
396 static inline bool switch_ids(uid_t uid, gid_t gid)
397 {
398         if (setgroups(0, NULL))
399                 return log_errno(false, "failure: setgroups");
400
401         if (setresgid(gid, gid, gid))
402                 return log_errno(false, "failure: setresgid");
403
404         if (setresuid(uid, uid, uid))
405                 return log_errno(false, "failure: setresuid");
406
407         return true;
408 }
409
410 static inline bool switch_userns(int fd, uid_t uid, gid_t gid, bool drop_caps)
411 {
412         if (setns(fd, CLONE_NEWUSER))
413                 return log_errno(false, "failure: setns");
414
415         if (!switch_ids(uid, gid))
416                 return log_errno(false, "failure: switch_ids");
417
418         if (drop_caps && !caps_down())
419                 return log_errno(false, "failure: caps_down");
420
421         return true;
422 }
423
424 /* rm_r - recursively remove all files */
425 static int rm_r(int fd, const char *path)
426 {
427         int dfd, ret;
428         DIR *dir;
429         struct dirent *direntp;
430
431         if (!path || strcmp(path, "") == 0)
432                 return -1;
433
434         dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
435         if (dfd < 0)
436                 return -1;
437
438         dir = fdopendir(dfd);
439         if (!dir) {
440                 close(dfd);
441                 return -1;
442         }
443
444         while ((direntp = readdir(dir))) {
445                 struct stat st;
446
447                 if (!strcmp(direntp->d_name, ".") ||
448                     !strcmp(direntp->d_name, ".."))
449                         continue;
450
451                 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
452                 if (ret < 0 && errno != ENOENT)
453                         break;
454
455                 if (S_ISDIR(st.st_mode))
456                         ret = rm_r(dfd, direntp->d_name);
457                 else
458                         ret = unlinkat(dfd, direntp->d_name, 0);
459                 if (ret < 0 && errno != ENOENT)
460                         break;
461         }
462
463         ret = unlinkat(fd, path, AT_REMOVEDIR);
464         closedir(dir);
465         return ret;
466 }
467
468 /* chown_r - recursively change ownership of all files */
469 static int chown_r(int fd, const char *path, uid_t uid, gid_t gid)
470 {
471         int dfd, ret;
472         DIR *dir;
473         struct dirent *direntp;
474
475         dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY);
476         if (dfd < 0)
477                 return -1;
478
479         dir = fdopendir(dfd);
480         if (!dir) {
481                 close(dfd);
482                 return -1;
483         }
484
485         while ((direntp = readdir(dir))) {
486                 struct stat st;
487
488                 if (!strcmp(direntp->d_name, ".") ||
489                     !strcmp(direntp->d_name, ".."))
490                         continue;
491
492                 ret = fstatat(dfd, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
493                 if (ret < 0 && errno != ENOENT)
494                         break;
495
496                 if (S_ISDIR(st.st_mode))
497                         ret = chown_r(dfd, direntp->d_name, uid, gid);
498                 else
499                         ret = fchownat(dfd, direntp->d_name, uid, gid, AT_SYMLINK_NOFOLLOW);
500                 if (ret < 0 && errno != ENOENT)
501                         break;
502         }
503
504         ret = fchownat(fd, path, uid, gid, AT_SYMLINK_NOFOLLOW);
505         closedir(dir);
506         return ret;
507 }
508
509 /*
510  * There'll be scenarios where you'll want to see the attributes associated with
511  * a directory tree during debugging or just to make sure things look correct.
512  * Simply uncomment and place the print_r() helper where you need it.
513  */
514 #ifdef DEBUG_TRACE
515 static int fd_cloexec(int fd, bool cloexec)
516 {
517         int oflags, nflags;
518
519         oflags = fcntl(fd, F_GETFD, 0);
520         if (oflags < 0)
521                 return -errno;
522
523         if (cloexec)
524                 nflags = oflags | FD_CLOEXEC;
525         else
526                 nflags = oflags & ~FD_CLOEXEC;
527
528         if (nflags == oflags)
529                 return 0;
530
531         if (fcntl(fd, F_SETFD, nflags) < 0)
532                 return -errno;
533
534         return 0;
535 }
536
537 static inline int dup_cloexec(int fd)
538 {
539         int fd_dup;
540
541         fd_dup = dup(fd);
542         if (fd_dup < 0)
543                 return -errno;
544
545         if (fd_cloexec(fd_dup, true)) {
546                 close(fd_dup);
547                 return -errno;
548         }
549
550         return fd_dup;
551 }
552
553 __attribute__((unused)) static int print_r(int fd, const char *path)
554 {
555         int ret = 0;
556         int dfd, dfd_dup;
557         DIR *dir;
558         struct dirent *direntp;
559         struct stat st;
560
561         if (!path || *path == '\0') {
562                 char buf[sizeof("/proc/self/fd/") + 30];
563
564                 ret = snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
565                 if (ret < 0 || (size_t)ret >= sizeof(buf))
566                         return -1;
567
568                 /*
569                  * O_PATH file descriptors can't be used so we need to re-open
570                  * just in case.
571                  */
572                 dfd = openat(-EBADF, buf, O_CLOEXEC | O_DIRECTORY, 0);
573         } else {
574                 dfd = openat(fd, path, O_CLOEXEC | O_DIRECTORY, 0);
575         }
576         if (dfd < 0)
577                 return -1;
578
579         /*
580          * When fdopendir() below succeeds it assumes ownership of the fd so we
581          * to make sure we always have an fd that fdopendir() can own which is
582          * why we dup() in the case where the caller wants us to operate on the
583          * fd directly.
584          */
585         dfd_dup = dup_cloexec(dfd);
586         if (dfd_dup < 0) {
587                 close(dfd);
588                 return -1;
589         }
590
591         dir = fdopendir(dfd);
592         if (!dir) {
593                 close(dfd);
594                 close(dfd_dup);
595                 return -1;
596         }
597         /* Transfer ownership to fdopendir(). */
598         dfd = -EBADF;
599
600         while ((direntp = readdir(dir))) {
601                 if (!strcmp(direntp->d_name, ".") ||
602                     !strcmp(direntp->d_name, ".."))
603                         continue;
604
605                 ret = fstatat(dfd_dup, direntp->d_name, &st, AT_SYMLINK_NOFOLLOW);
606                 if (ret < 0 && errno != ENOENT)
607                         break;
608
609                 ret = 0;
610                 if (S_ISDIR(st.st_mode))
611                         ret = print_r(dfd_dup, direntp->d_name);
612                 else
613                         fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %d/%s\n",
614                                 (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
615                                 dfd_dup, direntp->d_name);
616                 if (ret < 0 && errno != ENOENT)
617                         break;
618         }
619
620         if (!path || *path == '\0')
621                 ret = fstatat(fd, "", &st,
622                               AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW |
623                               AT_EMPTY_PATH);
624         else
625                 ret = fstatat(fd, path, &st,
626                               AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW);
627         if (!ret)
628                 fprintf(stderr, "mode(%o):uid(%d):gid(%d) -> %s",
629                         (st.st_mode & ~S_IFMT), st.st_uid, st.st_gid,
630                         (path && *path) ? path : "(null)");
631
632         close(dfd_dup);
633         closedir(dir);
634
635         return ret;
636 }
637 #endif
638
639 /* fd_to_fd - transfer data from one fd to another */
640 static int fd_to_fd(int from, int to)
641 {
642         for (;;) {
643                 uint8_t buf[PATH_MAX];
644                 uint8_t *p = buf;
645                 ssize_t bytes_to_write;
646                 ssize_t bytes_read;
647
648                 bytes_read = read_nointr(from, buf, sizeof buf);
649                 if (bytes_read < 0)
650                         return -1;
651                 if (bytes_read == 0)
652                         break;
653
654                 bytes_to_write = (size_t)bytes_read;
655                 do {
656                         ssize_t bytes_written;
657
658                         bytes_written = write_nointr(to, p, bytes_to_write);
659                         if (bytes_written < 0)
660                                 return -1;
661
662                         bytes_to_write -= bytes_written;
663                         p += bytes_written;
664                 } while (bytes_to_write > 0);
665         }
666
667         return 0;
668 }
669
670 static int sys_execveat(int fd, const char *path, char **argv, char **envp,
671                         int flags)
672 {
673 #ifdef __NR_execveat
674         return syscall(__NR_execveat, fd, path, argv, envp, flags);
675 #else
676         errno = ENOSYS;
677         return -1;
678 #endif
679 }
680
681 #ifndef CAP_NET_RAW
682 #define CAP_NET_RAW 13
683 #endif
684
685 #ifndef VFS_CAP_FLAGS_EFFECTIVE
686 #define VFS_CAP_FLAGS_EFFECTIVE 0x000001
687 #endif
688
689 #ifndef VFS_CAP_U32_3
690 #define VFS_CAP_U32_3 2
691 #endif
692
693 #ifndef VFS_CAP_U32
694 #define VFS_CAP_U32 VFS_CAP_U32_3
695 #endif
696
697 #ifndef VFS_CAP_REVISION_1
698 #define VFS_CAP_REVISION_1 0x01000000
699 #endif
700
701 #ifndef VFS_CAP_REVISION_2
702 #define VFS_CAP_REVISION_2 0x02000000
703 #endif
704
705 #ifndef VFS_CAP_REVISION_3
706 #define VFS_CAP_REVISION_3 0x03000000
707 struct vfs_ns_cap_data {
708         __le32 magic_etc;
709         struct {
710                 __le32 permitted;
711                 __le32 inheritable;
712         } data[VFS_CAP_U32];
713         __le32 rootid;
714 };
715 #endif
716
717 #if __BYTE_ORDER == __BIG_ENDIAN
718 #define cpu_to_le16(w16) le16_to_cpu(w16)
719 #define le16_to_cpu(w16) ((u_int16_t)((u_int16_t)(w16) >> 8) | (u_int16_t)((u_int16_t)(w16) << 8))
720 #define cpu_to_le32(w32) le32_to_cpu(w32)
721 #define le32_to_cpu(w32)                                                                       \
722         ((u_int32_t)((u_int32_t)(w32) >> 24) | (u_int32_t)(((u_int32_t)(w32) >> 8) & 0xFF00) | \
723          (u_int32_t)(((u_int32_t)(w32) << 8) & 0xFF0000) | (u_int32_t)((u_int32_t)(w32) << 24))
724 #elif __BYTE_ORDER == __LITTLE_ENDIAN
725 #define cpu_to_le16(w16) ((u_int16_t)(w16))
726 #define le16_to_cpu(w16) ((u_int16_t)(w16))
727 #define cpu_to_le32(w32) ((u_int32_t)(w32))
728 #define le32_to_cpu(w32) ((u_int32_t)(w32))
729 #else
730 #error Expected endianess macro to be set
731 #endif
732
733 /* expected_dummy_vfs_caps_uid - check vfs caps are stored with the provided uid */
734 static bool expected_dummy_vfs_caps_uid(int fd, uid_t expected_uid)
735 {
736 #define __cap_raised_permitted(x, ns_cap_data)                                 \
737         ((ns_cap_data.data[(x) >> 5].permitted) & (1 << ((x)&31)))
738         struct vfs_ns_cap_data ns_xattr = {};
739         ssize_t ret;
740
741         ret = fgetxattr(fd, "security.capability", &ns_xattr, sizeof(ns_xattr));
742         if (ret < 0 || ret == 0)
743                 return false;
744
745         if (ns_xattr.magic_etc & VFS_CAP_REVISION_3) {
746
747                 if (le32_to_cpu(ns_xattr.rootid) != expected_uid) {
748                         errno = EINVAL;
749                         log_stderr("failure: rootid(%d) != expected_rootid(%d)", le32_to_cpu(ns_xattr.rootid), expected_uid);
750                 }
751
752                 return (le32_to_cpu(ns_xattr.rootid) == expected_uid) &&
753                        (__cap_raised_permitted(CAP_NET_RAW, ns_xattr) > 0);
754         } else {
755                 log_stderr("failure: fscaps version");
756         }
757
758         return false;
759 }
760
761 /* set_dummy_vfs_caps - set dummy vfs caps for the provided uid */
762 static int set_dummy_vfs_caps(int fd, int flags, int rootuid)
763 {
764 #define __raise_cap_permitted(x, ns_cap_data)                                  \
765         ns_cap_data.data[(x) >> 5].permitted |= (1 << ((x)&31))
766
767         struct vfs_ns_cap_data ns_xattr;
768
769         memset(&ns_xattr, 0, sizeof(ns_xattr));
770         __raise_cap_permitted(CAP_NET_RAW, ns_xattr);
771         ns_xattr.magic_etc |= VFS_CAP_REVISION_3 | VFS_CAP_FLAGS_EFFECTIVE;
772         ns_xattr.rootid = cpu_to_le32(rootuid);
773
774         return fsetxattr(fd, "security.capability",
775                          &ns_xattr, sizeof(ns_xattr), flags);
776 }
777
778 #define safe_close(fd)      \
779         if (fd >= 0) {           \
780                 int _e_ = errno; \
781                 close(fd);       \
782                 errno = _e_;     \
783                 fd = -EBADF;     \
784         }
785
786 static void test_setup(void)
787 {
788         if (mkdirat(t_mnt_fd, T_DIR1, 0777))
789                 die("failure: mkdirat");
790
791         t_dir1_fd = openat(t_mnt_fd, T_DIR1, O_CLOEXEC | O_DIRECTORY);
792         if (t_dir1_fd < 0)
793                 die("failure: openat");
794
795         if (fchmod(t_dir1_fd, 0777))
796                 die("failure: fchmod");
797 }
798
799 static void test_cleanup(void)
800 {
801         safe_close(t_dir1_fd);
802         if (rm_r(t_mnt_fd, T_DIR1))
803                 die("failure: rm_r");
804 }
805
806 /* Validate that basic file operations on idmapped mounts. */
807 static int fsids_unmapped(void)
808 {
809         int fret = -1;
810         int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
811         struct mount_attr attr = {
812                 .attr_set = MOUNT_ATTR_IDMAP,
813         };
814
815         /* create hardlink target */
816         hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
817         if (hardlink_target_fd < 0) {
818                 log_stderr("failure: openat");
819                 goto out;
820         }
821
822         /* create directory for rename test */
823         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
824                 log_stderr("failure: mkdirat");
825                 goto out;
826         }
827
828         /* change ownership of all files to uid 0 */
829         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
830                 log_stderr("failure: chown_r");
831                 goto out;
832         }
833
834         /* Changing mount properties on a detached mount. */
835         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
836         if (attr.userns_fd < 0) {
837                 log_stderr("failure: get_userns_fd");
838                 goto out;
839         }
840
841         open_tree_fd = sys_open_tree(t_dir1_fd, "",
842                                      AT_EMPTY_PATH |
843                                      AT_NO_AUTOMOUNT |
844                                      AT_SYMLINK_NOFOLLOW |
845                                      OPEN_TREE_CLOEXEC |
846                                      OPEN_TREE_CLONE);
847         if (open_tree_fd < 0) {
848                 log_stderr("failure: sys_open_tree");
849                 goto out;
850         }
851
852         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
853                 log_stderr("failure: sys_mount_setattr");
854                 goto out;
855         }
856
857         if (!switch_fsids(0, 0)) {
858                 log_stderr("failure: switch_fsids");
859                 goto out;
860         }
861
862         /* The caller's fsids don't have a mappings in the idmapped mount so any
863          * file creation must fail.
864          */
865
866         /* create hardlink */
867         if (!linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
868                 log_stderr("failure: linkat");
869                 goto out;
870         }
871         if (errno != EOVERFLOW) {
872                 log_stderr("failure: errno");
873                 goto out;
874         }
875
876         /* try to rename a file */
877         if (!renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME)) {
878                 log_stderr("failure: renameat");
879                 goto out;
880         }
881         if (errno != EOVERFLOW) {
882                 log_stderr("failure: errno");
883                 goto out;
884         }
885
886         /* try to rename a directory */
887         if (!renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME)) {
888                 log_stderr("failure: renameat");
889                 goto out;
890         }
891         if (errno != EOVERFLOW) {
892                 log_stderr("failure: errno");
893                 goto out;
894         }
895
896         /* The caller is privileged over the inode so file deletion must work. */
897
898         /* remove file */
899         if (unlinkat(open_tree_fd, FILE1, 0)) {
900                 log_stderr("failure: unlinkat");
901                 goto out;
902         }
903
904         /* remove directory */
905         if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR)) {
906                 log_stderr("failure: unlinkat");
907                 goto out;
908         }
909
910         /* The caller's fsids don't have a mappings in the idmapped mount so
911          * any file creation must fail.
912          */
913
914         /* create regular file via open() */
915         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
916         if (file1_fd >= 0) {
917                 log_stderr("failure: create");
918                 goto out;
919         }
920         if (errno != EOVERFLOW) {
921                 log_stderr("failure: errno");
922                 goto out;
923         }
924
925         /* create regular file via mknod */
926         if (!mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0)) {
927                 log_stderr("failure: mknodat");
928                 goto out;
929         }
930         if (errno != EOVERFLOW) {
931                 log_stderr("failure: errno");
932                 goto out;
933         }
934
935         /* create character device */
936         if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
937                 log_stderr("failure: mknodat");
938                 goto out;
939         }
940         if (errno != EOVERFLOW) {
941                 log_stderr("failure: errno");
942                 goto out;
943         }
944
945         /* create symlink */
946         if (!symlinkat(FILE2, open_tree_fd, SYMLINK1)) {
947                 log_stderr("failure: symlinkat");
948                 goto out;
949         }
950         if (errno != EOVERFLOW) {
951                 log_stderr("failure: errno");
952                 goto out;
953         }
954
955         /* create directory */
956         if (!mkdirat(open_tree_fd, DIR1, 0700)) {
957                 log_stderr("failure: mkdirat");
958                 goto out;
959         }
960         if (errno != EOVERFLOW) {
961                 log_stderr("failure: errno");
962                 goto out;
963         }
964
965         fret = 0;
966         log_debug("Ran test");
967 out:
968         safe_close(attr.userns_fd);
969         safe_close(hardlink_target_fd);
970         safe_close(file1_fd);
971         safe_close(open_tree_fd);
972
973         return fret;
974 }
975
976 static int fsids_mapped(void)
977 {
978         int fret = -1;
979         int file1_fd = -EBADF, hardlink_target_fd = -EBADF, open_tree_fd = -EBADF;
980         struct mount_attr attr = {
981                 .attr_set = MOUNT_ATTR_IDMAP,
982         };
983         pid_t pid;
984
985         if (!caps_supported())
986                 return 0;
987
988         /* create hardlink target */
989         hardlink_target_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
990         if (hardlink_target_fd < 0) {
991                 log_stderr("failure: openat");
992                 goto out;
993         }
994
995         /* create directory for rename test */
996         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
997                 log_stderr("failure: mkdirat");
998                 goto out;
999         }
1000
1001         /* change ownership of all files to uid 0 */
1002         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1003                 log_stderr("failure: chown_r");
1004                 goto out;
1005         }
1006
1007         /* Changing mount properties on a detached mount. */
1008         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1009         if (attr.userns_fd < 0) {
1010                 log_stderr("failure: get_userns_fd");
1011                 goto out;
1012         }
1013
1014         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1015                                      AT_EMPTY_PATH |
1016                                      AT_NO_AUTOMOUNT |
1017                                      AT_SYMLINK_NOFOLLOW |
1018                                      OPEN_TREE_CLOEXEC |
1019                                      OPEN_TREE_CLONE);
1020         if (open_tree_fd < 0) {
1021                 log_stderr("failure: sys_open_tree");
1022                 goto out;
1023         }
1024
1025         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1026                 log_stderr("failure: sys_mount_setattr");
1027                 goto out;
1028         }
1029
1030         pid = fork();
1031         if (pid < 0) {
1032                 log_stderr("failure: fork");
1033                 goto out;
1034         }
1035         if (pid == 0) {
1036                 if (!switch_fsids(10000, 10000))
1037                         die("failure: switch fsids");
1038
1039                 if (!caps_up())
1040                         die("failure: raise caps");
1041
1042                 /* The caller's fsids now have mappings in the idmapped mount so
1043                  * any file creation must fail.
1044                  */
1045
1046                 /* create hardlink */
1047                 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1048                         die("failure: create hardlink");
1049
1050                 /* try to rename a file */
1051                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1052                         die("failure: rename");
1053
1054                 /* try to rename a directory */
1055                 if (renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME))
1056                         die("failure: rename");
1057
1058                 /* remove file */
1059                 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1060                         die("failure: delete");
1061
1062                 /* remove directory */
1063                 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1064                         die("failure: delete");
1065
1066                 /* The caller's fsids have mappings in the idmapped mount so any
1067                  * file creation must fail.
1068                  */
1069
1070                 /* create regular file via open() */
1071                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1072                 if (file1_fd < 0)
1073                         die("failure: create");
1074
1075                 /* create regular file via mknod */
1076                 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1077                         die("failure: create");
1078
1079                 /* create character device */
1080                 if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
1081                         die("failure: create");
1082
1083                 /* create symlink */
1084                 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1085                         die("failure: create");
1086
1087                 /* create directory */
1088                 if (mkdirat(open_tree_fd, DIR1, 0700))
1089                         die("failure: create");
1090
1091                 exit(EXIT_SUCCESS);
1092         }
1093         if (wait_for_pid(pid))
1094                 goto out;
1095
1096         fret = 0;
1097         log_debug("Ran test");
1098 out:
1099         safe_close(attr.userns_fd);
1100         safe_close(file1_fd);
1101         safe_close(hardlink_target_fd);
1102         safe_close(open_tree_fd);
1103
1104         return fret;
1105 }
1106
1107 /* Validate that basic file operations on idmapped mounts from a user namespace. */
1108 static int create_in_userns(void)
1109 {
1110         int fret = -1;
1111         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1112         struct mount_attr attr = {
1113                 .attr_set = MOUNT_ATTR_IDMAP,
1114         };
1115         pid_t pid;
1116
1117         /* change ownership of all files to uid 0 */
1118         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1119                 log_stderr("failure: chown_r");
1120                 goto out;
1121         }
1122
1123         /* Changing mount properties on a detached mount. */
1124         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1125         if (attr.userns_fd < 0) {
1126                 log_stderr("failure: get_userns_fd");
1127                 goto out;
1128         }
1129
1130         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1131                                      AT_EMPTY_PATH |
1132                                      AT_NO_AUTOMOUNT |
1133                                      AT_SYMLINK_NOFOLLOW |
1134                                      OPEN_TREE_CLOEXEC |
1135                                      OPEN_TREE_CLONE);
1136         if (open_tree_fd < 0) {
1137                 log_stderr("failure: sys_open_tree");
1138                 goto out;
1139         }
1140
1141         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1142                 log_stderr("failure: sys_mount_setattr");
1143                 goto out;
1144         }
1145
1146         pid = fork();
1147         if (pid < 0) {
1148                 log_stderr("failure: fork");
1149                 goto out;
1150         }
1151         if (pid == 0) {
1152                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1153                         die("failure: switch_userns");
1154
1155                 /* create regular file via open() */
1156                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1157                 if (file1_fd < 0)
1158                         die("failure: open file");
1159                 safe_close(file1_fd);
1160
1161                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1162                         die("failure: check ownership");
1163
1164                 /* create regular file via mknod */
1165                 if (mknodat(open_tree_fd, FILE2, S_IFREG | 0000, 0))
1166                         die("failure: create");
1167
1168                 if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
1169                         die("failure: check ownership");
1170
1171                 /* create symlink */
1172                 if (symlinkat(FILE2, open_tree_fd, SYMLINK1))
1173                         die("failure: create");
1174
1175                 if (!expected_uid_gid(open_tree_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0))
1176                         die("failure: check ownership");
1177
1178                 /* create directory */
1179                 if (mkdirat(open_tree_fd, DIR1, 0700))
1180                         die("failure: create");
1181
1182                 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
1183                         die("failure: check ownership");
1184
1185                 /* try to rename a file */
1186                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1187                         die("failure: create");
1188
1189                 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1190                         die("failure: check ownership");
1191
1192                 /* try to rename a file */
1193                 if (renameat(open_tree_fd, DIR1, open_tree_fd, DIR1_RENAME))
1194                         die("failure: create");
1195
1196                 if (!expected_uid_gid(open_tree_fd, DIR1_RENAME, 0, 0, 0))
1197                         die("failure: check ownership");
1198
1199                 /* remove file */
1200                 if (unlinkat(open_tree_fd, FILE1_RENAME, 0))
1201                         die("failure: remove");
1202
1203                 /* remove directory */
1204                 if (unlinkat(open_tree_fd, DIR1_RENAME, AT_REMOVEDIR))
1205                         die("failure: remove");
1206
1207                 exit(EXIT_SUCCESS);
1208         }
1209
1210         if (wait_for_pid(pid))
1211                 goto out;
1212
1213         fret = 0;
1214         log_debug("Ran test");
1215 out:
1216         safe_close(attr.userns_fd);
1217         safe_close(file1_fd);
1218         safe_close(open_tree_fd);
1219
1220         return fret;
1221 }
1222
1223 static int hardlink_crossing_mounts(void)
1224 {
1225         int fret = -1;
1226         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1227
1228         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1229                 log_stderr("failure: chown_r");
1230                 goto out;
1231         }
1232
1233         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1234                                      AT_EMPTY_PATH |
1235                                      AT_NO_AUTOMOUNT |
1236                                      AT_SYMLINK_NOFOLLOW |
1237                                      OPEN_TREE_CLOEXEC |
1238                                      OPEN_TREE_CLONE);
1239         if (open_tree_fd < 0) {
1240                 log_stderr("failure: sys_open_tree");
1241                 goto out;
1242         }
1243
1244         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1245         if (file1_fd < 0) {
1246                 log_stderr("failure: openat");
1247                 goto out;
1248         }
1249
1250         if (mkdirat(open_tree_fd, DIR1, 0777)) {
1251                 log_stderr("failure: mkdirat");
1252                 goto out;
1253         }
1254
1255         /* We're crossing a mountpoint so this must fail.
1256          *
1257          * Note that this must also fail for non-idmapped mounts but here we're
1258          * interested in making sure we're not introducing an accidental way to
1259          * violate that restriction or that suddenly this becomes possible.
1260          */
1261         if (!linkat(open_tree_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
1262                 log_stderr("failure: linkat");
1263                 goto out;
1264         }
1265         if (errno != EXDEV) {
1266                 log_stderr("failure: errno");
1267                 goto out;
1268         }
1269
1270         fret = 0;
1271         log_debug("Ran test");
1272 out:
1273         safe_close(file1_fd);
1274         safe_close(open_tree_fd);
1275
1276         return fret;
1277 }
1278
1279 static int hardlink_crossing_idmapped_mounts(void)
1280 {
1281         int fret = -1;
1282         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1283         struct mount_attr attr = {
1284                 .attr_set = MOUNT_ATTR_IDMAP,
1285         };
1286
1287         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1288                 log_stderr("failure: chown_r");
1289                 goto out;
1290         }
1291
1292         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1293         if (attr.userns_fd < 0) {
1294                 log_stderr("failure: get_userns_fd");
1295                 goto out;
1296         }
1297
1298         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1299                                      AT_EMPTY_PATH |
1300                                      AT_NO_AUTOMOUNT |
1301                                      AT_SYMLINK_NOFOLLOW |
1302                                      OPEN_TREE_CLOEXEC |
1303                                      OPEN_TREE_CLONE);
1304         if (open_tree_fd1 < 0) {
1305                 log_stderr("failure: sys_open_tree");
1306                 goto out;
1307         }
1308
1309         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1310                 log_stderr("failure: sys_mount_setattr");
1311                 goto out;
1312         }
1313
1314         file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1315         if (file1_fd < 0) {
1316                 log_stderr("failure: openat");
1317                 goto out;
1318         }
1319
1320         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1321                 log_stderr("failure: expected_uid_gid");
1322                 goto out;
1323         }
1324
1325         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1326                 log_stderr("failure: expected_uid_gid");
1327                 goto out;
1328         }
1329
1330         safe_close(file1_fd);
1331
1332         if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1333                 log_stderr("failure: mkdirat");
1334                 goto out;
1335         }
1336
1337         open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1338                                       AT_NO_AUTOMOUNT |
1339                                       AT_SYMLINK_NOFOLLOW |
1340                                       OPEN_TREE_CLOEXEC |
1341                                       OPEN_TREE_CLONE |
1342                                       AT_RECURSIVE);
1343         if (open_tree_fd2 < 0) {
1344                 log_stderr("failure: sys_open_tree");
1345                 goto out;
1346         }
1347
1348         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1349                 log_stderr("failure: sys_mount_setattr");
1350                 goto out;
1351         }
1352
1353         /* We're crossing a mountpoint so this must fail.
1354          *
1355          * Note that this must also fail for non-idmapped mounts but here we're
1356          * interested in making sure we're not introducing an accidental way to
1357          * violate that restriction or that suddenly this becomes possible.
1358          */
1359         if (!linkat(open_tree_fd1, FILE1, open_tree_fd2, HARDLINK1, 0)) {
1360                 log_stderr("failure: linkat");
1361                 goto out;
1362         }
1363         if (errno != EXDEV) {
1364                 log_stderr("failure: errno");
1365                 goto out;
1366         }
1367
1368         fret = 0;
1369         log_debug("Ran test");
1370 out:
1371         safe_close(attr.userns_fd);
1372         safe_close(file1_fd);
1373         safe_close(open_tree_fd1);
1374         safe_close(open_tree_fd2);
1375
1376         return fret;
1377 }
1378
1379 static int hardlink_from_idmapped_mount(void)
1380 {
1381         int fret = -1;
1382         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1383         struct mount_attr attr = {
1384                 .attr_set = MOUNT_ATTR_IDMAP,
1385         };
1386
1387         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1388                 log_stderr("failure: chown_r");
1389                 goto out;
1390         }
1391
1392         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1393         if (attr.userns_fd < 0) {
1394                 log_stderr("failure: get_userns_fd");
1395                 goto out;
1396         }
1397
1398         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1399                                      AT_EMPTY_PATH |
1400                                      AT_NO_AUTOMOUNT |
1401                                      AT_SYMLINK_NOFOLLOW |
1402                                      OPEN_TREE_CLOEXEC |
1403                                      OPEN_TREE_CLONE);
1404         if (open_tree_fd < 0) {
1405                 log_stderr("failure: sys_open_tree");
1406                 goto out;
1407         }
1408
1409         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1410                 log_stderr("failure: sys_mount_setattr");
1411                 goto out;
1412         }
1413
1414         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1415         if (file1_fd < 0) {
1416                 log_stderr("failure: openat");
1417                 goto out;
1418         }
1419         safe_close(file1_fd);
1420
1421         if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1422                 log_stderr("failure: expected_uid_gid");
1423                 goto out;
1424         }
1425
1426         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1427                 log_stderr("failure: expected_uid_gid");
1428                 goto out;
1429         }
1430
1431         /* We're not crossing a mountpoint so this must succeed. */
1432         if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0)) {
1433                 log_stderr("failure: linkat");
1434                 goto out;
1435         }
1436
1437
1438         fret = 0;
1439         log_debug("Ran test");
1440 out:
1441         safe_close(attr.userns_fd);
1442         safe_close(file1_fd);
1443         safe_close(open_tree_fd);
1444
1445         return fret;
1446 }
1447
1448 static int hardlink_from_idmapped_mount_in_userns(void)
1449 {
1450         int fret = -1;
1451         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1452         struct mount_attr attr = {
1453                 .attr_set = MOUNT_ATTR_IDMAP,
1454         };
1455         pid_t pid;
1456
1457         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1458                 log_stderr("failure: chown_r");
1459                 goto out;
1460         }
1461
1462         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1463         if (attr.userns_fd < 0) {
1464                 log_stderr("failure: get_userns_fd");
1465                 goto out;
1466         }
1467
1468         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1469                                      AT_EMPTY_PATH |
1470                                      AT_NO_AUTOMOUNT |
1471                                      AT_SYMLINK_NOFOLLOW |
1472                                      OPEN_TREE_CLOEXEC |
1473                                      OPEN_TREE_CLONE);
1474         if (open_tree_fd < 0) {
1475                 log_stderr("failure: sys_open_tree");
1476                 goto out;
1477         }
1478
1479         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1480                 log_stderr("failure: sys_mount_setattr");
1481                 goto out;
1482         }
1483
1484         pid = fork();
1485         if (pid < 0) {
1486                 log_stderr("failure: fork");
1487                 goto out;
1488         }
1489         if (pid == 0) {
1490                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1491                         die("failure: switch_userns");
1492
1493                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1494                 if (file1_fd < 0)
1495                         die("failure: create");
1496
1497                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1498                         die("failure: check ownership");
1499
1500                 /* We're not crossing a mountpoint so this must succeed. */
1501                 if (linkat(open_tree_fd, FILE1, open_tree_fd, HARDLINK1, 0))
1502                         die("failure: create");
1503
1504                 if (!expected_uid_gid(open_tree_fd, HARDLINK1, 0, 0, 0))
1505                         die("failure: check ownership");
1506
1507                 exit(EXIT_SUCCESS);
1508         }
1509
1510         if (wait_for_pid(pid))
1511                 goto out;
1512
1513         fret = 0;
1514         log_debug("Ran test");
1515 out:
1516         safe_close(attr.userns_fd);
1517         safe_close(file1_fd);
1518         safe_close(open_tree_fd);
1519
1520         return fret;
1521 }
1522
1523 static int rename_crossing_mounts(void)
1524 {
1525         int fret = -1;
1526         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1527
1528         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1529                 log_stderr("failure: chown_r");
1530                 goto out;
1531         }
1532
1533         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1534                                      AT_EMPTY_PATH |
1535                                      AT_NO_AUTOMOUNT |
1536                                      AT_SYMLINK_NOFOLLOW |
1537                                      OPEN_TREE_CLOEXEC |
1538                                      OPEN_TREE_CLONE);
1539         if (open_tree_fd < 0) {
1540                 log_stderr("failure: sys_open_tree");
1541                 goto out;
1542         }
1543
1544         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1545         if (file1_fd < 0) {
1546                 log_stderr("failure: openat");
1547                 goto out;
1548         }
1549
1550         if (mkdirat(open_tree_fd, DIR1, 0777)) {
1551                 log_stderr("failure: mkdirat");
1552                 goto out;
1553         }
1554
1555         /* We're crossing a mountpoint so this must fail.
1556          *
1557          * Note that this must also fail for non-idmapped mounts but here we're
1558          * interested in making sure we're not introducing an accidental way to
1559          * violate that restriction or that suddenly this becomes possible.
1560          */
1561         if (!renameat(open_tree_fd, FILE1, t_dir1_fd, FILE1_RENAME)) {
1562                 log_stderr("failure: renameat");
1563                 goto out;
1564         }
1565         if (errno != EXDEV) {
1566                 log_stderr("failure: errno");
1567                 goto out;
1568         }
1569
1570         fret = 0;
1571         log_debug("Ran test");
1572 out:
1573         safe_close(file1_fd);
1574         safe_close(open_tree_fd);
1575
1576         return fret;
1577 }
1578
1579 static int rename_crossing_idmapped_mounts(void)
1580 {
1581         int fret = -1;
1582         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
1583         struct mount_attr attr = {
1584                 .attr_set = MOUNT_ATTR_IDMAP,
1585         };
1586
1587         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1588                 log_stderr("failure: chown_r");
1589                 goto out;
1590         }
1591
1592         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1593         if (attr.userns_fd < 0) {
1594                 log_stderr("failure: get_userns_fd");
1595                 goto out;
1596         }
1597
1598         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
1599                                      AT_EMPTY_PATH |
1600                                      AT_NO_AUTOMOUNT |
1601                                      AT_SYMLINK_NOFOLLOW |
1602                                      OPEN_TREE_CLOEXEC |
1603                                      OPEN_TREE_CLONE);
1604         if (open_tree_fd1 < 0) {
1605                 log_stderr("failure: sys_open_tree");
1606                 goto out;
1607         }
1608
1609         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1610                 log_stderr("failure: sys_mount_setattr");
1611                 goto out;
1612         }
1613
1614         file1_fd = openat(open_tree_fd1, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1615         if (file1_fd < 0) {
1616                 log_stderr("failure: openat");
1617                 goto out;
1618         }
1619
1620         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 0, 0)) {
1621                 log_stderr("failure: expected_uid_gid");
1622                 goto out;
1623         }
1624
1625         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1626                 log_stderr("failure: expected_uid_gid");
1627                 goto out;
1628         }
1629
1630         if (mkdirat(open_tree_fd1, DIR1, 0777)) {
1631                 log_stderr("failure: mkdirat");
1632                 goto out;
1633         }
1634
1635         open_tree_fd2 = sys_open_tree(t_dir1_fd, DIR1,
1636                                       AT_NO_AUTOMOUNT |
1637                                       AT_SYMLINK_NOFOLLOW |
1638                                       OPEN_TREE_CLOEXEC |
1639                                       OPEN_TREE_CLONE |
1640                                       AT_RECURSIVE);
1641         if (open_tree_fd2 < 0) {
1642                 log_stderr("failure: sys_open_tree");
1643                 goto out;
1644         }
1645
1646         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1647                 log_stderr("failure: sys_mount_setattr");
1648                 goto out;
1649         }
1650
1651         /* We're crossing a mountpoint so this must fail.
1652          *
1653          * Note that this must also fail for non-idmapped mounts but here we're
1654          * interested in making sure we're not introducing an accidental way to
1655          * violate that restriction or that suddenly this becomes possible.
1656          */
1657         if (!renameat(open_tree_fd1, FILE1, open_tree_fd2, FILE1_RENAME)) {
1658                 log_stderr("failure: renameat");
1659                 goto out;
1660         }
1661         if (errno != EXDEV) {
1662                 log_stderr("failure: errno");
1663                 goto out;
1664         }
1665
1666         fret = 0;
1667         log_debug("Ran test");
1668 out:
1669         safe_close(attr.userns_fd);
1670         safe_close(file1_fd);
1671         safe_close(open_tree_fd1);
1672         safe_close(open_tree_fd2);
1673
1674         return fret;
1675 }
1676
1677 static int rename_from_idmapped_mount(void)
1678 {
1679         int fret = -1;
1680         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1681         struct mount_attr attr = {
1682                 .attr_set = MOUNT_ATTR_IDMAP,
1683         };
1684
1685         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1686                 log_stderr("failure: chown_r");
1687                 goto out;
1688         }
1689
1690         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
1691         if (attr.userns_fd < 0) {
1692                 log_stderr("failure: get_userns_fd");
1693                 goto out;
1694         }
1695
1696         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1697                                      AT_EMPTY_PATH |
1698                                      AT_NO_AUTOMOUNT |
1699                                      AT_SYMLINK_NOFOLLOW |
1700                                      OPEN_TREE_CLOEXEC |
1701                                      OPEN_TREE_CLONE);
1702         if (open_tree_fd < 0) {
1703                 log_stderr("failure: sys_open_tree");
1704                 goto out;
1705         }
1706
1707         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1708                 log_stderr("failure: sys_mount_setattr");
1709                 goto out;
1710         }
1711
1712         file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1713         if (file1_fd < 0) {
1714                 log_stderr("failure: openat");
1715                 goto out;
1716         }
1717
1718         if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0)) {
1719                 log_stderr("failure: expected_uid_gid");
1720                 goto out;
1721         }
1722
1723         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000)) {
1724                 log_stderr("failure: expected_uid_gid");
1725                 goto out;
1726         }
1727
1728         /* We're not crossing a mountpoint so this must succeed. */
1729         if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME)) {
1730                 log_stderr("failure: renameat");
1731                 goto out;
1732         }
1733
1734         fret = 0;
1735         log_debug("Ran test");
1736 out:
1737         safe_close(attr.userns_fd);
1738         safe_close(file1_fd);
1739         safe_close(open_tree_fd);
1740
1741         return fret;
1742 }
1743
1744 static int rename_from_idmapped_mount_in_userns(void)
1745 {
1746         int fret = -1;
1747         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1748         pid_t pid;
1749         struct mount_attr attr = {
1750                 .attr_set = MOUNT_ATTR_IDMAP,
1751         };
1752
1753         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1754                 log_stderr("failure: chown_r");
1755                 goto out;
1756         }
1757
1758         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1759         if (attr.userns_fd < 0) {
1760                 log_stderr("failure: get_userns_fd");
1761                 goto out;
1762         }
1763
1764         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1765                                      AT_EMPTY_PATH |
1766                                      AT_NO_AUTOMOUNT |
1767                                      AT_SYMLINK_NOFOLLOW |
1768                                      OPEN_TREE_CLOEXEC |
1769                                      OPEN_TREE_CLONE);
1770         if (open_tree_fd < 0) {
1771                 log_stderr("failure: sys_open_tree");
1772                 goto out;
1773         }
1774
1775         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1776                 log_stderr("failure: sys_mount_setattr");
1777                 goto out;
1778         }
1779
1780         pid = fork();
1781         if (pid < 0) {
1782                 log_stderr("failure: fork");
1783                 goto out;
1784         }
1785         if (pid == 0) {
1786                 if (!switch_userns(attr.userns_fd, 0, 0, false))
1787                         die("failure: switch_userns");
1788
1789                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1790                 if (file1_fd < 0)
1791                         die("failure: create");
1792
1793                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
1794                         die("failure: check ownership");
1795
1796                 /* We're not crossing a mountpoint so this must succeed. */
1797                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
1798                         die("failure: create");
1799
1800                 if (!expected_uid_gid(open_tree_fd, FILE1_RENAME, 0, 0, 0))
1801                         die("failure: check ownership");
1802
1803                 exit(EXIT_SUCCESS);
1804         }
1805
1806         if (wait_for_pid(pid))
1807                 goto out;
1808
1809         fret = 0;
1810         log_debug("Ran test");
1811 out:
1812         safe_close(attr.userns_fd);
1813         safe_close(file1_fd);
1814         safe_close(open_tree_fd);
1815
1816         return fret;
1817 }
1818
1819 static int symlink_regular_mounts(void)
1820 {
1821         int fret = -1;
1822         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1823         struct stat st;
1824
1825         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1826         if (file1_fd < 0) {
1827                 log_stderr("failure: openat");
1828                 goto out;
1829         }
1830
1831         if (chown_r(t_mnt_fd, T_DIR1, 10000, 10000)) {
1832                 log_stderr("failure: chown_r");
1833                 goto out;
1834         }
1835
1836         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1837                                      AT_EMPTY_PATH |
1838                                      AT_NO_AUTOMOUNT |
1839                                      AT_SYMLINK_NOFOLLOW |
1840                                      OPEN_TREE_CLOEXEC |
1841                                      OPEN_TREE_CLONE);
1842         if (open_tree_fd < 0) {
1843                 log_stderr("failure: sys_open_tree");
1844                 goto out;
1845         }
1846
1847         if (symlinkat(FILE1, open_tree_fd, FILE2)) {
1848                 log_stderr("failure: symlinkat");
1849                 goto out;
1850         }
1851
1852         if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW)) {
1853                 log_stderr("failure: fchownat");
1854                 goto out;
1855         }
1856
1857         if (fstatat(open_tree_fd, FILE2, &st, AT_SYMLINK_NOFOLLOW)) {
1858                 log_stderr("failure: fstatat");
1859                 goto out;
1860         }
1861
1862         if (st.st_uid != 15000 || st.st_gid != 15000) {
1863                 log_stderr("failure: compare ids");
1864                 goto out;
1865         }
1866
1867         if (fstatat(open_tree_fd, FILE1, &st, 0)) {
1868                 log_stderr("failure: fstatat");
1869                 goto out;
1870         }
1871
1872         if (st.st_uid != 10000 || st.st_gid != 10000) {
1873                 log_stderr("failure: compare ids");
1874                 goto out;
1875         }
1876
1877         fret = 0;
1878         log_debug("Ran test");
1879 out:
1880         safe_close(file1_fd);
1881         safe_close(open_tree_fd);
1882
1883         return fret;
1884 }
1885
1886 static int symlink_idmapped_mounts(void)
1887 {
1888         int fret = -1;
1889         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1890         struct mount_attr attr = {
1891                 .attr_set = MOUNT_ATTR_IDMAP,
1892         };
1893         pid_t pid;
1894
1895         if (!caps_supported())
1896                 return 0;
1897
1898         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
1899         if (file1_fd < 0) {
1900                 log_stderr("failure: openat");
1901                 goto out;
1902         }
1903
1904         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1905                 log_stderr("failure: chown_r");
1906                 goto out;
1907         }
1908
1909         /* Changing mount properties on a detached mount. */
1910         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1911         if (attr.userns_fd < 0) {
1912                 log_stderr("failure: get_userns_fd");
1913                 goto out;
1914         }
1915
1916         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1917                                      AT_EMPTY_PATH |
1918                                      AT_NO_AUTOMOUNT |
1919                                      AT_SYMLINK_NOFOLLOW |
1920                                      OPEN_TREE_CLOEXEC |
1921                                      OPEN_TREE_CLONE);
1922         if (open_tree_fd < 0) {
1923                 log_stderr("failure: sys_open_tree");
1924                 goto out;
1925         }
1926
1927         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
1928                 log_stderr("failure: sys_mount_setattr");
1929                 goto out;
1930         }
1931
1932         pid = fork();
1933         if (pid < 0) {
1934                 log_stderr("failure: fork");
1935                 goto out;
1936         }
1937         if (pid == 0) {
1938                 if (!switch_fsids(10000, 10000))
1939                         die("failure: switch fsids");
1940
1941                 if (!caps_up())
1942                         die("failure: raise caps");
1943
1944                 if (symlinkat(FILE1, open_tree_fd, FILE2))
1945                         die("failure: create");
1946
1947                 if (fchownat(open_tree_fd, FILE2, 15000, 15000, AT_SYMLINK_NOFOLLOW))
1948                         die("failure: change ownership");
1949
1950                 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 15000, 15000))
1951                         die("failure: check ownership");
1952
1953                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
1954                         die("failure: check ownership");
1955
1956                 exit(EXIT_SUCCESS);
1957         }
1958         if (wait_for_pid(pid))
1959                 goto out;
1960
1961         fret = 0;
1962         log_debug("Ran test");
1963 out:
1964         safe_close(attr.userns_fd);
1965         safe_close(file1_fd);
1966         safe_close(open_tree_fd);
1967
1968         return fret;
1969 }
1970
1971 static int symlink_idmapped_mounts_in_userns(void)
1972 {
1973         int fret = -1;
1974         int file1_fd = -EBADF, open_tree_fd = -EBADF;
1975         struct mount_attr attr = {
1976                 .attr_set = MOUNT_ATTR_IDMAP,
1977         };
1978         pid_t pid;
1979
1980         if (chown_r(t_mnt_fd, T_DIR1, 0, 0)) {
1981                 log_stderr("failure: chown_r");
1982                 goto out;
1983         }
1984
1985         /* Changing mount properties on a detached mount. */
1986         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
1987         if (attr.userns_fd < 0) {
1988                 log_stderr("failure: get_userns_fd");
1989                 goto out;
1990         }
1991
1992         open_tree_fd = sys_open_tree(t_dir1_fd, "",
1993                                      AT_EMPTY_PATH |
1994                                      AT_NO_AUTOMOUNT |
1995                                      AT_SYMLINK_NOFOLLOW |
1996                                      OPEN_TREE_CLOEXEC |
1997                                      OPEN_TREE_CLONE);
1998         if (open_tree_fd < 0) {
1999                 log_stderr("failure: sys_open_tree");
2000                 goto out;
2001         }
2002
2003         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2004                 log_stderr("failure: sys_mount_setattr");
2005                 goto out;
2006         }
2007
2008         pid = fork();
2009         if (pid < 0) {
2010                 log_stderr("failure: fork");
2011                 goto out;
2012         }
2013         if (pid == 0) {
2014                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2015                         die("failure: switch_userns");
2016
2017                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2018                 if (file1_fd < 0)
2019                         die("failure: create");
2020                 safe_close(file1_fd);
2021
2022                 if (symlinkat(FILE1, open_tree_fd, FILE2))
2023                         die("failure: create");
2024
2025                 if (fchownat(open_tree_fd, FILE2, 5000, 5000, AT_SYMLINK_NOFOLLOW))
2026                         die("failure: change ownership");
2027
2028                 if (!expected_uid_gid(open_tree_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000))
2029                         die("failure: check ownership");
2030
2031                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
2032                         die("failure: check ownership");
2033
2034                 exit(EXIT_SUCCESS);
2035         }
2036
2037         if (wait_for_pid(pid))
2038                 goto out;
2039
2040         if (!expected_uid_gid(t_dir1_fd, FILE2, AT_SYMLINK_NOFOLLOW, 5000, 5000)) {
2041                 log_stderr("failure: expected_uid_gid");
2042                 goto out;
2043         }
2044
2045         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2046                 log_stderr("failure: expected_uid_gid");
2047                 goto out;
2048         }
2049
2050         fret = 0;
2051         log_debug("Ran test");
2052 out:
2053         safe_close(attr.userns_fd);
2054         safe_close(file1_fd);
2055         safe_close(open_tree_fd);
2056
2057         return fret;
2058 }
2059
2060 /* Validate that a caller whose fsids map into the idmapped mount within it's
2061  * user namespace cannot create any device nodes.
2062  */
2063 static int device_node_in_userns(void)
2064 {
2065         int fret = -1;
2066         int open_tree_fd = -EBADF;
2067         struct mount_attr attr = {
2068                 .attr_set = MOUNT_ATTR_IDMAP,
2069         };
2070         pid_t pid;
2071
2072         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2073         if (attr.userns_fd < 0) {
2074                 log_stderr("failure: get_userns_fd");
2075                 goto out;
2076         }
2077
2078         open_tree_fd = sys_open_tree(t_dir1_fd, "",
2079                                      AT_EMPTY_PATH |
2080                                      AT_NO_AUTOMOUNT |
2081                                      AT_SYMLINK_NOFOLLOW |
2082                                      OPEN_TREE_CLOEXEC |
2083                                      OPEN_TREE_CLONE);
2084         if (open_tree_fd < 0) {
2085                 log_stderr("failure: sys_open_tree");
2086                 goto out;
2087         }
2088
2089         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
2090                 log_stderr("failure: sys_mount_setattr");
2091                 goto out;
2092         }
2093
2094         pid = fork();
2095         if (pid < 0) {
2096                 log_stderr("failure: fork");
2097                 goto out;
2098         }
2099         if (pid == 0) {
2100                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2101                         die("failure: switch_userns");
2102
2103                 /* create character device */
2104                 if (!mknodat(open_tree_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1)))
2105                         die("failure: create");
2106
2107                 exit(EXIT_SUCCESS);
2108         }
2109
2110         if (wait_for_pid(pid))
2111                 goto out;
2112
2113         fret = 0;
2114         log_debug("Ran test");
2115 out:
2116         safe_close(attr.userns_fd);
2117         safe_close(open_tree_fd);
2118
2119         return fret;
2120 }
2121
2122
2123 /* Validate that changing file ownership works correctly on idmapped mounts. */
2124 static int expected_uid_gid_idmapped_mounts(void)
2125 {
2126         int fret = -1;
2127         int file1_fd = -EBADF, open_tree_fd1 = -EBADF, open_tree_fd2 = -EBADF;
2128         struct mount_attr attr1 = {
2129                 .attr_set = MOUNT_ATTR_IDMAP,
2130         };
2131         struct mount_attr attr2 = {
2132                 .attr_set = MOUNT_ATTR_IDMAP,
2133         };
2134         pid_t pid;
2135
2136         if (!switch_fsids(0, 0)) {
2137                 log_stderr("failure: switch_fsids");
2138                 goto out;
2139         }
2140
2141         /* create regular file via open() */
2142         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2143         if (file1_fd < 0) {
2144                 log_stderr("failure: openat");
2145                 goto out;
2146         }
2147
2148         /* create regular file via mknod */
2149         if (mknodat(t_dir1_fd, FILE2, S_IFREG | 0000, 0)) {
2150                 log_stderr("failure: mknodat");
2151                 goto out;
2152         }
2153
2154         /* create character device */
2155         if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | 0644, makedev(5, 1))) {
2156                 log_stderr("failure: mknodat");
2157                 goto out;
2158         }
2159
2160         /* create hardlink */
2161         if (linkat(t_dir1_fd, FILE1, t_dir1_fd, HARDLINK1, 0)) {
2162                 log_stderr("failure: linkat");
2163                 goto out;
2164         }
2165
2166         /* create symlink */
2167         if (symlinkat(FILE2, t_dir1_fd, SYMLINK1)) {
2168                 log_stderr("failure: symlinkat");
2169                 goto out;
2170         }
2171
2172         /* create directory */
2173         if (mkdirat(t_dir1_fd, DIR1, 0700)) {
2174                 log_stderr("failure: mkdirat");
2175                 goto out;
2176         }
2177
2178         /* Changing mount properties on a detached mount. */
2179         attr1.userns_fd = get_userns_fd(0, 10000, 10000);
2180         if (attr1.userns_fd < 0) {
2181                 log_stderr("failure: get_userns_fd");
2182                 goto out;
2183         }
2184
2185         open_tree_fd1 = sys_open_tree(t_dir1_fd, "",
2186                                      AT_EMPTY_PATH |
2187                                      AT_NO_AUTOMOUNT |
2188                                      AT_SYMLINK_NOFOLLOW |
2189                                      OPEN_TREE_CLOEXEC |
2190                                      OPEN_TREE_CLONE);
2191         if (open_tree_fd1 < 0) {
2192                 log_stderr("failure: sys_open_tree");
2193                 goto out;
2194         }
2195
2196         if (sys_mount_setattr(open_tree_fd1, "", AT_EMPTY_PATH, &attr1, sizeof(attr1))) {
2197                 log_stderr("failure: sys_mount_setattr");
2198                 goto out;
2199         }
2200
2201         /* Validate that all files created through the image mountpoint are
2202          * owned by the callers fsuid and fsgid.
2203          */
2204         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2205                 log_stderr("failure: expected_uid_gid");
2206                 goto out;
2207         }
2208         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2209                 log_stderr("failure: expected_uid_gid");
2210                 goto out;
2211         }
2212         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2213                 log_stderr("failure: expected_uid_gid");
2214                 goto out;
2215         }
2216         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2217                 log_stderr("failure: expected_uid_gid");
2218                 goto out;
2219         }
2220         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
2221                 log_stderr("failure: expected_uid_gid");
2222                 goto out;
2223         }
2224         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2225                 log_stderr("failure: expected_uid_gid");
2226                 goto out;
2227         }
2228         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2229                 log_stderr("failure: expected_uid_gid");
2230                 goto out;
2231         }
2232
2233         /* Validate that all files are owned by the uid and gid specified in
2234          * the idmapping of the mount they are accessed from.
2235          */
2236         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2237                 log_stderr("failure: expected_uid_gid");
2238                 goto out;
2239         }
2240         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2241                 log_stderr("failure: expected_uid_gid");
2242                 goto out;
2243         }
2244         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2245                 log_stderr("failure: expected_uid_gid");
2246                 goto out;
2247         }
2248         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2249                 log_stderr("failure: expected_uid_gid");
2250                 goto out;
2251         }
2252         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 10000, 10000)) {
2253                 log_stderr("failure: expected_uid_gid");
2254                 goto out;
2255         }
2256         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2257                 log_stderr("failure: expected_uid_gid");
2258                 goto out;
2259         }
2260         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2261                 log_stderr("failure: expected_uid_gid");
2262                 goto out;
2263         }
2264
2265         /* Changing mount properties on a detached mount. */
2266         attr2.userns_fd = get_userns_fd(0, 30000, 2001);
2267         if (attr2.userns_fd < 0) {
2268                 log_stderr("failure: get_userns_fd");
2269                 goto out;
2270         }
2271
2272         open_tree_fd2 = sys_open_tree(t_dir1_fd, "",
2273                                      AT_EMPTY_PATH |
2274                                      AT_NO_AUTOMOUNT |
2275                                      AT_SYMLINK_NOFOLLOW |
2276                                      OPEN_TREE_CLOEXEC |
2277                                      OPEN_TREE_CLONE);
2278         if (open_tree_fd2 < 0) {
2279                 log_stderr("failure: sys_open_tree");
2280                 goto out;
2281         }
2282
2283         if (sys_mount_setattr(open_tree_fd2, "", AT_EMPTY_PATH, &attr2, sizeof(attr2))) {
2284                 log_stderr("failure: sys_mount_setattr");
2285                 goto out;
2286         }
2287
2288         /* Validate that all files are owned by the uid and gid specified in
2289          * the idmapping of the mount they are accessed from.
2290          */
2291         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2292                 log_stderr("failure: expected_uid_gid");
2293                 goto out;
2294         }
2295         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2296                 log_stderr("failure: expected_uid_gid");
2297                 goto out;
2298         }
2299         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2300                 log_stderr("failure: expected_uid_gid");
2301                 goto out;
2302         }
2303         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2304                 log_stderr("failure: expected_uid_gid");
2305                 goto out;
2306         }
2307         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 30000, 30000)) {
2308                 log_stderr("failure: expected_uid_gid");
2309                 goto out;
2310         }
2311         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2312                 log_stderr("failure: expected_uid_gid");
2313                 goto out;
2314         }
2315         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2316                 log_stderr("failure: expected_uid_gid");
2317                 goto out;
2318         }
2319
2320         /* Change ownership throught original image mountpoint. */
2321         if (fchownat(t_dir1_fd, FILE1, 2000, 2000, 0)) {
2322                 log_stderr("failure: fchownat");
2323                 goto out;
2324         }
2325         if (fchownat(t_dir1_fd, FILE2, 2000, 2000, 0)) {
2326                 log_stderr("failure: fchownat");
2327                 goto out;
2328         }
2329         if (fchownat(t_dir1_fd, HARDLINK1, 2000, 2000, 0)) {
2330                 log_stderr("failure: fchownat");
2331                 goto out;
2332         }
2333         if (fchownat(t_dir1_fd, CHRDEV1, 2000, 2000, 0)) {
2334                 log_stderr("failure: fchownat");
2335                 goto out;
2336         }
2337         if (fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)) {
2338                 log_stderr("failure: fchownat");
2339                 goto out;
2340         }
2341         if (fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH)) {
2342                 log_stderr("failure: fchownat");
2343                 goto out;
2344         }
2345         if (fchownat(t_dir1_fd, DIR1, 2000, 2000, AT_EMPTY_PATH)) {
2346                 log_stderr("failure: fchownat");
2347                 goto out;
2348         }
2349
2350         /* Check ownership through original mount. */
2351         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 2000, 2000)) {
2352                 log_stderr("failure: expected_uid_gid");
2353                 goto out;
2354         }
2355         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 2000, 2000)) {
2356                 log_stderr("failure: expected_uid_gid");
2357                 goto out;
2358         }
2359         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 2000, 2000)) {
2360                 log_stderr("failure: expected_uid_gid");
2361                 goto out;
2362         }
2363         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 2000, 2000)) {
2364                 log_stderr("failure: expected_uid_gid");
2365                 goto out;
2366         }
2367         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 3000, 3000)) {
2368                 log_stderr("failure: expected_uid_gid");
2369                 goto out;
2370         }
2371         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 2000, 2000)) {
2372                 log_stderr("failure: expected_uid_gid");
2373                 goto out;
2374         }
2375         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 2000, 2000)) {
2376                 log_stderr("failure: expected_uid_gid");
2377                 goto out;
2378         }
2379
2380         /* Check ownership through first idmapped mount. */
2381         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 12000, 12000)) {
2382                 log_stderr("failure:expected_uid_gid ");
2383                 goto out;
2384         }
2385         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 12000, 12000)) {
2386                 log_stderr("failure: expected_uid_gid");
2387                 goto out;
2388         }
2389         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 12000, 12000)) {
2390                 log_stderr("failure: expected_uid_gid");
2391                 goto out;
2392         }
2393         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 12000, 12000)) {
2394                 log_stderr("failure: expected_uid_gid");
2395                 goto out;
2396         }
2397         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 13000, 13000)) {
2398                 log_stderr("failure: expected_uid_gid");
2399                 goto out;
2400         }
2401         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 12000, 12000)) {
2402                 log_stderr("failure:expected_uid_gid ");
2403                 goto out;
2404         }
2405         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 12000, 12000)) {
2406                 log_stderr("failure: expected_uid_gid");
2407                 goto out;
2408         }
2409
2410         /* Check ownership through second idmapped mount. */
2411         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 32000, 32000)) {
2412                 log_stderr("failure: expected_uid_gid");
2413                 goto out;
2414         }
2415         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 32000, 32000)) {
2416                 log_stderr("failure: expected_uid_gid");
2417                 goto out;
2418         }
2419         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 32000, 32000)) {
2420                 log_stderr("failure: expected_uid_gid");
2421                 goto out;
2422         }
2423         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 32000, 32000)) {
2424                 log_stderr("failure: expected_uid_gid");
2425                 goto out;
2426         }
2427         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid)) {
2428                 log_stderr("failure: expected_uid_gid");
2429                 goto out;
2430         }
2431         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 32000, 32000)) {
2432                 log_stderr("failure: expected_uid_gid");
2433                 goto out;
2434         }
2435         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 32000, 32000)) {
2436                 log_stderr("failure: expected_uid_gid");
2437                 goto out;
2438         }
2439
2440         pid = fork();
2441         if (pid < 0) {
2442                 log_stderr("failure: fork");
2443                 goto out;
2444         }
2445         if (pid == 0) {
2446                 if (!switch_userns(attr1.userns_fd, 0, 0, false))
2447                         die("failure: switch_userns");
2448
2449                 if (!fchownat(t_dir1_fd, FILE1, 1000, 1000, 0))
2450                         die("failure: fchownat");
2451                 if (!fchownat(t_dir1_fd, FILE2, 1000, 1000, 0))
2452                         die("failure: fchownat");
2453                 if (!fchownat(t_dir1_fd, HARDLINK1, 1000, 1000, 0))
2454                         die("failure: fchownat");
2455                 if (!fchownat(t_dir1_fd, CHRDEV1, 1000, 1000, 0))
2456                         die("failure: fchownat");
2457                 if (!fchownat(t_dir1_fd, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2458                         die("failure: fchownat");
2459                 if (!fchownat(t_dir1_fd, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2460                         die("failure: fchownat");
2461                 if (!fchownat(t_dir1_fd, DIR1, 1000, 1000, AT_EMPTY_PATH))
2462                         die("failure: fchownat");
2463
2464                 if (!fchownat(open_tree_fd2, FILE1, 1000, 1000, 0))
2465                         die("failure: fchownat");
2466                 if (!fchownat(open_tree_fd2, FILE2, 1000, 1000, 0))
2467                         die("failure: fchownat");
2468                 if (!fchownat(open_tree_fd2, HARDLINK1, 1000, 1000, 0))
2469                         die("failure: fchownat");
2470                 if (!fchownat(open_tree_fd2, CHRDEV1, 1000, 1000, 0))
2471                         die("failure: fchownat");
2472                 if (!fchownat(open_tree_fd2, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2473                         die("failure: fchownat");
2474                 if (!fchownat(open_tree_fd2, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2475                         die("failure: fchownat");
2476                 if (!fchownat(open_tree_fd2, DIR1, 1000, 1000, AT_EMPTY_PATH))
2477                         die("failure: fchownat");
2478
2479                 if (fchownat(open_tree_fd1, FILE1, 1000, 1000, 0))
2480                         die("failure: fchownat");
2481                 if (fchownat(open_tree_fd1, FILE2, 1000, 1000, 0))
2482                         die("failure: fchownat");
2483                 if (fchownat(open_tree_fd1, HARDLINK1, 1000, 1000, 0))
2484                         die("failure: fchownat");
2485                 if (fchownat(open_tree_fd1, CHRDEV1, 1000, 1000, 0))
2486                         die("failure: fchownat");
2487                 if (fchownat(open_tree_fd1, SYMLINK1, 2000, 2000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2488                         die("failure: fchownat");
2489                 if (fchownat(open_tree_fd1, SYMLINK1, 1000, 1000, AT_EMPTY_PATH))
2490                         die("failure: fchownat");
2491                 if (fchownat(open_tree_fd1, DIR1, 1000, 1000, AT_EMPTY_PATH))
2492                         die("failure: fchownat");
2493
2494                 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2495                         die("failure: expected_uid_gid");
2496                 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2497                         die("failure: expected_uid_gid");
2498                 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2499                         die("failure: expected_uid_gid");
2500                 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2501                         die("failure: expected_uid_gid");
2502                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2503                         die("failure: expected_uid_gid");
2504                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2505                         die("failure: expected_uid_gid");
2506                 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2507                         die("failure: expected_uid_gid");
2508
2509                 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, t_overflowuid, t_overflowgid))
2510                         die("failure: expected_uid_gid");
2511                 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, t_overflowuid, t_overflowgid))
2512                         die("failure: expected_uid_gid");
2513                 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2514                         die("failure: expected_uid_gid");
2515                 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2516                         die("failure: expected_uid_gid");
2517                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2518                         die("failure: expected_uid_gid");
2519                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2520                         die("failure: expected_uid_gid");
2521                 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, t_overflowuid, t_overflowgid))
2522                         die("failure: expected_uid_gid");
2523
2524                 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 1000, 1000))
2525                         die("failure: expected_uid_gid");
2526                 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 1000, 1000))
2527                         die("failure: expected_uid_gid");
2528                 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 1000, 1000))
2529                         die("failure: expected_uid_gid");
2530                 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 1000, 1000))
2531                         die("failure: expected_uid_gid");
2532                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2533                         die("failure: expected_uid_gid");
2534                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 1000, 1000))
2535                         die("failure: expected_uid_gid");
2536                 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 1000, 1000))
2537                         die("failure: expected_uid_gid");
2538
2539                 exit(EXIT_SUCCESS);
2540         }
2541
2542         if (wait_for_pid(pid))
2543                 goto out;
2544
2545         /* Check ownership through original mount. */
2546         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 1000, 1000)) {
2547                 log_stderr("failure: expected_uid_gid");
2548                 goto out;
2549         }
2550         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 1000, 1000)) {
2551                 log_stderr("failure: expected_uid_gid");
2552                 goto out;
2553         }
2554         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 1000, 1000)) {
2555                 log_stderr("failure: expected_uid_gid");
2556                 goto out;
2557         }
2558         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 1000, 1000)) {
2559                 log_stderr("failure: expected_uid_gid");
2560                 goto out;
2561         }
2562         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2563                 log_stderr("failure: expected_uid_gid");
2564                 goto out;
2565         }
2566         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 1000, 1000)) {
2567                 log_stderr("failure: expected_uid_gid");
2568                 goto out;
2569         }
2570         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 1000, 1000)) {
2571                 log_stderr("failure: expected_uid_gid");
2572                 goto out;
2573         }
2574
2575         /* Check ownership through first idmapped mount. */
2576         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 11000, 11000)) {
2577                 log_stderr("failure: expected_uid_gid");
2578                 goto out;
2579         }
2580         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 11000, 11000)) {
2581                 log_stderr("failure: expected_uid_gid");
2582                 goto out;
2583         }
2584         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 11000, 11000)) {
2585                 log_stderr("failure: expected_uid_gid");
2586                 goto out;
2587         }
2588         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 11000, 11000)) {
2589                 log_stderr("failure: expected_uid_gid");
2590                 goto out;
2591         }
2592         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2593                 log_stderr("failure: expected_uid_gid");
2594                 goto out;
2595         }
2596         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 11000, 11000)) {
2597                 log_stderr("failure: expected_uid_gid");
2598                 goto out;
2599         }
2600         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 11000, 11000)) {
2601                 log_stderr("failure: expected_uid_gid");
2602                 goto out;
2603         }
2604
2605         /* Check ownership through second idmapped mount. */
2606         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 31000, 31000)) {
2607                 log_stderr("failure: expected_uid_gid");
2608                 goto out;
2609         }
2610         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 31000, 31000)) {
2611                 log_stderr("failure: expected_uid_gid");
2612                 goto out;
2613         }
2614         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 31000, 31000)) {
2615                 log_stderr("failure: expected_uid_gid");
2616                 goto out;
2617         }
2618         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 31000, 31000)) {
2619                 log_stderr("failure: expected_uid_gid");
2620                 goto out;
2621         }
2622         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2623                 log_stderr("failure: expected_uid_gid");
2624                 goto out;
2625         }
2626         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 31000, 31000)) {
2627                 log_stderr("failure: expected_uid_gid");
2628                 goto out;
2629         }
2630         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 31000, 31000)) {
2631                 log_stderr("failure: expected_uid_gid");
2632                 goto out;
2633         }
2634
2635         pid = fork();
2636         if (pid < 0) {
2637                 log_stderr("failure: fork");
2638                 goto out;
2639         }
2640         if (pid == 0) {
2641                 if (!switch_userns(attr2.userns_fd, 0, 0, false))
2642                         die("failure: switch_userns");
2643
2644                 if (!fchownat(t_dir1_fd, FILE1, 0, 0, 0))
2645                         die("failure: fchownat");
2646                 if (!fchownat(t_dir1_fd, FILE2, 0, 0, 0))
2647                         die("failure: fchownat");
2648                 if (!fchownat(t_dir1_fd, HARDLINK1, 0, 0, 0))
2649                         die("failure: fchownat");
2650                 if (!fchownat(t_dir1_fd, CHRDEV1, 0, 0, 0))
2651                         die("failure: fchownat");
2652                 if (!fchownat(t_dir1_fd, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2653                         die("failure: fchownat");
2654                 if (!fchownat(t_dir1_fd, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2655                         die("failure: fchownat");
2656                 if (!fchownat(t_dir1_fd, DIR1, 0, 0, AT_EMPTY_PATH))
2657                         die("failure: fchownat");
2658
2659                 if (!fchownat(open_tree_fd1, FILE1, 0, 0, 0))
2660                         die("failure: fchownat");
2661                 if (!fchownat(open_tree_fd1, FILE2, 0, 0, 0))
2662                         die("failure: fchownat");
2663                 if (!fchownat(open_tree_fd1, HARDLINK1, 0, 0, 0))
2664                         die("failure: fchownat");
2665                 if (!fchownat(open_tree_fd1, CHRDEV1, 0, 0, 0))
2666                         die("failure: fchownat");
2667                 if (!fchownat(open_tree_fd1, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2668                         die("failure: fchownat");
2669                 if (!fchownat(open_tree_fd1, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2670                         die("failure: fchownat");
2671                 if (!fchownat(open_tree_fd1, DIR1, 0, 0, AT_EMPTY_PATH))
2672                         die("failure: fchownat");
2673
2674                 if (fchownat(open_tree_fd2, FILE1, 0, 0, 0))
2675                         die("failure: fchownat");
2676                 if (fchownat(open_tree_fd2, FILE2, 0, 0, 0))
2677                         die("failure: fchownat");
2678                 if (fchownat(open_tree_fd2, HARDLINK1, 0, 0, 0))
2679                         die("failure: fchownat");
2680                 if (fchownat(open_tree_fd2, CHRDEV1, 0, 0, 0))
2681                         die("failure: fchownat");
2682                 if (!fchownat(open_tree_fd2, SYMLINK1, 3000, 3000, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW))
2683                         die("failure: fchownat");
2684                 if (fchownat(open_tree_fd2, SYMLINK1, 0, 0, AT_EMPTY_PATH))
2685                         die("failure: fchownat");
2686                 if (fchownat(open_tree_fd2, DIR1, 0, 0, AT_EMPTY_PATH))
2687                         die("failure: fchownat");
2688
2689                 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, t_overflowuid, t_overflowgid))
2690                         die("failure: expected_uid_gid");
2691                 if (!expected_uid_gid(t_dir1_fd, FILE2, 0, t_overflowuid, t_overflowgid))
2692                         die("failure: expected_uid_gid");
2693                 if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2694                         die("failure: expected_uid_gid");
2695                 if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2696                         die("failure: expected_uid_gid");
2697                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2698                         die("failure: expected_uid_gid");
2699                 if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2700                         die("failure: expected_uid_gid");
2701                 if (!expected_uid_gid(t_dir1_fd, DIR1, 0, t_overflowuid, t_overflowgid))
2702                         die("failure: expected_uid_gid");
2703
2704                 if (!expected_uid_gid(open_tree_fd1, FILE1, 0, t_overflowuid, t_overflowgid))
2705                         die("failure: expected_uid_gid");
2706                 if (!expected_uid_gid(open_tree_fd1, FILE2, 0, t_overflowuid, t_overflowgid))
2707                         die("failure: expected_uid_gid");
2708                 if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, t_overflowuid, t_overflowgid))
2709                         die("failure: expected_uid_gid");
2710                 if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, t_overflowuid, t_overflowgid))
2711                         die("failure: expected_uid_gid");
2712                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, t_overflowuid, t_overflowgid))
2713                         die("failure: expected_uid_gid");
2714                 if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, t_overflowuid, t_overflowgid))
2715                         die("failure: expected_uid_gid");
2716                 if (!expected_uid_gid(open_tree_fd1, DIR1, 0, t_overflowuid, t_overflowgid))
2717                         die("failure: expected_uid_gid");
2718
2719                 if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 0, 0))
2720                         die("failure: expected_uid_gid");
2721                 if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 0, 0))
2722                         die("failure: expected_uid_gid");
2723                 if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 0, 0))
2724                         die("failure: expected_uid_gid");
2725                 if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 0, 0))
2726                         die("failure: expected_uid_gid");
2727                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000))
2728                         die("failure: expected_uid_gid");
2729                 if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 0, 0))
2730                         die("failure: expected_uid_gid");
2731                 if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 0, 0))
2732                         die("failure: expected_uid_gid");
2733
2734                 exit(EXIT_SUCCESS);
2735         }
2736
2737         if (wait_for_pid(pid))
2738                 goto out;
2739
2740         /* Check ownership through original mount. */
2741         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
2742                 log_stderr("failure: expected_uid_gid");
2743                 goto out;
2744         }
2745         if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0)) {
2746                 log_stderr("failure: expected_uid_gid");
2747                 goto out;
2748         }
2749         if (!expected_uid_gid(t_dir1_fd, HARDLINK1, 0, 0, 0)) {
2750                 log_stderr("failure: expected_uid_gid");
2751                 goto out;
2752         }
2753         if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0)) {
2754                 log_stderr("failure: expected_uid_gid");
2755                 goto out;
2756         }
2757         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
2758                 log_stderr("failure: expected_uid_gid");
2759                 goto out;
2760         }
2761         if (!expected_uid_gid(t_dir1_fd, SYMLINK1, 0, 0, 0)) {
2762                 log_stderr("failure: expected_uid_gid");
2763                 goto out;
2764         }
2765         if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0)) {
2766                 log_stderr("failure: expected_uid_gid");
2767                 goto out;
2768         }
2769
2770         /* Check ownership through first idmapped mount. */
2771         if (!expected_uid_gid(open_tree_fd1, FILE1, 0, 10000, 10000)) {
2772                 log_stderr("failure: expected_uid_gid");
2773                 goto out;
2774         }
2775         if (!expected_uid_gid(open_tree_fd1, FILE2, 0, 10000, 10000)) {
2776                 log_stderr("failure: expected_uid_gid");
2777                 goto out;
2778         }
2779         if (!expected_uid_gid(open_tree_fd1, HARDLINK1, 0, 10000, 10000)) {
2780                 log_stderr("failure: expected_uid_gid");
2781                 goto out;
2782         }
2783         if (!expected_uid_gid(open_tree_fd1, CHRDEV1, 0, 10000, 10000)) {
2784                 log_stderr("failure: expected_uid_gid");
2785                 goto out;
2786         }
2787         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
2788                 log_stderr("failure: expected_uid_gid");
2789                 goto out;
2790         }
2791         if (!expected_uid_gid(open_tree_fd1, SYMLINK1, 0, 10000, 10000)) {
2792                 log_stderr("failure: expected_uid_gid");
2793                 goto out;
2794         }
2795         if (!expected_uid_gid(open_tree_fd1, DIR1, 0, 10000, 10000)) {
2796                 log_stderr("failure: expected_uid_gid");
2797                 goto out;
2798         }
2799
2800         /* Check ownership through second idmapped mount. */
2801         if (!expected_uid_gid(open_tree_fd2, FILE1, 0, 30000, 30000)) {
2802                 log_stderr("failure: expected_uid_gid");
2803                 goto out;
2804         }
2805         if (!expected_uid_gid(open_tree_fd2, FILE2, 0, 30000, 30000)) {
2806                 log_stderr("failure: expected_uid_gid");
2807                 goto out;
2808         }
2809         if (!expected_uid_gid(open_tree_fd2, HARDLINK1, 0, 30000, 30000)) {
2810                 log_stderr("failure: expected_uid_gid");
2811                 goto out;
2812         }
2813         if (!expected_uid_gid(open_tree_fd2, CHRDEV1, 0, 30000, 30000)) {
2814                 log_stderr("failure: expected_uid_gid");
2815                 goto out;
2816         }
2817         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, AT_SYMLINK_NOFOLLOW, 32000, 32000)) {
2818                 log_stderr("failure: expected_uid_gid");
2819                 goto out;
2820         }
2821         if (!expected_uid_gid(open_tree_fd2, SYMLINK1, 0, 30000, 30000)) {
2822                 log_stderr("failure: expected_uid_gid");
2823                 goto out;
2824         }
2825         if (!expected_uid_gid(open_tree_fd2, DIR1, 0, 30000, 30000)) {
2826                 log_stderr("failure: expected_uid_gid");
2827                 goto out;
2828         }
2829
2830         fret = 0;
2831         log_debug("Ran test");
2832 out:
2833         safe_close(attr1.userns_fd);
2834         safe_close(attr2.userns_fd);
2835         safe_close(file1_fd);
2836         safe_close(open_tree_fd1);
2837         safe_close(open_tree_fd2);
2838
2839         return fret;
2840 }
2841
2842 static int fscaps(void)
2843 {
2844         int fret = -1;
2845         int file1_fd = -EBADF;
2846         struct mount_attr attr = {
2847                 .attr_set = MOUNT_ATTR_IDMAP,
2848         };
2849         pid_t pid;
2850
2851         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2852         if (file1_fd < 0) {
2853                 log_stderr("failure: openat");
2854                 goto out;
2855         }
2856
2857         /* Skip if vfs caps are unsupported. */
2858         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2859                 return 0;
2860
2861         /* Changing mount properties on a detached mount. */
2862         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2863         if (attr.userns_fd < 0) {
2864                 log_stderr("failure: get_userns_fd");
2865                 goto out;
2866         }
2867
2868         if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
2869                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2870                 goto out;
2871         }
2872
2873         pid = fork();
2874         if (pid < 0) {
2875                 log_stderr("failure: fork");
2876                 goto out;
2877         }
2878         if (pid == 0) {
2879                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2880                         die("failure: switch_userns");
2881
2882                 /*
2883                  * On kernels before 5.12 this would succeed and return the
2884                  * unconverted caps. Then - for whatever reason - this behavior
2885                  * got changed and since 5.12 EOVERFLOW is returned when the
2886                  * rootid stored alongside the vfs caps does not map to uid 0 in
2887                  * the caller's user namespace.
2888                  */
2889                 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
2890                         die("failure: expected_dummy_vfs_caps_uid");
2891
2892                 exit(EXIT_SUCCESS);
2893         }
2894
2895         if (wait_for_pid(pid))
2896                 goto out;
2897
2898         if (fremovexattr(file1_fd, "security.capability")) {
2899                 log_stderr("failure: fremovexattr");
2900                 goto out;
2901         }
2902         if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2903                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2904                 goto out;
2905         }
2906         if (errno != ENODATA) {
2907                 log_stderr("failure: errno");
2908                 goto out;
2909         }
2910
2911         if (set_dummy_vfs_caps(file1_fd, 0, 10000)) {
2912                 log_stderr("failure: set_dummy_vfs_caps");
2913                 goto out;
2914         }
2915
2916         if (!expected_dummy_vfs_caps_uid(file1_fd, 10000)) {
2917                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2918                 goto out;
2919         }
2920
2921         pid = fork();
2922         if (pid < 0) {
2923                 log_stderr("failure: fork");
2924                 goto out;
2925         }
2926         if (pid == 0) {
2927                 if (!switch_userns(attr.userns_fd, 0, 0, false))
2928                         die("failure: switch_userns");
2929
2930                 if (!expected_dummy_vfs_caps_uid(file1_fd, 0))
2931                         die("failure: expected_dummy_vfs_caps_uid");
2932
2933                 exit(EXIT_SUCCESS);
2934         }
2935
2936         if (wait_for_pid(pid))
2937                 goto out;
2938
2939         if (fremovexattr(file1_fd, "security.capability")) {
2940                 log_stderr("failure: fremovexattr");
2941                 goto out;
2942         }
2943         if (expected_dummy_vfs_caps_uid(file1_fd, -1)) {
2944                 log_stderr("failure: expected_dummy_vfs_caps_uid");
2945                 goto out;
2946         }
2947         if (errno != ENODATA) {
2948                 log_stderr("failure: errno");
2949                 goto out;
2950         }
2951
2952         fret = 0;
2953         log_debug("Ran test");
2954 out:
2955         safe_close(attr.userns_fd);
2956         safe_close(file1_fd);
2957
2958         return fret;
2959 }
2960
2961 static int fscaps_idmapped_mounts(void)
2962 {
2963         int fret = -1;
2964         int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
2965         struct mount_attr attr = {
2966                 .attr_set = MOUNT_ATTR_IDMAP,
2967         };
2968         pid_t pid;
2969
2970         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
2971         if (file1_fd < 0) {
2972                 log_stderr("failure: openat");
2973                 goto out;
2974         }
2975
2976         /* Skip if vfs caps are unsupported. */
2977         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
2978                 return 0;
2979
2980         if (fremovexattr(file1_fd, "security.capability")) {
2981                 log_stderr("failure: fremovexattr");
2982                 goto out;
2983         }
2984
2985         /* Changing mount properties on a detached mount. */
2986         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
2987         if (attr.userns_fd < 0) {
2988                 log_stderr("failure: get_userns_fd");
2989                 goto out;
2990         }
2991
2992         open_tree_fd = sys_open_tree(t_dir1_fd, "",
2993                                      AT_EMPTY_PATH |
2994                                      AT_NO_AUTOMOUNT |
2995                                      AT_SYMLINK_NOFOLLOW |
2996                                      OPEN_TREE_CLOEXEC |
2997                                      OPEN_TREE_CLONE);
2998         if (open_tree_fd < 0) {
2999                 log_stderr("failure: sys_open_tree");
3000                 goto out;
3001         }
3002
3003         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3004                 log_stderr("failure: sys_mount_setattr");
3005                 goto out;
3006         }
3007
3008         file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3009         if (file1_fd2 < 0) {
3010                 log_stderr("failure: openat");
3011                 goto out;
3012         }
3013
3014         if (!set_dummy_vfs_caps(file1_fd2, 0, 1000)) {
3015                 log_stderr("failure: set_dummy_vfs_caps");
3016                 goto out;
3017         }
3018
3019         if (set_dummy_vfs_caps(file1_fd2, 0, 10000)) {
3020                 log_stderr("failure: set_dummy_vfs_caps");
3021                 goto out;
3022         }
3023
3024         if (!expected_dummy_vfs_caps_uid(file1_fd2, 10000)) {
3025                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3026                 goto out;
3027         }
3028
3029         if (!expected_dummy_vfs_caps_uid(file1_fd, 0)) {
3030                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3031                 goto out;
3032         }
3033
3034         pid = fork();
3035         if (pid < 0) {
3036                 log_stderr("failure: fork");
3037                 goto out;
3038         }
3039         if (pid == 0) {
3040                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3041                         die("failure: switch_userns");
3042
3043                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 0))
3044                         die("failure: expected_dummy_vfs_caps_uid");
3045
3046                 exit(EXIT_SUCCESS);
3047         }
3048
3049         if (wait_for_pid(pid))
3050                 goto out;
3051
3052         if (fremovexattr(file1_fd2, "security.capability")) {
3053                 log_stderr("failure: fremovexattr");
3054                 goto out;
3055         }
3056         if (expected_dummy_vfs_caps_uid(file1_fd2, -1)) {
3057                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3058                 goto out;
3059         }
3060         if (errno != ENODATA) {
3061                 log_stderr("failure: errno");
3062                 goto out;
3063         }
3064
3065         if (set_dummy_vfs_caps(file1_fd2, 0, 12000)) {
3066                 log_stderr("failure: set_dummy_vfs_caps");
3067                 goto out;
3068         }
3069
3070         if (!expected_dummy_vfs_caps_uid(file1_fd2, 12000)) {
3071                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3072                 goto out;
3073         }
3074
3075         if (!expected_dummy_vfs_caps_uid(file1_fd, 2000)) {
3076                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3077                 goto out;
3078         }
3079
3080         pid = fork();
3081         if (pid < 0) {
3082                 log_stderr("failure: fork");
3083                 goto out;
3084         }
3085         if (pid == 0) {
3086                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3087                         die("failure: switch_userns");
3088
3089                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 2000))
3090                         die("failure: expected_dummy_vfs_caps_uid");
3091
3092                 exit(EXIT_SUCCESS);
3093         }
3094
3095         if (wait_for_pid(pid))
3096                 goto out;
3097
3098         fret = 0;
3099         log_debug("Ran test");
3100 out:
3101         safe_close(attr.userns_fd);
3102         safe_close(file1_fd);
3103         safe_close(file1_fd2);
3104         safe_close(open_tree_fd);
3105
3106         return fret;
3107 }
3108
3109 static int fscaps_idmapped_mounts_in_userns(void)
3110 {
3111         int fret = -1;
3112         int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
3113         struct mount_attr attr = {
3114                 .attr_set = MOUNT_ATTR_IDMAP,
3115         };
3116         pid_t pid;
3117
3118         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
3119         if (file1_fd < 0) {
3120                 log_stderr("failure: openat");
3121                 goto out;
3122         }
3123
3124         /* Skip if vfs caps are unsupported. */
3125         if (set_dummy_vfs_caps(file1_fd, 0, 1000))
3126                 return 0;
3127
3128         if (fremovexattr(file1_fd, "security.capability")) {
3129                 log_stderr("failure: fremovexattr");
3130                 goto out;
3131         }
3132
3133         /* Changing mount properties on a detached mount. */
3134         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
3135         if (attr.userns_fd < 0) {
3136                 log_stderr("failure: get_userns_fd");
3137                 goto out;
3138         }
3139
3140         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3141                                      AT_EMPTY_PATH |
3142                                      AT_NO_AUTOMOUNT |
3143                                      AT_SYMLINK_NOFOLLOW |
3144                                      OPEN_TREE_CLOEXEC |
3145                                      OPEN_TREE_CLONE);
3146         if (open_tree_fd < 0) {
3147                 log_stderr("failure: sys_open_tree");
3148                 goto out;
3149         }
3150
3151         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3152                 log_stderr("failure: sys_mount_setattr");
3153                 goto out;
3154         }
3155
3156         file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3157         if (file1_fd2 < 0) {
3158                 log_stderr("failure: openat");
3159                 goto out;
3160         }
3161
3162         pid = fork();
3163         if (pid < 0) {
3164                 log_stderr("failure: fork");
3165                 goto out;
3166         }
3167         if (pid == 0) {
3168                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3169                         die("failure: switch_userns");
3170
3171                 if (expected_dummy_vfs_caps_uid(file1_fd2, -1))
3172                         die("failure: expected_dummy_vfs_caps_uid");
3173                 if (errno != ENODATA)
3174                         die("failure: errno");
3175
3176                 if (set_dummy_vfs_caps(file1_fd2, 0, 1000))
3177                         die("failure: set_dummy_vfs_caps");
3178
3179                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 1000))
3180                         die("failure: expected_dummy_vfs_caps_uid");
3181
3182                 if (!expected_dummy_vfs_caps_uid(file1_fd, 1000) && errno != EOVERFLOW)
3183                         die("failure: expected_dummy_vfs_caps_uid");
3184
3185                 exit(EXIT_SUCCESS);
3186         }
3187
3188         if (wait_for_pid(pid))
3189                 goto out;
3190
3191         if (!expected_dummy_vfs_caps_uid(file1_fd, 1000)) {
3192                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3193                 goto out;
3194         }
3195
3196         fret = 0;
3197         log_debug("Ran test");
3198 out:
3199         safe_close(attr.userns_fd);
3200         safe_close(file1_fd);
3201         safe_close(file1_fd2);
3202         safe_close(open_tree_fd);
3203
3204         return fret;
3205 }
3206
3207 static int fscaps_idmapped_mounts_in_userns_separate_userns(void)
3208 {
3209         int fret = -1;
3210         int file1_fd = -EBADF, file1_fd2 = -EBADF, open_tree_fd = -EBADF;
3211         struct mount_attr attr = {
3212                 .attr_set = MOUNT_ATTR_IDMAP,
3213         };
3214         pid_t pid;
3215
3216         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, 0644);
3217         if (file1_fd < 0) {
3218                 log_stderr("failure: openat");
3219                 goto out;
3220         }
3221
3222         /* Skip if vfs caps are unsupported. */
3223         if (set_dummy_vfs_caps(file1_fd, 0, 1000)) {
3224                 log_stderr("failure: set_dummy_vfs_caps");
3225                 goto out;
3226         }
3227
3228         if (fremovexattr(file1_fd, "security.capability")) {
3229                 log_stderr("failure: fremovexattr");
3230                 goto out;
3231         }
3232
3233         /* change ownership of all files to uid 0 */
3234         if (chown_r(t_mnt_fd, T_DIR1, 20000, 20000)) {
3235                 log_stderr("failure: chown_r");
3236                 goto out;
3237         }
3238
3239         /* Changing mount properties on a detached mount. */
3240         attr.userns_fd  = get_userns_fd(20000, 10000, 10000);
3241         if (attr.userns_fd < 0) {
3242                 log_stderr("failure: get_userns_fd");
3243                 goto out;
3244         }
3245
3246         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3247                                      AT_EMPTY_PATH |
3248                                      AT_NO_AUTOMOUNT |
3249                                      AT_SYMLINK_NOFOLLOW |
3250                                      OPEN_TREE_CLOEXEC |
3251                                      OPEN_TREE_CLONE);
3252         if (open_tree_fd < 0) {
3253                 log_stderr("failure: sys_open_tree");
3254                 goto out;
3255         }
3256
3257         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3258                 log_stderr("failure: sys_mount_setattr");
3259                 goto out;
3260         }
3261
3262         file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, 0);
3263         if (file1_fd2 < 0) {
3264                 log_stderr("failure: openat");
3265                 goto out;
3266         }
3267
3268         pid = fork();
3269         if (pid < 0) {
3270                 log_stderr("failure: fork");
3271                 goto out;
3272         }
3273         if (pid == 0) {
3274                 int userns_fd;
3275
3276                 userns_fd = get_userns_fd(0, 10000, 10000);
3277                 if (userns_fd < 0)
3278                         die("failure: get_userns_fd");
3279
3280                 if (!switch_userns(userns_fd, 0, 0, false))
3281                         die("failure: switch_userns");
3282
3283                 if (set_dummy_vfs_caps(file1_fd2, 0, 0))
3284                         die("failure: set fscaps");
3285
3286                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 0))
3287                         die("failure: expected_dummy_vfs_caps_uid");
3288
3289                 if (!expected_dummy_vfs_caps_uid(file1_fd, 20000) && errno != EOVERFLOW)
3290                         die("failure: expected_dummy_vfs_caps_uid");
3291
3292                 exit(EXIT_SUCCESS);
3293         }
3294
3295         if (wait_for_pid(pid))
3296                 goto out;
3297
3298         if (!expected_dummy_vfs_caps_uid(file1_fd, 20000)) {
3299                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3300                 goto out;
3301         }
3302
3303         pid = fork();
3304         if (pid < 0) {
3305                 log_stderr("failure: fork");
3306                 goto out;
3307         }
3308         if (pid == 0) {
3309                 int userns_fd;
3310
3311                 userns_fd = get_userns_fd(0, 10000, 10000);
3312                 if (userns_fd < 0)
3313                         die("failure: get_userns_fd");
3314
3315                 if (!switch_userns(userns_fd, 0, 0, false))
3316                         die("failure: switch_userns");
3317
3318                 if (fremovexattr(file1_fd2, "security.capability"))
3319                         die("failure: fremovexattr");
3320                 if (expected_dummy_vfs_caps_uid(file1_fd2, -1))
3321                         die("failure: expected_dummy_vfs_caps_uid");
3322                 if (errno != ENODATA)
3323                         die("failure: errno");
3324
3325                 if (set_dummy_vfs_caps(file1_fd2, 0, 1000))
3326                         die("failure: set_dummy_vfs_caps");
3327
3328                 if (!expected_dummy_vfs_caps_uid(file1_fd2, 1000))
3329                         die("failure: expected_dummy_vfs_caps_uid");
3330
3331                 if (!expected_dummy_vfs_caps_uid(file1_fd, 21000) && errno != EOVERFLOW)
3332                         die("failure: expected_dummy_vfs_caps_uid");
3333
3334                 exit(EXIT_SUCCESS);
3335         }
3336
3337         if (wait_for_pid(pid))
3338                 goto out;
3339
3340         if (!expected_dummy_vfs_caps_uid(file1_fd, 21000)) {
3341                 log_stderr("failure: expected_dummy_vfs_caps_uid");
3342                 goto out;
3343         }
3344
3345         fret = 0;
3346         log_debug("Ran test");
3347 out:
3348         safe_close(attr.userns_fd);
3349         safe_close(file1_fd);
3350         safe_close(file1_fd2);
3351         safe_close(open_tree_fd);
3352
3353         return fret;
3354 }
3355
3356 /* Validate that when the IDMAP_MOUNT_TEST_RUN_SETID environment variable is set
3357  * to 1 that we are executed with setid privileges and if set to 0 we are not.
3358  * If the env variable isn't set the tests are not run.
3359  */
3360 static void __attribute__((constructor)) setuid_rexec(void)
3361 {
3362         const char *expected_euid_str, *expected_egid_str, *rexec;
3363
3364         rexec = getenv("IDMAP_MOUNT_TEST_RUN_SETID");
3365         /* This is a regular test-suite run. */
3366         if (!rexec)
3367                 return;
3368
3369         expected_euid_str = getenv("EXPECTED_EUID");
3370         expected_egid_str = getenv("EXPECTED_EGID");
3371
3372         if (expected_euid_str && expected_egid_str) {
3373                 uid_t expected_euid;
3374                 gid_t expected_egid;
3375
3376                 expected_euid = atoi(expected_euid_str);
3377                 expected_egid = atoi(expected_egid_str);
3378
3379                 if (strcmp(rexec, "1") == 0) {
3380                         /* we're expecting to run setid */
3381                         if ((getuid() != geteuid()) && (expected_euid == geteuid()) &&
3382                             (getgid() != getegid()) && (expected_egid == getegid()))
3383                                 exit(EXIT_SUCCESS);
3384                 } else if (strcmp(rexec, "0") == 0) {
3385                         /* we're expecting to not run setid */
3386                         if ((getuid() == geteuid()) && (expected_euid == geteuid()) &&
3387                             (getgid() == getegid()) && (expected_egid == getegid()))
3388                                 exit(EXIT_SUCCESS);
3389                         else
3390                                 die("failure: non-setid");
3391                 }
3392         }
3393
3394         exit(EXIT_FAILURE);
3395 }
3396
3397 /* Validate that setid transitions are handled correctly. */
3398 static int setid_binaries(void)
3399 {
3400         int fret = -1;
3401         int file1_fd = -EBADF, exec_fd = -EBADF;
3402         pid_t pid;
3403
3404         /* create a file to be used as setuid binary */
3405         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3406         if (file1_fd < 0) {
3407                 log_stderr("failure: openat");
3408                 goto out;
3409         }
3410
3411         /* open our own executable */
3412         exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3413         if (exec_fd < 0) {
3414                 log_stderr("failure: openat");
3415                 goto out;
3416         }
3417
3418         /* copy our own executable into the file we created */
3419         if (fd_to_fd(exec_fd, file1_fd)) {
3420                 log_stderr("failure: fd_to_fd");
3421                 goto out;
3422         }
3423
3424         /* chown the file to the uid and gid we want to assume */
3425         if (fchown(file1_fd, 5000, 5000)) {
3426                 log_stderr("failure: fchown");
3427                 goto out;
3428         }
3429
3430         /* set the setid bits and grant execute permissions to the group */
3431         if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3432                 log_stderr("failure: fchmod");
3433                 goto out;
3434         }
3435
3436         /* Verify that the sid bits got raised. */
3437         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3438                 log_stderr("failure: is_setid");
3439                 goto out;
3440         }
3441
3442         safe_close(exec_fd);
3443         safe_close(file1_fd);
3444
3445         /* Verify we run setid binary as uid and gid 5000 from the original
3446          * mount.
3447          */
3448         pid = fork();
3449         if (pid < 0) {
3450                 log_stderr("failure: fork");
3451                 goto out;
3452         }
3453         if (pid == 0) {
3454                 static char *envp[] = {
3455                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
3456                         "EXPECTED_EUID=5000",
3457                         "EXPECTED_EGID=5000",
3458                         NULL,
3459                 };
3460                 static char *argv[] = {
3461                         NULL,
3462                 };
3463
3464                 if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 5000, 5000))
3465                         die("failure: expected_uid_gid");
3466
3467                 sys_execveat(t_dir1_fd, FILE1, argv, envp, 0);
3468                 die("failure: sys_execveat");
3469
3470                 exit(EXIT_FAILURE);
3471         }
3472         if (wait_for_pid(pid))
3473                 goto out;
3474
3475         fret = 0;
3476         log_debug("Ran test");
3477 out:
3478
3479         return fret;
3480 }
3481
3482 /* Validate that setid transitions are handled correctly on idmapped mounts. */
3483 static int setid_binaries_idmapped_mounts(void)
3484 {
3485         int fret = -1;
3486         int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3487         struct mount_attr attr = {
3488                 .attr_set = MOUNT_ATTR_IDMAP,
3489         };
3490         pid_t pid;
3491
3492         if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3493                 log_stderr("failure: mkdirat");
3494                 goto out;
3495         }
3496
3497         /* create a file to be used as setuid binary */
3498         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3499         if (file1_fd < 0) {
3500                 log_stderr("failure: openat");
3501                 goto out;
3502         }
3503
3504         /* open our own executable */
3505         exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3506         if (exec_fd < 0) {
3507                 log_stderr("failure:openat ");
3508                 goto out;
3509         }
3510
3511         /* copy our own executable into the file we created */
3512         if (fd_to_fd(exec_fd, file1_fd)) {
3513                 log_stderr("failure: fd_to_fd");
3514                 goto out;
3515         }
3516
3517         /* chown the file to the uid and gid we want to assume */
3518         if (fchown(file1_fd, 5000, 5000)) {
3519                 log_stderr("failure: fchown");
3520                 goto out;
3521         }
3522
3523         /* set the setid bits and grant execute permissions to the group */
3524         if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3525                 log_stderr("failure: fchmod");
3526                 goto out;
3527         }
3528
3529         /* Verify that the sid bits got raised. */
3530         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3531                 log_stderr("failure: is_setid");
3532                 goto out;
3533         }
3534
3535         safe_close(exec_fd);
3536         safe_close(file1_fd);
3537
3538         /* Changing mount properties on a detached mount. */
3539         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
3540         if (attr.userns_fd < 0) {
3541                 log_stderr("failure: get_userns_fd");
3542                 goto out;
3543         }
3544
3545         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3546                                      AT_EMPTY_PATH |
3547                                      AT_NO_AUTOMOUNT |
3548                                      AT_SYMLINK_NOFOLLOW |
3549                                      OPEN_TREE_CLOEXEC |
3550                                      OPEN_TREE_CLONE);
3551         if (open_tree_fd < 0) {
3552                 log_stderr("failure: sys_open_tree");
3553                 goto out;
3554         }
3555
3556         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3557                 log_stderr("failure: sys_mount_setattr");
3558                 goto out;
3559         }
3560
3561         /* A detached mount will have an anonymous mount namespace attached to
3562          * it. This means that we can't execute setid binaries on a detached
3563          * mount because the mnt_may_suid() helper will fail the check_mount()
3564          * part of its check which compares the caller's mount namespace to the
3565          * detached mount's mount namespace. Since by definition an anonymous
3566          * mount namespace is not equale to any mount namespace currently in
3567          * use this can't work. So attach the mount to the filesystem first
3568          * before performing this check.
3569          */
3570         if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3571                 log_stderr("failure: sys_move_mount");
3572                 goto out;
3573         }
3574
3575         /* Verify we run setid binary as uid and gid 10000 from idmapped mount mount. */
3576         pid = fork();
3577         if (pid < 0) {
3578                 log_stderr("failure: fork");
3579                 goto out;
3580         }
3581         if (pid == 0) {
3582                 static char *envp[] = {
3583                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
3584                         "EXPECTED_EUID=15000",
3585                         "EXPECTED_EGID=15000",
3586                         NULL,
3587                 };
3588                 static char *argv[] = {
3589                         NULL,
3590                 };
3591
3592                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 15000, 15000))
3593                         die("failure: expected_uid_gid");
3594
3595                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3596                 die("failure: sys_execveat");
3597
3598                 exit(EXIT_FAILURE);
3599         }
3600
3601         if (wait_for_pid(pid))
3602                 goto out;
3603
3604         fret = 0;
3605         log_debug("Ran test");
3606 out:
3607         safe_close(exec_fd);
3608         safe_close(file1_fd);
3609         safe_close(open_tree_fd);
3610
3611         snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
3612         sys_umount2(t_buf, MNT_DETACH);
3613         rm_r(t_mnt_fd, DIR1);
3614
3615         return fret;
3616 }
3617
3618 /* Validate that setid transitions are handled correctly on idmapped mounts
3619  * running in a user namespace where the uid and gid of the setid binary have no
3620  * mapping.
3621  */
3622 static int setid_binaries_idmapped_mounts_in_userns(void)
3623 {
3624         int fret = -1;
3625         int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3626         struct mount_attr attr = {
3627                 .attr_set = MOUNT_ATTR_IDMAP,
3628         };
3629         pid_t pid;
3630
3631         if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3632                 log_stderr("failure: ");
3633                 goto out;
3634         }
3635
3636         /* create a file to be used as setuid binary */
3637         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3638         if (file1_fd < 0) {
3639                 log_stderr("failure: openat");
3640                 goto out;
3641         }
3642
3643         /* open our own executable */
3644         exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3645         if (exec_fd < 0) {
3646                 log_stderr("failure: openat");
3647                 goto out;
3648         }
3649
3650         /* copy our own executable into the file we created */
3651         if (fd_to_fd(exec_fd, file1_fd)) {
3652                 log_stderr("failure: fd_to_fd");
3653                 goto out;
3654         }
3655
3656         safe_close(exec_fd);
3657
3658         /* chown the file to the uid and gid we want to assume */
3659         if (fchown(file1_fd, 5000, 5000)) {
3660                 log_stderr("failure: fchown");
3661                 goto out;
3662         }
3663
3664         /* set the setid bits and grant execute permissions to the group */
3665         if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3666                 log_stderr("failure: fchmod");
3667                 goto out;
3668         }
3669
3670         /* Verify that the sid bits got raised. */
3671         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3672                 log_stderr("failure: is_setid");
3673                 goto out;
3674         }
3675
3676         safe_close(file1_fd);
3677
3678         /* Changing mount properties on a detached mount. */
3679         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
3680         if (attr.userns_fd < 0) {
3681                 log_stderr("failure: get_userns_fd");
3682                 goto out;
3683         }
3684
3685         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3686                                      AT_EMPTY_PATH |
3687                                      AT_NO_AUTOMOUNT |
3688                                      AT_SYMLINK_NOFOLLOW |
3689                                      OPEN_TREE_CLOEXEC |
3690                                      OPEN_TREE_CLONE);
3691         if (open_tree_fd < 0) {
3692                 log_stderr("failure: sys_open_tree");
3693                 goto out;
3694         }
3695
3696         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3697                 log_stderr("failure: sys_mount_setattr");
3698                 goto out;
3699         }
3700
3701         /* A detached mount will have an anonymous mount namespace attached to
3702          * it. This means that we can't execute setid binaries on a detached
3703          * mount because the mnt_may_suid() helper will fail the check_mount()
3704          * part of its check which compares the caller's mount namespace to the
3705          * detached mount's mount namespace. Since by definition an anonymous
3706          * mount namespace is not equale to any mount namespace currently in
3707          * use this can't work. So attach the mount to the filesystem first
3708          * before performing this check.
3709          */
3710         if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3711                 log_stderr("failure: sys_move_mount");
3712                 goto out;
3713         }
3714
3715         pid = fork();
3716         if (pid < 0) {
3717                 log_stderr("failure: fork");
3718                 goto out;
3719         }
3720         if (pid == 0) {
3721                 static char *envp[] = {
3722                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
3723                         "EXPECTED_EUID=5000",
3724                         "EXPECTED_EGID=5000",
3725                         NULL,
3726                 };
3727                 static char *argv[] = {
3728                         NULL,
3729                 };
3730
3731                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3732                         die("failure: switch_userns");
3733
3734                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 5000, 5000))
3735                         die("failure: expected_uid_gid");
3736
3737                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3738                 die("failure: sys_execveat");
3739
3740                 exit(EXIT_FAILURE);
3741         }
3742
3743         if (wait_for_pid(pid)) {
3744                 log_stderr("failure: wait_for_pid");
3745                 goto out;
3746         }
3747
3748         file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
3749         if (file1_fd < 0) {
3750                 log_stderr("failure: openat");
3751                 goto out;
3752         }
3753
3754         /* chown the file to the uid and gid we want to assume */
3755         if (fchown(file1_fd, 0, 0)) {
3756                 log_stderr("failure: fchown");
3757                 goto out;
3758         }
3759
3760         /* set the setid bits and grant execute permissions to the group */
3761         if (fchmod(file1_fd, S_IXOTH | S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3762                 log_stderr("failure: fchmod");
3763                 goto out;
3764         }
3765
3766         /* Verify that the sid bits got raised. */
3767         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3768                 log_stderr("failure: is_setid");
3769                 goto out;
3770         }
3771
3772         safe_close(file1_fd);
3773
3774         pid = fork();
3775         if (pid < 0) {
3776                 log_stderr("failure: fork");
3777                 goto out;
3778         }
3779         if (pid == 0) {
3780                 static char *envp[] = {
3781                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
3782                         "EXPECTED_EUID=0",
3783                         "EXPECTED_EGID=0",
3784                         NULL,
3785                 };
3786                 static char *argv[] = {
3787                         NULL,
3788                 };
3789
3790                 if (!caps_supported()) {
3791                         log_debug("skip: capability library not installed");
3792                         exit(EXIT_SUCCESS);
3793                 }
3794
3795                 if (!switch_userns(attr.userns_fd, 5000, 5000, true))
3796                         die("failure: switch_userns");
3797
3798                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
3799                         die("failure: expected_uid_gid");
3800
3801                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3802                 die("failure: sys_execveat");
3803
3804                 exit(EXIT_FAILURE);
3805         }
3806
3807         if (wait_for_pid(pid)) {
3808                 log_stderr("failure: wait_for_pid");
3809                 goto out;
3810         }
3811
3812         file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
3813         if (file1_fd < 0) {
3814                 log_stderr("failure: openat");
3815                 goto out;
3816         }
3817
3818         /* chown the file to the uid and gid we want to assume */
3819         if (fchown(file1_fd, 30000, 30000)) {
3820                 log_stderr("failure: fchown");
3821                 goto out;
3822         }
3823
3824         if (fchmod(file1_fd, S_IXOTH | S_IEXEC | S_ISUID | S_ISGID), 0) {
3825                 log_stderr("failure: fchmod");
3826                 goto out;
3827         }
3828
3829         /* Verify that the sid bits got raised. */
3830         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3831                 log_stderr("failure: is_setid");
3832                 goto out;
3833         }
3834
3835         safe_close(file1_fd);
3836
3837         /* Verify that we can't assume a uid and gid of a setid binary for which
3838          * we have no mapping in our user namespace.
3839          */
3840         pid = fork();
3841         if (pid < 0) {
3842                 log_stderr("failure: fork");
3843                 goto out;
3844         }
3845         if (pid == 0) {
3846                 char expected_euid[100];
3847                 char expected_egid[100];
3848                 static char *envp[4] = {
3849                         NULL,
3850                         NULL,
3851                         NULL,
3852                         NULL,
3853                 };
3854                 static char *argv[] = {
3855                         NULL,
3856                 };
3857
3858                 if (!switch_userns(attr.userns_fd, 0, 0, false))
3859                         die("failure: switch_userns");
3860
3861                 envp[0] = "IDMAP_MOUNT_TEST_RUN_SETID=0";
3862                 snprintf(expected_euid, sizeof(expected_euid), "EXPECTED_EUID=%d", geteuid());
3863                 envp[1] = expected_euid;
3864                 snprintf(expected_egid, sizeof(expected_egid), "EXPECTED_EGID=%d", getegid());
3865                 envp[2] = expected_egid;
3866
3867                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid))
3868                         die("failure: expected_uid_gid");
3869
3870                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
3871                 die("failure: sys_execveat");
3872
3873                 exit(EXIT_FAILURE);
3874         }
3875
3876         if (wait_for_pid(pid)) {
3877                 log_stderr("failure: wait_for_pid");
3878                 goto out;
3879         }
3880
3881         fret = 0;
3882         log_debug("Ran test");
3883 out:
3884         safe_close(attr.userns_fd);
3885         safe_close(exec_fd);
3886         safe_close(file1_fd);
3887         safe_close(open_tree_fd);
3888
3889         snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
3890         sys_umount2(t_buf, MNT_DETACH);
3891         rm_r(t_mnt_fd, DIR1);
3892
3893         return fret;
3894 }
3895
3896 /* Validate that setid transitions are handled correctly on idmapped mounts
3897  * running in a user namespace where the uid and gid of the setid binary have no
3898  * mapping.
3899  */
3900 static int setid_binaries_idmapped_mounts_in_userns_separate_userns(void)
3901 {
3902         int fret = -1;
3903         int file1_fd = -EBADF, exec_fd = -EBADF, open_tree_fd = -EBADF;
3904         struct mount_attr attr = {
3905                 .attr_set = MOUNT_ATTR_IDMAP,
3906         };
3907         pid_t pid;
3908
3909         if (mkdirat(t_mnt_fd, DIR1, 0777)) {
3910                 log_stderr("failure: mkdirat");
3911                 goto out;
3912         }
3913
3914         /* create a file to be used as setuid binary */
3915         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC | O_RDWR, 0644);
3916         if (file1_fd < 0) {
3917                 log_stderr("failure: openat");
3918                 goto out;
3919         }
3920
3921         /* open our own executable */
3922         exec_fd = openat(-EBADF, "/proc/self/exe", O_RDONLY | O_CLOEXEC, 0000);
3923         if (exec_fd < 0) {
3924                 log_stderr("failure: openat");
3925                 goto out;
3926         }
3927
3928         /* copy our own executable into the file we created */
3929         if (fd_to_fd(exec_fd, file1_fd)) {
3930                 log_stderr("failure: fd_to_fd");
3931                 goto out;
3932         }
3933
3934         safe_close(exec_fd);
3935
3936         /* change ownership of all files to uid 0 */
3937         if (chown_r(t_mnt_fd, T_DIR1, 20000, 20000)) {
3938                 log_stderr("failure: chown_r");
3939                 goto out;
3940         }
3941
3942         /* chown the file to the uid and gid we want to assume */
3943         if (fchown(file1_fd, 25000, 25000)) {
3944                 log_stderr("failure: fchown");
3945                 goto out;
3946         }
3947
3948         /* set the setid bits and grant execute permissions to the group */
3949         if (fchmod(file1_fd, S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
3950                 log_stderr("failure: fchmod");
3951                 goto out;
3952         }
3953
3954         /* Verify that the sid bits got raised. */
3955         if (!is_setid(t_dir1_fd, FILE1, 0)) {
3956                 log_stderr("failure: is_setid");
3957                 goto out;
3958         }
3959
3960         safe_close(file1_fd);
3961
3962         /* Changing mount properties on a detached mount. */
3963         attr.userns_fd  = get_userns_fd(20000, 10000, 10000);
3964         if (attr.userns_fd < 0) {
3965                 log_stderr("failure: get_userns_fd");
3966                 goto out;
3967         }
3968
3969         open_tree_fd = sys_open_tree(t_dir1_fd, "",
3970                                      AT_EMPTY_PATH |
3971                                      AT_NO_AUTOMOUNT |
3972                                      AT_SYMLINK_NOFOLLOW |
3973                                      OPEN_TREE_CLOEXEC |
3974                                      OPEN_TREE_CLONE);
3975         if (open_tree_fd < 0) {
3976                 log_stderr("failure: sys_open_tree");
3977                 goto out;
3978         }
3979
3980         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
3981                 log_stderr("failure: sys_mount_setattr");
3982                 goto out;
3983         }
3984
3985         /* A detached mount will have an anonymous mount namespace attached to
3986          * it. This means that we can't execute setid binaries on a detached
3987          * mount because the mnt_may_suid() helper will fail the check_mount()
3988          * part of its check which compares the caller's mount namespace to the
3989          * detached mount's mount namespace. Since by definition an anonymous
3990          * mount namespace is not equale to any mount namespace currently in
3991          * use this can't work. So attach the mount to the filesystem first
3992          * before performing this check.
3993          */
3994         if (sys_move_mount(open_tree_fd, "", t_mnt_fd, DIR1, MOVE_MOUNT_F_EMPTY_PATH)) {
3995                 log_stderr("failure: sys_move_mount");
3996                 goto out;
3997         }
3998
3999         pid = fork();
4000         if (pid < 0) {
4001                 log_stderr("failure: fork");
4002                 goto out;
4003         }
4004         if (pid == 0) {
4005                 int userns_fd;
4006                 static char *envp[] = {
4007                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
4008                         "EXPECTED_EUID=5000",
4009                         "EXPECTED_EGID=5000",
4010                         NULL,
4011                 };
4012                 static char *argv[] = {
4013                         NULL,
4014                 };
4015
4016                 userns_fd = get_userns_fd(0, 10000, 10000);
4017                 if (userns_fd < 0)
4018                         die("failure: get_userns_fd");
4019
4020                 if (!switch_userns(userns_fd, 0, 0, false))
4021                         die("failure: switch_userns");
4022
4023                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 5000, 5000))
4024                         die("failure: expected_uid_gid");
4025
4026                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4027                 die("failure: sys_execveat");
4028
4029                 exit(EXIT_FAILURE);
4030         }
4031
4032         if (wait_for_pid(pid)) {
4033                 log_stderr("failure: wait_for_pid");
4034                 goto out;
4035         }
4036
4037         file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
4038         if (file1_fd < 0) {
4039                 log_stderr("failure: openat");
4040                 goto out;
4041         }
4042
4043         /* chown the file to the uid and gid we want to assume */
4044         if (fchown(file1_fd, 20000, 20000)) {
4045                 log_stderr("failure: fchown");
4046                 goto out;
4047         }
4048
4049         /* set the setid bits and grant execute permissions to the group */
4050         if (fchmod(file1_fd, S_IXOTH | S_IXGRP | S_IEXEC | S_ISUID | S_ISGID), 0) {
4051                 log_stderr("failure: fchmod");
4052                 goto out;
4053         }
4054
4055         /* Verify that the sid bits got raised. */
4056         if (!is_setid(t_dir1_fd, FILE1, 0)) {
4057                 log_stderr("failure: is_setid");
4058                 goto out;
4059         }
4060
4061         safe_close(file1_fd);
4062
4063         pid = fork();
4064         if (pid < 0) {
4065                 log_stderr("failure: fork");
4066                 goto out;
4067         }
4068         if (pid == 0) {
4069                 int userns_fd;
4070                 static char *envp[] = {
4071                         "IDMAP_MOUNT_TEST_RUN_SETID=1",
4072                         "EXPECTED_EUID=0",
4073                         "EXPECTED_EGID=0",
4074                         NULL,
4075                 };
4076                 static char *argv[] = {
4077                         NULL,
4078                 };
4079
4080                 userns_fd = get_userns_fd(0, 10000, 10000);
4081                 if (userns_fd < 0)
4082                         die("failure: get_userns_fd");
4083
4084                 if (!caps_supported()) {
4085                         log_debug("skip: capability library not installed");
4086                         exit(EXIT_SUCCESS);
4087                 }
4088
4089                 if (!switch_userns(userns_fd, 1000, 1000, true))
4090                         die("failure: switch_userns");
4091
4092                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
4093                         die("failure: expected_uid_gid");
4094
4095                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4096                 die("failure: sys_execveat");
4097
4098                 exit(EXIT_FAILURE);
4099         }
4100         if (wait_for_pid(pid)) {
4101                 log_stderr("failure: wait_for_pid");
4102                 goto out;
4103         }
4104
4105         file1_fd = openat(t_dir1_fd, FILE1, O_RDWR | O_CLOEXEC, 0644);
4106         if (file1_fd < 0) {
4107                 log_stderr("failure: openat");
4108                 goto out;
4109         }
4110
4111         /* chown the file to the uid and gid we want to assume */
4112         if (fchown(file1_fd, 0, 0)) {
4113                 log_stderr("failure: fchown");
4114                 goto out;
4115         }
4116
4117         if (fchmod(file1_fd, S_IXOTH | S_IEXEC | S_ISUID | S_ISGID), 0) {
4118                 log_stderr("failure: fchmod");
4119                 goto out;
4120         }
4121
4122         /* Verify that the sid bits got raised. */
4123         if (!is_setid(t_dir1_fd, FILE1, 0)) {
4124                 log_stderr("failure: is_setid");
4125                 goto out;
4126         }
4127
4128         safe_close(file1_fd);
4129
4130         /* Verify that we can't assume a uid and gid of a setid binary for
4131          * which we have no mapping in our user namespace.
4132          */
4133         pid = fork();
4134         if (pid < 0) {
4135                 log_stderr("failure: fork");
4136                 goto out;
4137         }
4138         if (pid == 0) {
4139                 int userns_fd;
4140                 char expected_euid[100];
4141                 char expected_egid[100];
4142                 static char *envp[4] = {
4143                         NULL,
4144                         NULL,
4145                         NULL,
4146                         NULL,
4147                 };
4148                 static char *argv[] = {
4149                         NULL,
4150                 };
4151
4152                 userns_fd = get_userns_fd(0, 10000, 10000);
4153                 if (userns_fd < 0)
4154                         die("failure: get_userns_fd");
4155
4156                 if (!switch_userns(userns_fd, 0, 0, false))
4157                         die("failure: switch_userns");
4158
4159                 envp[0] = "IDMAP_MOUNT_TEST_RUN_SETID=0";
4160                 snprintf(expected_euid, sizeof(expected_euid), "EXPECTED_EUID=%d", geteuid());
4161                 envp[1] = expected_euid;
4162                 snprintf(expected_egid, sizeof(expected_egid), "EXPECTED_EGID=%d", getegid());
4163                 envp[2] = expected_egid;
4164
4165                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid))
4166                         die("failure: expected_uid_gid");
4167
4168                 sys_execveat(open_tree_fd, FILE1, argv, envp, 0);
4169                 die("failure: sys_execveat");
4170
4171                 exit(EXIT_FAILURE);
4172         }
4173         if (wait_for_pid(pid)) {
4174                 log_stderr("failure: wait_for_pid");
4175                 goto out;
4176         }
4177
4178         fret = 0;
4179         log_debug("Ran test");
4180 out:
4181         safe_close(attr.userns_fd);
4182         safe_close(exec_fd);
4183         safe_close(file1_fd);
4184         safe_close(open_tree_fd);
4185
4186         snprintf(t_buf, sizeof(t_buf), "%s/" DIR1, t_mountpoint);
4187         sys_umount2(t_buf, MNT_DETACH);
4188         rm_r(t_mnt_fd, DIR1);
4189
4190         return fret;
4191 }
4192
4193 static int sticky_bit_unlink(void)
4194 {
4195         int fret = -1;
4196         int dir_fd = -EBADF;
4197         pid_t pid;
4198
4199         if (!caps_supported())
4200                 return 0;
4201
4202         /* create directory */
4203         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4204                 log_stderr("failure: mkdirat");
4205                 goto out;
4206         }
4207
4208         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4209         if (dir_fd < 0) {
4210                 log_stderr("failure: openat");
4211                 goto out;
4212         }
4213
4214         if (fchown(dir_fd, 0, 0)) {
4215                 log_stderr("failure: fchown");
4216                 goto out;
4217         }
4218
4219         if (fchmod(dir_fd, 0777)) {
4220                 log_stderr("failure: fchmod");
4221                 goto out;
4222         }
4223
4224         /* create regular file via mknod */
4225         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4226                 log_stderr("failure: mknodat");
4227                 goto out;
4228         }
4229         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4230                 log_stderr("failure: fchownat");
4231                 goto out;
4232         }
4233         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4234                 log_stderr("failure: fchmodat");
4235                 goto out;
4236         }
4237
4238         /* create regular file via mknod */
4239         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4240                 log_stderr("failure: mknodat");
4241                 goto out;
4242         }
4243         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4244                 log_stderr("failure: fchownat");
4245                 goto out;
4246         }
4247         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4248                 log_stderr("failure: fchmodat");
4249                 goto out;
4250         }
4251
4252         /* The sticky bit is not set so we must be able to delete files not
4253          * owned by us.
4254          */
4255         pid = fork();
4256         if (pid < 0) {
4257                 log_stderr("failure: fork");
4258                 goto out;
4259         }
4260         if (pid == 0) {
4261                 if (!switch_ids(1000, 1000))
4262                         die("failure: switch_ids");
4263
4264                 if (unlinkat(dir_fd, FILE1, 0))
4265                         die("failure: unlinkat");
4266
4267                 if (unlinkat(dir_fd, FILE2, 0))
4268                         die("failure: unlinkat");
4269
4270                 exit(EXIT_SUCCESS);
4271         }
4272         if (wait_for_pid(pid)) {
4273                 log_stderr("failure: wait_for_pid");
4274                 goto out;
4275         }
4276
4277         /* set sticky bit */
4278         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4279                 log_stderr("failure: fchmod");
4280                 goto out;
4281         }
4282
4283         /* validate sticky bit is set */
4284         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4285                 log_stderr("failure: is_sticky");
4286                 goto out;
4287         }
4288
4289         /* create regular file via mknod */
4290         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4291                 log_stderr("failure: mknodat");
4292                 goto out;
4293         }
4294         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4295                 log_stderr("failure: fchownat");
4296                 goto out;
4297         }
4298         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4299                 log_stderr("failure: fchmodat");
4300                 goto out;
4301         }
4302
4303         /* create regular file via mknod */
4304         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4305                 log_stderr("failure: mknodat");
4306                 goto out;
4307         }
4308         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4309                 log_stderr("failure: fchownat");
4310                 goto out;
4311         }
4312         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4313                 log_stderr("failure: fchmodat");
4314                 goto out;
4315         }
4316
4317         /* The sticky bit is set so we must not be able to delete files not
4318          * owned by us.
4319          */
4320         pid = fork();
4321         if (pid < 0) {
4322                 log_stderr("failure: fork");
4323                 goto out;
4324         }
4325         if (pid == 0) {
4326                 if (!switch_ids(1000, 1000))
4327                         die("failure: switch_ids");
4328
4329                 if (!unlinkat(dir_fd, FILE1, 0))
4330                         die("failure: unlinkat");
4331                 if (errno != EPERM)
4332                         die("failure: errno");
4333
4334                 if (!unlinkat(dir_fd, FILE2, 0))
4335                         die("failure: unlinkat");
4336                 if (errno != EPERM)
4337                         die("failure: errno");
4338
4339                 exit(EXIT_SUCCESS);
4340         }
4341         if (wait_for_pid(pid)) {
4342                 log_stderr("failure: wait_for_pid");
4343                 goto out;
4344         }
4345
4346         /* The sticky bit is set and we own the files so we must be able to
4347          * delete the files now.
4348          */
4349         pid = fork();
4350         if (pid < 0) {
4351                 log_stderr("failure: fork");
4352                 goto out;
4353         }
4354         if (pid == 0) {
4355                 /* change ownership */
4356                 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
4357                         die("failure: fchownat");
4358                 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
4359                         die("failure: expected_uid_gid");
4360                 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
4361                         die("failure: fchownat");
4362                 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
4363                         die("failure: expected_uid_gid");
4364
4365                 if (!switch_ids(1000, 1000))
4366                         die("failure: switch_ids");
4367
4368                 if (unlinkat(dir_fd, FILE1, 0))
4369                         die("failure: unlinkat");
4370
4371                 if (unlinkat(dir_fd, FILE2, 0))
4372                         die("failure: unlinkat");
4373
4374                 exit(EXIT_SUCCESS);
4375         }
4376         if (wait_for_pid(pid)) {
4377                 log_stderr("failure: wait_for_pid");
4378                 goto out;
4379         }
4380
4381         /* change uid to unprivileged user */
4382         if (fchown(dir_fd, 1000, -1)) {
4383                 log_stderr("failure: fchown");
4384                 goto out;
4385         }
4386         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4387                 log_stderr("failure: fchmod");
4388                 goto out;
4389         }
4390         /* validate sticky bit is set */
4391         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4392                 log_stderr("failure: is_sticky");
4393                 goto out;
4394         }
4395
4396         /* create regular file via mknod */
4397         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4398                 log_stderr("failure: mknodat");
4399                 goto out;
4400         }
4401         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4402                 log_stderr("failure: fchownat");
4403                 goto out;
4404         }
4405         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4406                 log_stderr("failure: fchmodat");
4407                 goto out;
4408         }
4409
4410         /* create regular file via mknod */
4411         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4412                 log_stderr("failure: mknodat");
4413                 goto out;
4414         }
4415         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4416                 log_stderr("failure: fchownat");
4417                 goto out;
4418         }
4419         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4420                 log_stderr("failure: fchmodat");
4421                 goto out;
4422         }
4423
4424         /* The sticky bit is set and we own the directory so we must be able to
4425          * delete the files now.
4426          */
4427         pid = fork();
4428         if (pid < 0) {
4429                 log_stderr("failure: fork");
4430                 goto out;
4431         }
4432         if (pid == 0) {
4433                 if (!switch_ids(1000, 1000))
4434                         die("failure: switch_ids");
4435
4436                 if (unlinkat(dir_fd, FILE1, 0))
4437                         die("failure: unlinkat");
4438
4439                 if (unlinkat(dir_fd, FILE2, 0))
4440                         die("failure: unlinkat");
4441
4442                 exit(EXIT_SUCCESS);
4443         }
4444         if (wait_for_pid(pid)) {
4445                 log_stderr("failure: wait_for_pid");
4446                 goto out;
4447         }
4448
4449         fret = 0;
4450         log_debug("Ran test");
4451 out:
4452         safe_close(dir_fd);
4453
4454         return fret;
4455 }
4456
4457 static int sticky_bit_unlink_idmapped_mounts(void)
4458 {
4459         int fret = -1;
4460         int dir_fd = -EBADF, open_tree_fd = -EBADF;
4461         struct mount_attr attr = {
4462                 .attr_set = MOUNT_ATTR_IDMAP,
4463         };
4464         pid_t pid;
4465
4466         if (!caps_supported())
4467                 return 0;
4468
4469         /* create directory */
4470         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4471                 log_stderr("failure: mkdirat");
4472                 goto out;
4473         }
4474
4475         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4476         if (dir_fd < 0) {
4477                 log_stderr("failure: openat");
4478                 goto out;
4479         }
4480         if (fchown(dir_fd, 10000, 10000)) {
4481                 log_stderr("failure: fchown");
4482                 goto out;
4483         }
4484         if (fchmod(dir_fd, 0777)) {
4485                 log_stderr("failure: fchmod");
4486                 goto out;
4487         }
4488
4489         /* create regular file via mknod */
4490         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4491                 log_stderr("failure: mknodat");
4492                 goto out;
4493         }
4494         if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4495                 log_stderr("failure: fchownat");
4496                 goto out;
4497         }
4498         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4499                 log_stderr("failure: fchmodat");
4500                 goto out;
4501         }
4502
4503         /* create regular file via mknod */
4504         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4505                 log_stderr("failure: mknodat");
4506                 goto out;
4507         }
4508         if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4509                 log_stderr("failure: fchownat");
4510                 goto out;
4511         }
4512         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4513                 log_stderr("failure: fchmodat");
4514                 goto out;
4515         }
4516
4517         /* Changing mount properties on a detached mount. */
4518         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
4519         if (attr.userns_fd < 0) {
4520                 log_stderr("failure: get_userns_fd");
4521                 goto out;
4522         }
4523
4524         open_tree_fd = sys_open_tree(dir_fd, "",
4525                                      AT_EMPTY_PATH |
4526                                      AT_NO_AUTOMOUNT |
4527                                      AT_SYMLINK_NOFOLLOW |
4528                                      OPEN_TREE_CLOEXEC |
4529                                      OPEN_TREE_CLONE);
4530         if (open_tree_fd < 0) {
4531                 log_stderr("failure: sys_open_tree");
4532                 goto out;
4533         }
4534
4535         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
4536                 log_stderr("failure: sys_mount_setattr");
4537                 goto out;
4538         }
4539
4540         /* The sticky bit is not set so we must be able to delete files not
4541          * owned by us.
4542          */
4543         pid = fork();
4544         if (pid < 0) {
4545                 log_stderr("failure: fork");
4546                 goto out;
4547         }
4548         if (pid == 0) {
4549                 if (!switch_ids(1000, 1000))
4550                         die("failure: switch_ids");
4551
4552                 if (unlinkat(open_tree_fd, FILE1, 0))
4553                         die("failure: unlinkat");
4554
4555                 if (unlinkat(open_tree_fd, FILE2, 0))
4556                         die("failure: unlinkat");
4557
4558                 exit(EXIT_SUCCESS);
4559         }
4560         if (wait_for_pid(pid)) {
4561                 log_stderr("failure: wait_for_pid");
4562                 goto out;
4563         }
4564
4565         /* set sticky bit */
4566         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4567                 log_stderr("failure: fchmod");
4568                 goto out;
4569         }
4570
4571         /* validate sticky bit is set */
4572         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4573                 log_stderr("failure: is_sticky");
4574                 goto out;
4575         }
4576
4577         /* create regular file via mknod */
4578         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4579                 log_stderr("failure: mknodat");
4580                 goto out;
4581         }
4582         if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4583                 log_stderr("failure: fchownat");
4584                 goto out;
4585         }
4586         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4587                 log_stderr("failure: fchmodat");
4588                 goto out;
4589         }
4590
4591         /* create regular file via mknod */
4592         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4593                 log_stderr("failure: mknodat");
4594                 goto out;
4595         }
4596         if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4597                 log_stderr("failure: fchownat");
4598                 goto out;
4599         }
4600         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4601                 log_stderr("failure: fchmodat");
4602                 goto out;
4603         }
4604
4605         /* The sticky bit is set so we must not be able to delete files not
4606          * owned by us.
4607          */
4608         pid = fork();
4609         if (pid < 0) {
4610                 log_stderr("failure: fork");
4611                 goto out;
4612         }
4613         if (pid == 0) {
4614                 if (!switch_ids(1000, 1000))
4615                         die("failure: switch_ids");
4616
4617                 if (!unlinkat(open_tree_fd, FILE1, 0))
4618                         die("failure: unlinkat");
4619                 if (errno != EPERM)
4620                         die("failure: errno");
4621
4622                 if (!unlinkat(open_tree_fd, FILE2, 0))
4623                         die("failure: unlinkat");
4624                 if (errno != EPERM)
4625                         die("failure: errno");
4626
4627                 exit(EXIT_SUCCESS);
4628         }
4629         if (wait_for_pid(pid)) {
4630                 log_stderr("failure: wait_for_pid");
4631                 goto out;
4632         }
4633
4634         /* The sticky bit is set and we own the files so we must be able to
4635          * delete the files now.
4636          */
4637         pid = fork();
4638         if (pid < 0) {
4639                 log_stderr("failure: fork");
4640                 goto out;
4641         }
4642         if (pid == 0) {
4643                 /* change ownership */
4644                 if (fchownat(dir_fd, FILE1, 11000, -1, 0))
4645                         die("failure: fchownat");
4646                 if (!expected_uid_gid(dir_fd, FILE1, 0, 11000, 10000))
4647                         die("failure: expected_uid_gid");
4648                 if (fchownat(dir_fd, FILE2, 11000, -1, 0))
4649                         die("failure: fchownat");
4650                 if (!expected_uid_gid(dir_fd, FILE2, 0, 11000, 12000))
4651                         die("failure: expected_uid_gid");
4652
4653                 if (!switch_ids(1000, 1000))
4654                         die("failure: switch_ids");
4655
4656                 if (unlinkat(open_tree_fd, FILE1, 0))
4657                         die("failure: unlinkat");
4658
4659                 if (unlinkat(open_tree_fd, FILE2, 0))
4660                         die("failure: unlinkat");
4661
4662                 exit(EXIT_SUCCESS);
4663         }
4664         if (wait_for_pid(pid)) {
4665                 log_stderr("failure: wait_for_pid");
4666                 goto out;
4667         }
4668
4669         /* change uid to unprivileged user */
4670         if (fchown(dir_fd, 11000, -1)) {
4671                 log_stderr("failure: fchown");
4672                 goto out;
4673         }
4674         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4675                 log_stderr("failure: fchmod");
4676                 goto out;
4677         }
4678         /* validate sticky bit is set */
4679         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4680                 log_stderr("failure: is_sticky");
4681                 goto out;
4682         }
4683
4684         /* create regular file via mknod */
4685         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4686                 log_stderr("failure: mknodat");
4687                 goto out;
4688         }
4689         if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
4690                 log_stderr("failure: fchownat");
4691                 goto out;
4692         }
4693         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4694                 log_stderr("failure: fchmodat");
4695                 goto out;
4696         }
4697
4698         /* create regular file via mknod */
4699         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4700                 log_stderr("failure: mknodat");
4701                 goto out;
4702         }
4703         if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
4704                 log_stderr("failure: fchownat");
4705                 goto out;
4706         }
4707         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4708                 log_stderr("failure: fchmodat");
4709                 goto out;
4710         }
4711
4712         /* The sticky bit is set and we own the directory so we must be able to
4713          * delete the files now.
4714          */
4715         pid = fork();
4716         if (pid < 0) {
4717                 log_stderr("failure: fork");
4718                 goto out;
4719         }
4720         if (pid == 0) {
4721                 if (!switch_ids(1000, 1000))
4722                         die("failure: switch_ids");
4723
4724                 if (unlinkat(open_tree_fd, FILE1, 0))
4725                         die("failure: unlinkat");
4726
4727                 if (unlinkat(open_tree_fd, FILE2, 0))
4728                         die("failure: unlinkat");
4729
4730                 exit(EXIT_SUCCESS);
4731         }
4732         if (wait_for_pid(pid)) {
4733                 log_stderr("failure: wait_for_pid");
4734                 goto out;
4735         }
4736
4737         fret = 0;
4738         log_debug("Ran test");
4739 out:
4740         safe_close(attr.userns_fd);
4741         safe_close(dir_fd);
4742         safe_close(open_tree_fd);
4743
4744         return fret;
4745 }
4746
4747 /* Validate that the sticky bit behaves correctly on idmapped mounts for unlink
4748  * operations in a user namespace.
4749  */
4750 static int sticky_bit_unlink_idmapped_mounts_in_userns(void)
4751 {
4752         int fret = -1;
4753         int dir_fd = -EBADF, open_tree_fd = -EBADF;
4754         struct mount_attr attr = {
4755                 .attr_set = MOUNT_ATTR_IDMAP,
4756         };
4757         pid_t pid;
4758
4759         if (!caps_supported())
4760                 return 0;
4761
4762         /* create directory */
4763         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
4764                 log_stderr("failure: mkdirat");
4765                 goto out;
4766         }
4767
4768         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
4769         if (dir_fd < 0) {
4770                 log_stderr("failure: openat");
4771                 goto out;
4772         }
4773         if (fchown(dir_fd, 0, 0)) {
4774                 log_stderr("failure: fchown");
4775                 goto out;
4776         }
4777         if (fchmod(dir_fd, 0777)) {
4778                 log_stderr("failure: fchmod");
4779                 goto out;
4780         }
4781
4782         /* create regular file via mknod */
4783         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4784                 log_stderr("failure: mknodat");
4785                 goto out;
4786         }
4787         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4788                 log_stderr("failure: fchownat");
4789                 goto out;
4790         }
4791         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4792                 log_stderr("failure: fchmodat");
4793                 goto out;
4794         }
4795
4796         /* create regular file via mknod */
4797         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4798                 log_stderr("failure: mknodat");
4799                 goto out;
4800         }
4801         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4802                 log_stderr("failure: fchownat");
4803                 goto out;
4804         }
4805         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4806                 log_stderr("failure: fchmodat");
4807                 goto out;
4808         }
4809
4810         /* Changing mount properties on a detached mount. */
4811         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
4812         if (attr.userns_fd < 0) {
4813                 log_stderr("failure: get_userns_fd");
4814                 goto out;
4815         }
4816
4817         open_tree_fd = sys_open_tree(dir_fd, "",
4818                                      AT_EMPTY_PATH |
4819                                      AT_NO_AUTOMOUNT |
4820                                      AT_SYMLINK_NOFOLLOW |
4821                                      OPEN_TREE_CLOEXEC |
4822                                      OPEN_TREE_CLONE);
4823         if (open_tree_fd < 0) {
4824                 log_stderr("failure: sys_open_tree");
4825                 goto out;
4826         }
4827
4828         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
4829                 log_stderr("failure: sys_mount_setattr");
4830                 goto out;
4831         }
4832
4833         /* The sticky bit is not set so we must be able to delete files not
4834          * owned by us.
4835          */
4836         pid = fork();
4837         if (pid < 0) {
4838                 log_stderr("failure: fork");
4839                 goto out;
4840         }
4841         if (pid == 0) {
4842                 if (!caps_supported()) {
4843                         log_debug("skip: capability library not installed");
4844                         exit(EXIT_SUCCESS);
4845                 }
4846
4847                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4848                         die("failure: switch_userns");
4849
4850                 if (unlinkat(dir_fd, FILE1, 0))
4851                         die("failure: unlinkat");
4852
4853                 if (unlinkat(dir_fd, FILE2, 0))
4854                         die("failure: unlinkat");
4855
4856                 exit(EXIT_SUCCESS);
4857         }
4858         if (wait_for_pid(pid)) {
4859                 log_stderr("failure: wait_for_pid");
4860                 goto out;
4861         }
4862
4863         /* set sticky bit */
4864         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
4865                 log_stderr("failure: fchmod");
4866                 goto out;
4867         }
4868
4869         /* validate sticky bit is set */
4870         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
4871                 log_stderr("failure: is_sticky");
4872                 goto out;
4873         }
4874
4875         /* create regular file via mknod */
4876         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
4877                 log_stderr("failure: mknodat");
4878                 goto out;
4879         }
4880         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
4881                 log_stderr("failure: fchownat");
4882                 goto out;
4883         }
4884         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
4885                 log_stderr("failure: fchmodat");
4886                 goto out;
4887         }
4888
4889         /* create regular file via mknod */
4890         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
4891                 log_stderr("failure: mknodat");
4892                 goto out;
4893         }
4894         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
4895                 log_stderr("failure: fchownat");
4896                 goto out;
4897         }
4898         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
4899                 log_stderr("failure: fchmodat");
4900                 goto out;
4901         }
4902
4903         /* The sticky bit is set so we must not be able to delete files not
4904          * owned by us.
4905          */
4906         pid = fork();
4907         if (pid < 0) {
4908                 log_stderr("failure: fork");
4909                 goto out;
4910         }
4911         if (pid == 0) {
4912                 if (!caps_supported()) {
4913                         log_debug("skip: capability library not installed");
4914                         exit(EXIT_SUCCESS);
4915                 }
4916
4917                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4918                         die("failure: switch_userns");
4919
4920                 if (!unlinkat(dir_fd, FILE1, 0))
4921                         die("failure: unlinkat");
4922                 if (errno != EPERM)
4923                         die("failure: errno");
4924
4925                 if (!unlinkat(dir_fd, FILE2, 0))
4926                         die("failure: unlinkat");
4927                 if (errno != EPERM)
4928                         die("failure: errno");
4929
4930                 if (!unlinkat(open_tree_fd, FILE1, 0))
4931                         die("failure: unlinkat");
4932                 if (errno != EPERM)
4933                         die("failure: errno");
4934
4935                 if (!unlinkat(open_tree_fd, FILE2, 0))
4936                         die("failure: unlinkat");
4937                 if (errno != EPERM)
4938                         die("failure: errno");
4939
4940                 exit(EXIT_SUCCESS);
4941         }
4942         if (wait_for_pid(pid)) {
4943                 log_stderr("failure: wait_for_pid");
4944                 goto out;
4945         }
4946
4947         /* The sticky bit is set and we own the files so we must be able to
4948          * delete the files now.
4949          */
4950         pid = fork();
4951         if (pid < 0) {
4952                 log_stderr("failure: fork");
4953                 goto out;
4954         }
4955         if (pid == 0) {
4956                 /* change ownership */
4957                 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
4958                         die("failure: fchownat");
4959                 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
4960                         die("failure: expected_uid_gid");
4961                 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
4962                         die("failure: fchownat");
4963                 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
4964                         die("failure: expected_uid_gid");
4965
4966                 if (!caps_supported()) {
4967                         log_debug("skip: capability library not installed");
4968                         exit(EXIT_SUCCESS);
4969                 }
4970
4971                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
4972                         die("failure: switch_userns");
4973
4974                 if (!unlinkat(dir_fd, FILE1, 0))
4975                         die("failure: unlinkat");
4976                 if (errno != EPERM)
4977                         die("failure: errno");
4978
4979                 if (!unlinkat(dir_fd, FILE2, 0))
4980                         die("failure: unlinkat");
4981                 if (errno != EPERM)
4982                         die("failure: errno");
4983
4984                 if (unlinkat(open_tree_fd, FILE1, 0))
4985                         die("failure: unlinkat");
4986
4987                 if (unlinkat(open_tree_fd, FILE2, 0))
4988                         die("failure: unlinkat");
4989
4990                 exit(EXIT_SUCCESS);
4991         }
4992         if (wait_for_pid(pid)) {
4993                 log_stderr("failure: wait_for_pid");
4994                 goto out;
4995         }
4996
4997         /* change uid to unprivileged user */
4998         if (fchown(dir_fd, 1000, -1)) {
4999                 log_stderr("failure: fchown");
5000                 goto out;
5001         }
5002         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5003                 log_stderr("failure: fchmod");
5004                 goto out;
5005         }
5006         /* validate sticky bit is set */
5007         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5008                 log_stderr("failure: is_sticky");
5009                 goto out;
5010         }
5011
5012         /* create regular file via mknod */
5013         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5014                 log_stderr("failure: mknodat");
5015                 goto out;
5016         }
5017         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5018                 log_stderr("failure: fchownat");
5019                 goto out;
5020         }
5021         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5022                 log_stderr("failure: fchmodat");
5023                 goto out;
5024         }
5025
5026         /* create regular file via mknod */
5027         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5028                 log_stderr("failure: mknodat");
5029                 goto out;
5030         }
5031         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5032                 log_stderr("failure: fchownat");
5033                 goto out;
5034         }
5035         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5036                 log_stderr("failure: fchmodat");
5037                 goto out;
5038         }
5039
5040         /* The sticky bit is set and we own the directory so we must be able to
5041          * delete the files now.
5042          */
5043         pid = fork();
5044         if (pid < 0) {
5045                 log_stderr("failure: fork");
5046                 goto out;
5047         }
5048         if (pid == 0) {
5049                 if (!caps_supported()) {
5050                         log_debug("skip: capability library not installed");
5051                         exit(EXIT_SUCCESS);
5052                 }
5053
5054                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5055                         die("failure: switch_userns");
5056
5057                 /* we don't own the directory from the original mount */
5058                 if (!unlinkat(dir_fd, FILE1, 0))
5059                         die("failure: unlinkat");
5060                 if (errno != EPERM)
5061                         die("failure: errno");
5062
5063                 if (!unlinkat(dir_fd, FILE2, 0))
5064                         die("failure: unlinkat");
5065                 if (errno != EPERM)
5066                         die("failure: errno");
5067
5068                 /* we own the file from the idmapped mount */
5069                 if (unlinkat(open_tree_fd, FILE1, 0))
5070                         die("failure: unlinkat");
5071                 if (unlinkat(open_tree_fd, FILE2, 0))
5072                         die("failure: unlinkat");
5073
5074                 exit(EXIT_SUCCESS);
5075         }
5076         if (wait_for_pid(pid)) {
5077                 log_stderr("failure: wait_for_pid");
5078                 goto out;
5079         }
5080
5081         fret = 0;
5082         log_debug("Ran test");
5083 out:
5084         safe_close(attr.userns_fd);
5085         safe_close(dir_fd);
5086         safe_close(open_tree_fd);
5087
5088         return fret;
5089 }
5090
5091 static int sticky_bit_rename(void)
5092 {
5093         int fret = -1;
5094         int dir_fd = -EBADF;
5095         pid_t pid;
5096
5097         if (!caps_supported())
5098                 return 0;
5099
5100         /* create directory */
5101         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5102                 log_stderr("failure: mkdirat");
5103                 goto out;
5104         }
5105
5106         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5107         if (dir_fd < 0) {
5108                 log_stderr("failure: openat");
5109                 goto out;
5110         }
5111         if (fchown(dir_fd, 0, 0)) {
5112                 log_stderr("failure: fchown");
5113                 goto out;
5114         }
5115         if (fchmod(dir_fd, 0777)) {
5116                 log_stderr("failure: fchmod");
5117                 goto out;
5118         }
5119
5120         /* create regular file via mknod */
5121         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5122                 log_stderr("failure: mknodat");
5123                 goto out;
5124         }
5125         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5126                 log_stderr("failure: fchownat");
5127                 goto out;
5128         }
5129         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5130                 log_stderr("failure: fchmodat");
5131                 goto out;
5132         }
5133
5134         /* create regular file via mknod */
5135         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5136                 log_stderr("failure: mknodat");
5137                 goto out;
5138         }
5139         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5140                 log_stderr("failure: fchownat");
5141                 goto out;
5142         }
5143         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5144                 log_stderr("failure: fchmodat");
5145                 goto out;
5146         }
5147
5148         /* The sticky bit is not set so we must be able to delete files not
5149          * owned by us.
5150          */
5151         pid = fork();
5152         if (pid < 0) {
5153                 log_stderr("failure: fork");
5154                 goto out;
5155         }
5156         if (pid == 0) {
5157                 if (!switch_ids(1000, 1000))
5158                         die("failure: switch_ids");
5159
5160                 if (renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5161                         die("failure: renameat");
5162
5163                 if (renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5164                         die("failure: renameat");
5165
5166                 if (renameat(dir_fd, FILE1_RENAME, dir_fd, FILE1))
5167                         die("failure: renameat");
5168
5169                 if (renameat(dir_fd, FILE2_RENAME, dir_fd, FILE2))
5170                         die("failure: renameat");
5171
5172                 exit(EXIT_SUCCESS);
5173         }
5174         if (wait_for_pid(pid)) {
5175                 log_stderr("failure: wait_for_pid");
5176                 goto out;
5177         }
5178
5179         /* set sticky bit */
5180         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5181                 log_stderr("failure: fchmod");
5182                 goto out;
5183         }
5184
5185         /* validate sticky bit is set */
5186         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5187                 log_stderr("failure: is_sticky");
5188                 goto out;
5189         }
5190
5191         /* The sticky bit is set so we must not be able to delete files not
5192          * owned by us.
5193          */
5194         pid = fork();
5195         if (pid < 0) {
5196                 log_stderr("failure: fork");
5197                 goto out;
5198         }
5199         if (pid == 0) {
5200                 if (!switch_ids(1000, 1000))
5201                         die("failure: switch_ids");
5202
5203                 if (!renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5204                         die("failure: renameat");
5205                 if (errno != EPERM)
5206                         die("failure: errno");
5207
5208                 if (!renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5209                         die("failure: renameat");
5210                 if (errno != EPERM)
5211                         die("failure: errno");
5212
5213                 exit(EXIT_SUCCESS);
5214         }
5215         if (wait_for_pid(pid)) {
5216                 log_stderr("failure: wait_for_pid");
5217                 goto out;
5218         }
5219
5220         /* The sticky bit is set and we own the files so we must be able to
5221          * delete the files now.
5222          */
5223         pid = fork();
5224         if (pid < 0) {
5225                 log_stderr("failure: fork");
5226                 goto out;
5227         }
5228         if (pid == 0) {
5229                 /* change ownership */
5230                 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
5231                         die("failure: fchownat");
5232                 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
5233                         die("failure: expected_uid_gid");
5234                 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
5235                         die("failure: fchownat");
5236                 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
5237                         die("failure: expected_uid_gid");
5238
5239                 if (!switch_ids(1000, 1000))
5240                         die("failure: switch_ids");
5241
5242                 if (renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5243                         die("failure: renameat");
5244
5245                 if (renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5246                         die("failure: renameat");
5247
5248                 if (renameat(dir_fd, FILE1_RENAME, dir_fd, FILE1))
5249                         die("failure: renameat");
5250
5251                 if (renameat(dir_fd, FILE2_RENAME, dir_fd, FILE2))
5252                         die("failure: renameat");
5253
5254                 exit(EXIT_SUCCESS);
5255         }
5256         if (wait_for_pid(pid)) {
5257                 log_stderr("failure: wait_for_pid");
5258                 goto out;
5259         }
5260
5261         /* change uid to unprivileged user */
5262         if (fchown(dir_fd, 1000, -1)) {
5263                 log_stderr("failure: fchown");
5264                 goto out;
5265         }
5266         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5267                 log_stderr("failure: fchmod");
5268                 goto out;
5269         }
5270         /* validate sticky bit is set */
5271         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5272                 log_stderr("failure: is_sticky");
5273                 goto out;
5274         }
5275
5276
5277         /* The sticky bit is set and we own the directory so we must be able to
5278          * delete the files now.
5279          */
5280         pid = fork();
5281         if (pid < 0) {
5282                 log_stderr("failure: fork");
5283                 goto out;
5284         }
5285         if (pid == 0) {
5286                 if (!switch_ids(1000, 1000))
5287                         die("failure: switch_ids");
5288
5289                 if (renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5290                         die("failure: renameat");
5291
5292                 if (renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5293                         die("failure: renameat");
5294
5295                 if (renameat(dir_fd, FILE1_RENAME, dir_fd, FILE1))
5296                         die("failure: renameat");
5297
5298                 if (renameat(dir_fd, FILE2_RENAME, dir_fd, FILE2))
5299                         die("failure: renameat");
5300
5301                 exit(EXIT_SUCCESS);
5302         }
5303         if (wait_for_pid(pid)) {
5304                 log_stderr("failure: wait_for_pid");
5305                 goto out;
5306         }
5307
5308         fret = 0;
5309         log_debug("Ran test");
5310 out:
5311         safe_close(dir_fd);
5312
5313         return fret;
5314 }
5315
5316 static int sticky_bit_rename_idmapped_mounts(void)
5317 {
5318         int fret = -1;
5319         int dir_fd = -EBADF, open_tree_fd = -EBADF;
5320         struct mount_attr attr = {
5321                 .attr_set = MOUNT_ATTR_IDMAP,
5322         };
5323         pid_t pid;
5324
5325         if (!caps_supported())
5326                 return 0;
5327
5328         /* create directory */
5329         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5330                 log_stderr("failure: mkdirat");
5331                 goto out;
5332         }
5333
5334         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5335         if (dir_fd < 0) {
5336                 log_stderr("failure: openat");
5337                 goto out;
5338         }
5339
5340         if (fchown(dir_fd, 10000, 10000)) {
5341                 log_stderr("failure: fchown");
5342                 goto out;
5343         }
5344
5345         if (fchmod(dir_fd, 0777)) {
5346                 log_stderr("failure: fchmod");
5347                 goto out;
5348         }
5349
5350         /* create regular file via mknod */
5351         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5352                 log_stderr("failure: mknodat");
5353                 goto out;
5354         }
5355         if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
5356                 log_stderr("failure: fchownat");
5357                 goto out;
5358         }
5359         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5360                 log_stderr("failure: fchmodat");
5361                 goto out;
5362         }
5363
5364         /* create regular file via mknod */
5365         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5366                 log_stderr("failure: mknodat");
5367                 goto out;
5368         }
5369         if (fchownat(dir_fd, FILE2, 12000, 12000, 0)) {
5370                 log_stderr("failure: fchownat");
5371                 goto out;
5372         }
5373         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5374                 log_stderr("failure: fchmodat");
5375                 goto out;
5376         }
5377
5378         /* Changing mount properties on a detached mount. */
5379         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
5380         if (attr.userns_fd < 0) {
5381                 log_stderr("failure: get_userns_fd");
5382                 goto out;
5383         }
5384
5385         open_tree_fd = sys_open_tree(dir_fd, "",
5386                                      AT_EMPTY_PATH |
5387                                      AT_NO_AUTOMOUNT |
5388                                      AT_SYMLINK_NOFOLLOW |
5389                                      OPEN_TREE_CLOEXEC |
5390                                      OPEN_TREE_CLONE);
5391         if (open_tree_fd < 0) {
5392                 log_stderr("failure: sys_open_tree");
5393                 goto out;
5394         }
5395
5396         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
5397                 log_stderr("failure: sys_mount_setattr");
5398                 goto out;
5399         }
5400
5401         /* The sticky bit is not set so we must be able to delete files not
5402          * owned by us.
5403          */
5404         pid = fork();
5405         if (pid < 0) {
5406                 log_stderr("failure: fork");
5407                 goto out;
5408         }
5409         if (pid == 0) {
5410                 if (!switch_ids(1000, 1000))
5411                         die("failure: switch_ids");
5412
5413                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5414                         die("failure: renameat");
5415
5416                 if (renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5417                         die("failure: renameat");
5418
5419                 if (renameat(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1))
5420                         die("failure: renameat");
5421
5422                 if (renameat(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2))
5423                         die("failure: renameat");
5424
5425                 exit(EXIT_SUCCESS);
5426         }
5427         if (wait_for_pid(pid)) {
5428                 log_stderr("failure: wait_for_pid");
5429                 goto out;
5430         }
5431
5432         /* set sticky bit */
5433         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5434                 log_stderr("failure: fchmod");
5435                 goto out;
5436         }
5437
5438         /* validate sticky bit is set */
5439         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5440                 log_stderr("failure: is_sticky");
5441                 goto out;
5442         }
5443
5444         /* The sticky bit is set so we must not be able to delete files not
5445          * owned by us.
5446          */
5447         pid = fork();
5448         if (pid < 0) {
5449                 log_stderr("failure: fork");
5450                 goto out;
5451         }
5452         if (pid == 0) {
5453                 if (!switch_ids(1000, 1000))
5454                         die("failure: switch_ids");
5455
5456                 if (!renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5457                         die("failure: renameat");
5458                 if (errno != EPERM)
5459                         die("failure: errno");
5460
5461                 if (!renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5462                         die("failure: renameat");
5463                 if (errno != EPERM)
5464                         die("failure: errno");
5465
5466                 exit(EXIT_SUCCESS);
5467         }
5468         if (wait_for_pid(pid)) {
5469                 log_stderr("failure: wait_for_pid");
5470                 goto out;
5471         }
5472
5473         /* The sticky bit is set and we own the files so we must be able to
5474          * delete the files now.
5475          */
5476         pid = fork();
5477         if (pid < 0) {
5478                 log_stderr("failure: fork");
5479                 goto out;
5480         }
5481         if (pid == 0) {
5482                 /* change ownership */
5483                 if (fchownat(dir_fd, FILE1, 11000, -1, 0))
5484                         die("failure: fchownat");
5485                 if (!expected_uid_gid(dir_fd, FILE1, 0, 11000, 10000))
5486                         die("failure: expected_uid_gid");
5487                 if (fchownat(dir_fd, FILE2, 11000, -1, 0))
5488                         die("failure: fchownat");
5489                 if (!expected_uid_gid(dir_fd, FILE2, 0, 11000, 12000))
5490                         die("failure: expected_uid_gid");
5491
5492                 if (!switch_ids(1000, 1000))
5493                         die("failure: switch_ids");
5494
5495                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5496                         die("failure: renameat");
5497
5498                 if (renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5499                         die("failure: renameat");
5500
5501                 if (renameat(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1))
5502                         die("failure: renameat");
5503
5504                 if (renameat(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2))
5505                         die("failure: renameat");
5506
5507                 exit(EXIT_SUCCESS);
5508         }
5509         if (wait_for_pid(pid)) {
5510                 log_stderr("failure: wait_for_pid");
5511                 goto out;
5512         }
5513
5514         /* change uid to unprivileged user */
5515         if (fchown(dir_fd, 11000, -1)) {
5516                 log_stderr("failure: fchown");
5517                 goto out;
5518         }
5519         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5520                 log_stderr("failure: fchmod");
5521                 goto out;
5522         }
5523         /* validate sticky bit is set */
5524         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5525                 log_stderr("failure: is_sticky");
5526                 goto out;
5527         }
5528
5529         /* The sticky bit is set and we own the directory so we must be able to
5530          * delete the files now.
5531          */
5532         pid = fork();
5533         if (pid < 0) {
5534                 log_stderr("failure: fork");
5535                 goto out;
5536         }
5537         if (pid == 0) {
5538                 if (!switch_ids(1000, 1000))
5539                         die("failure: switch_ids");
5540
5541                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5542                         die("failure: renameat");
5543
5544                 if (renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5545                         die("failure: renameat");
5546
5547                 if (renameat(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1))
5548                         die("failure: renameat");
5549
5550                 if (renameat(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2))
5551                         die("failure: renameat");
5552
5553                 exit(EXIT_SUCCESS);
5554         }
5555         if (wait_for_pid(pid)) {
5556                 log_stderr("failure: wait_for_pid");
5557                 goto out;
5558         }
5559
5560         fret = 0;
5561         log_debug("Ran test");
5562 out:
5563         safe_close(attr.userns_fd);
5564         safe_close(dir_fd);
5565         safe_close(open_tree_fd);
5566
5567         return fret;
5568 }
5569
5570 /* Validate that the sticky bit behaves correctly on idmapped mounts for unlink
5571  * operations in a user namespace.
5572  */
5573 static int sticky_bit_rename_idmapped_mounts_in_userns(void)
5574 {
5575         int fret = -1;
5576         int dir_fd = -EBADF, open_tree_fd = -EBADF;
5577         struct mount_attr attr = {
5578                 .attr_set = MOUNT_ATTR_IDMAP,
5579         };
5580         pid_t pid;
5581
5582         if (!caps_supported())
5583                 return 0;
5584
5585         /* create directory */
5586         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5587                 log_stderr("failure: mkdirat");
5588                 goto out;
5589         }
5590
5591         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5592         if (dir_fd < 0) {
5593                 log_stderr("failure: openat");
5594                 goto out;
5595         }
5596         if (fchown(dir_fd, 0, 0)) {
5597                 log_stderr("failure: fchown");
5598                 goto out;
5599         }
5600         if (fchmod(dir_fd, 0777)) {
5601                 log_stderr("failure: fchmod");
5602                 goto out;
5603         }
5604
5605         /* create regular file via mknod */
5606         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5607                 log_stderr("failure: mknodat");
5608                 goto out;
5609         }
5610         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5611                 log_stderr("failure: fchownat");
5612                 goto out;
5613         }
5614         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5615                 log_stderr("failure: fchmodat");
5616                 goto out;
5617         }
5618
5619         /* create regular file via mknod */
5620         if (mknodat(dir_fd, FILE2, S_IFREG | 0000, 0)) {
5621                 log_stderr("failure: mknodat");
5622                 goto out;
5623         }
5624         if (fchownat(dir_fd, FILE2, 2000, 2000, 0)) {
5625                 log_stderr("failure: fchownat");
5626                 goto out;
5627         }
5628         if (fchmodat(dir_fd, FILE2, 0644, 0)) {
5629                 log_stderr("failure: fchmodat");
5630                 goto out;
5631         }
5632
5633         /* Changing mount properties on a detached mount. */
5634         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
5635         if (attr.userns_fd < 0) {
5636                 log_stderr("failure: get_userns_fd");
5637                 goto out;
5638         }
5639
5640         open_tree_fd = sys_open_tree(dir_fd, "",
5641                                      AT_EMPTY_PATH |
5642                                      AT_NO_AUTOMOUNT |
5643                                      AT_SYMLINK_NOFOLLOW |
5644                                      OPEN_TREE_CLOEXEC |
5645                                      OPEN_TREE_CLONE);
5646         if (open_tree_fd < 0) {
5647                 log_stderr("failure: sys_open_tree");
5648                 goto out;
5649         }
5650
5651         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
5652                 log_stderr("failure: sys_mount_setattr");
5653                 goto out;
5654         }
5655
5656         /* The sticky bit is not set so we must be able to delete files not
5657          * owned by us.
5658          */
5659         pid = fork();
5660         if (pid < 0) {
5661                 log_stderr("failure: fork");
5662                 goto out;
5663         }
5664         if (pid == 0) {
5665                 if (!caps_supported()) {
5666                         log_debug("skip: capability library not installed");
5667                         exit(EXIT_SUCCESS);
5668                 }
5669
5670                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5671                         die("failure: switch_userns");
5672
5673                 if (renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5674                         die("failure: renameat");
5675
5676                 if (renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5677                         die("failure: renameat");
5678
5679                 if (renameat(dir_fd, FILE1_RENAME, dir_fd, FILE1))
5680                         die("failure: renameat");
5681
5682                 if (renameat(dir_fd, FILE2_RENAME, dir_fd, FILE2))
5683                         die("failure: renameat");
5684
5685                 exit(EXIT_SUCCESS);
5686         }
5687         if (wait_for_pid(pid)) {
5688                 log_stderr("failure: wait_for_pid");
5689                 goto out;
5690         }
5691
5692         /* set sticky bit */
5693         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5694                 log_stderr("failure: fchmod");
5695                 goto out;
5696         }
5697
5698         /* validate sticky bit is set */
5699         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5700                 log_stderr("failure: is_sticky");
5701                 goto out;
5702         }
5703
5704         /* The sticky bit is set so we must not be able to delete files not
5705          * owned by us.
5706          */
5707         pid = fork();
5708         if (pid < 0) {
5709                 log_stderr("failure: fork");
5710                 goto out;
5711         }
5712         if (pid == 0) {
5713                 if (!caps_supported()) {
5714                         log_debug("skip: capability library not installed");
5715                         exit(EXIT_SUCCESS);
5716                 }
5717
5718                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5719                         die("failure: switch_userns");
5720
5721                 if (!renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5722                         die("failure: renameat");
5723                 if (errno != EPERM)
5724                         die("failure: errno");
5725
5726                 if (!renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5727                         die("failure: renameat");
5728                 if (errno != EPERM)
5729                         die("failure: errno");
5730
5731                 if (!renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5732                         die("failure: renameat");
5733                 if (errno != EPERM)
5734                         die("failure: errno");
5735
5736                 if (!renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5737                         die("failure: renameat");
5738                 if (errno != EPERM)
5739                         die("failure: errno");
5740
5741                 exit(EXIT_SUCCESS);
5742         }
5743         if (wait_for_pid(pid)) {
5744                 log_stderr("failure: wait_for_pid");
5745                 goto out;
5746         }
5747
5748         /* The sticky bit is set and we own the files so we must be able to
5749          * delete the files now.
5750          */
5751         pid = fork();
5752         if (pid < 0) {
5753                 log_stderr("failure: fork");
5754                 goto out;
5755         }
5756         if (pid == 0) {
5757                 /* change ownership */
5758                 if (fchownat(dir_fd, FILE1, 1000, -1, 0))
5759                         die("failure: fchownat");
5760                 if (!expected_uid_gid(dir_fd, FILE1, 0, 1000, 0))
5761                         die("failure: expected_uid_gid");
5762                 if (fchownat(dir_fd, FILE2, 1000, -1, 0))
5763                         die("failure: fchownat");
5764                 if (!expected_uid_gid(dir_fd, FILE2, 0, 1000, 2000))
5765                         die("failure: expected_uid_gid");
5766
5767                 if (!caps_supported()) {
5768                         log_debug("skip: capability library not installed");
5769                         exit(EXIT_SUCCESS);
5770                 }
5771
5772                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5773                         die("failure: switch_userns");
5774
5775                 if (!renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5776                         die("failure: renameat");
5777                 if (errno != EPERM)
5778                         die("failure: errno");
5779
5780                 if (!renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5781                         die("failure: renameat");
5782                 if (errno != EPERM)
5783                         die("failure: errno");
5784
5785                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5786                         die("failure: renameat");
5787
5788                 if (renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5789                         die("failure: renameat");
5790
5791                 if (renameat(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1))
5792                         die("failure: renameat");
5793
5794                 if (renameat(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2))
5795                         die("failure: renameat");
5796
5797                 exit(EXIT_SUCCESS);
5798         }
5799         if (wait_for_pid(pid)) {
5800                 log_stderr("failure: wait_for_pid");
5801                 goto out;
5802         }
5803
5804         /* change uid to unprivileged user */
5805         if (fchown(dir_fd, 1000, -1)) {
5806                 log_stderr("failure: fchown");
5807                 goto out;
5808         }
5809         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5810                 log_stderr("failure: fchmod");
5811                 goto out;
5812         }
5813         /* validate sticky bit is set */
5814         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5815                 log_stderr("failure: is_sticky");
5816                 goto out;
5817         }
5818
5819         /* The sticky bit is set and we own the directory so we must be able to
5820          * delete the files now.
5821          */
5822         pid = fork();
5823         if (pid < 0) {
5824                 log_stderr("failure: fork");
5825                 goto out;
5826         }
5827         if (pid == 0) {
5828                 if (!caps_supported()) {
5829                         log_debug("skip: capability library not installed");
5830                         exit(EXIT_SUCCESS);
5831                 }
5832
5833                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
5834                         die("failure: switch_userns");
5835
5836                 /* we don't own the directory from the original mount */
5837                 if (!renameat(dir_fd, FILE1, dir_fd, FILE1_RENAME))
5838                         die("failure: renameat");
5839                 if (errno != EPERM)
5840                         die("failure: errno");
5841
5842                 if (!renameat(dir_fd, FILE2, dir_fd, FILE2_RENAME))
5843                         die("failure: renameat");
5844                 if (errno != EPERM)
5845                         die("failure: errno");
5846
5847                 /* we own the file from the idmapped mount */
5848                 if (renameat(open_tree_fd, FILE1, open_tree_fd, FILE1_RENAME))
5849                         die("failure: renameat");
5850
5851                 if (renameat(open_tree_fd, FILE2, open_tree_fd, FILE2_RENAME))
5852                         die("failure: renameat");
5853
5854                 if (renameat(open_tree_fd, FILE1_RENAME, open_tree_fd, FILE1))
5855                         die("failure: renameat");
5856
5857                 if (renameat(open_tree_fd, FILE2_RENAME, open_tree_fd, FILE2))
5858                         die("failure: renameat");
5859
5860                 exit(EXIT_SUCCESS);
5861         }
5862         if (wait_for_pid(pid)) {
5863                 log_stderr("failure: wait_for_pid");
5864                 goto out;
5865         }
5866
5867         fret = 0;
5868         log_debug("Ran test");
5869 out:
5870         safe_close(open_tree_fd);
5871         safe_close(attr.userns_fd);
5872         safe_close(dir_fd);
5873
5874         return fret;
5875 }
5876
5877 /* Validate that protected symlinks work correctly. */
5878 static int protected_symlinks(void)
5879 {
5880         int fret = -1;
5881         int dir_fd = -EBADF, fd = -EBADF;
5882         pid_t pid;
5883
5884         if (!protected_symlinks_enabled())
5885                 return 0;
5886
5887         if (!caps_supported())
5888                 return 0;
5889
5890         /* create directory */
5891         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
5892                 log_stderr("failure: mkdirat");
5893                 goto out;
5894         }
5895
5896         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
5897         if (dir_fd < 0) {
5898                 log_stderr("failure: openat");
5899                 goto out;
5900         }
5901         if (fchown(dir_fd, 0, 0)) {
5902                 log_stderr("failure: fchown");
5903                 goto out;
5904         }
5905         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
5906                 log_stderr("failure: fchmod");
5907                 goto out;
5908         }
5909         /* validate sticky bit is set */
5910         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
5911                 log_stderr("failure: is_sticky");
5912                 goto out;
5913         }
5914
5915         /* create regular file via mknod */
5916         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
5917                 log_stderr("failure: mknodat");
5918                 goto out;
5919         }
5920         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
5921                 log_stderr("failure: fchownat");
5922                 goto out;
5923         }
5924         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
5925                 log_stderr("failure: fchmodat");
5926                 goto out;
5927         }
5928
5929         /* create symlinks */
5930         if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
5931                 log_stderr("failure: symlinkat");
5932                 goto out;
5933         }
5934         if (fchownat(dir_fd, SYMLINK_USER1, 0, 0, AT_SYMLINK_NOFOLLOW)) {
5935                 log_stderr("failure: fchownat");
5936                 goto out;
5937         }
5938         if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
5939                 log_stderr("failure: expected_uid_gid");
5940                 goto out;
5941         }
5942         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5943                 log_stderr("failure: expected_uid_gid");
5944                 goto out;
5945         }
5946
5947         if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
5948                 log_stderr("failure: symlinkat");
5949                 goto out;
5950         }
5951         if (fchownat(dir_fd, SYMLINK_USER2, 1000, 1000, AT_SYMLINK_NOFOLLOW)) {
5952                 log_stderr("failure: fchownat");
5953                 goto out;
5954         }
5955         if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 1000, 1000)) {
5956                 log_stderr("failure: expected_uid_gid");
5957                 goto out;
5958         }
5959         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5960                 log_stderr("failure: expected_uid_gid");
5961                 goto out;
5962         }
5963
5964         if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
5965                 log_stderr("failure: symlinkat");
5966                 goto out;
5967         }
5968         if (fchownat(dir_fd, SYMLINK_USER3, 2000, 2000, AT_SYMLINK_NOFOLLOW)) {
5969                 log_stderr("failure: fchownat");
5970                 goto out;
5971         }
5972         if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
5973                 log_stderr("failure: expected_uid_gid");
5974                 goto out;
5975         }
5976         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
5977                 log_stderr("failure: expected_uid_gid");
5978                 goto out;
5979         }
5980
5981         /* validate file can be directly read */
5982         fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
5983         if (fd < 0) {
5984                 log_stderr("failure: openat");
5985                 goto out;
5986         }
5987         safe_close(fd);
5988
5989         /* validate file can be read through own symlink */
5990         fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
5991         if (fd < 0) {
5992                 log_stderr("failure: openat");
5993                 goto out;
5994         }
5995         safe_close(fd);
5996
5997         pid = fork();
5998         if (pid < 0) {
5999                 log_stderr("failure: fork");
6000                 goto out;
6001         }
6002         if (pid == 0) {
6003                 if (!switch_ids(1000, 1000))
6004                         die("failure: switch_ids");
6005
6006                 /* validate file can be directly read */
6007                 fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
6008                 if (fd < 0)
6009                         die("failure: openat");
6010                 safe_close(fd);
6011
6012                 /* validate file can be read through own symlink */
6013                 fd = openat(dir_fd, SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6014                 if (fd < 0)
6015                         die("failure: openat");
6016                 safe_close(fd);
6017
6018                 /* validate file can be read through root symlink */
6019                 fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6020                 if (fd < 0)
6021                         die("failure: openat");
6022                 safe_close(fd);
6023
6024                 /* validate file can't be read through other users symlink */
6025                 fd = openat(dir_fd, SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6026                 if (fd >= 0)
6027                         die("failure: openat");
6028                 if (errno != EACCES)
6029                         die("failure: errno");
6030
6031                 exit(EXIT_SUCCESS);
6032         }
6033         if (wait_for_pid(pid)) {
6034                 log_stderr("failure: wait_for_pid");
6035                 goto out;
6036         }
6037
6038         pid = fork();
6039         if (pid < 0) {
6040                 log_stderr("failure: fork");
6041                 goto out;
6042         }
6043         if (pid == 0) {
6044                 if (!switch_ids(2000, 2000))
6045                         die("failure: switch_ids");
6046
6047                 /* validate file can be directly read */
6048                 fd = openat(dir_fd, FILE1, O_RDONLY | O_CLOEXEC, 0);
6049                 if (fd < 0)
6050                         die("failure: openat");
6051                 safe_close(fd);
6052
6053                 /* validate file can be read through own symlink */
6054                 fd = openat(dir_fd, SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6055                 if (fd < 0)
6056                         die("failure: openat");
6057                 safe_close(fd);
6058
6059                 /* validate file can be read through root symlink */
6060                 fd = openat(dir_fd, SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6061                 if (fd < 0)
6062                         die("failure: openat");
6063                 safe_close(fd);
6064
6065                 /* validate file can't be read through other users symlink */
6066                 fd = openat(dir_fd, SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6067                 if (fd >= 0)
6068                         die("failure: openat");
6069                 if (errno != EACCES)
6070                         die("failure: errno");
6071
6072                 exit(EXIT_SUCCESS);
6073         }
6074         if (wait_for_pid(pid)) {
6075                 log_stderr("failure: wait_for_pid");
6076                 goto out;
6077         }
6078
6079         fret = 0;
6080         log_debug("Ran test");
6081 out:
6082         safe_close(fd);
6083         safe_close(dir_fd);
6084
6085         return fret;
6086 }
6087
6088 /* Validate that protected symlinks work correctly on idmapped mounts. */
6089 static int protected_symlinks_idmapped_mounts(void)
6090 {
6091         int fret = -1;
6092         int dir_fd = -EBADF, fd = -EBADF, open_tree_fd = -EBADF;
6093         struct mount_attr attr = {
6094                 .attr_set = MOUNT_ATTR_IDMAP,
6095         };
6096         pid_t pid;
6097
6098         if (!protected_symlinks_enabled())
6099                 return 0;
6100
6101         if (!caps_supported())
6102                 return 0;
6103
6104         /* create directory */
6105         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
6106                 log_stderr("failure: mkdirat");
6107                 goto out;
6108         }
6109
6110         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6111         if (dir_fd < 0) {
6112                 log_stderr("failure: openat");
6113                 goto out;
6114         }
6115         if (fchown(dir_fd, 10000, 10000)) {
6116                 log_stderr("failure: fchown");
6117                 goto out;
6118         }
6119         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
6120                 log_stderr("failure: fchmod");
6121                 goto out;
6122         }
6123         /* validate sticky bit is set */
6124         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
6125                 log_stderr("failure: is_sticky");
6126                 goto out;
6127         }
6128
6129         /* create regular file via mknod */
6130         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
6131                 log_stderr("failure: mknodat");
6132                 goto out;
6133         }
6134         if (fchownat(dir_fd, FILE1, 10000, 10000, 0)) {
6135                 log_stderr("failure: fchownat");
6136                 goto out;
6137         }
6138         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
6139                 log_stderr("failure: fchmodat");
6140                 goto out;
6141         }
6142
6143         /* create symlinks */
6144         if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
6145                 log_stderr("failure: symlinkat");
6146                 goto out;
6147         }
6148         if (fchownat(dir_fd, SYMLINK_USER1, 10000, 10000, AT_SYMLINK_NOFOLLOW)) {
6149                 log_stderr("failure: fchownat");
6150                 goto out;
6151         }
6152         if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 10000, 10000)) {
6153                 log_stderr("failure: expected_uid_gid");
6154                 goto out;
6155         }
6156         if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6157                 log_stderr("failure: expected_uid_gid");
6158                 goto out;
6159         }
6160
6161         if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
6162                 log_stderr("failure: symlinkat");
6163                 goto out;
6164         }
6165         if (fchownat(dir_fd, SYMLINK_USER2, 11000, 11000, AT_SYMLINK_NOFOLLOW)) {
6166                 log_stderr("failure: fchownat");
6167                 goto out;
6168         }
6169         if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 11000, 11000)) {
6170                 log_stderr("failure: expected_uid_gid");
6171                 goto out;
6172         }
6173         if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6174                 log_stderr("failure: expected_uid_gid");
6175                 goto out;
6176         }
6177
6178         if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
6179                 log_stderr("failure: symlinkat");
6180                 goto out;
6181         }
6182         if (fchownat(dir_fd, SYMLINK_USER3, 12000, 12000, AT_SYMLINK_NOFOLLOW)) {
6183                 log_stderr("failure: fchownat");
6184                 goto out;
6185         }
6186         if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 12000, 12000)) {
6187                 log_stderr("failure: expected_uid_gid");
6188                 goto out;
6189         }
6190         if (!expected_uid_gid(dir_fd, FILE1, 0, 10000, 10000)) {
6191                 log_stderr("failure: expected_uid_gid");
6192                 goto out;
6193         }
6194
6195         /* Changing mount properties on a detached mount. */
6196         attr.userns_fd  = get_userns_fd(10000, 0, 10000);
6197         if (attr.userns_fd < 0) {
6198                 log_stderr("failure: get_userns_fd");
6199                 goto out;
6200         }
6201
6202         open_tree_fd = sys_open_tree(t_dir1_fd, "",
6203                                      AT_EMPTY_PATH |
6204                                      AT_NO_AUTOMOUNT |
6205                                      AT_SYMLINK_NOFOLLOW |
6206                                      OPEN_TREE_CLOEXEC |
6207                                      OPEN_TREE_CLONE);
6208         if (open_tree_fd < 0) {
6209                 log_stderr("failure: open_tree_fd");
6210                 goto out;
6211         }
6212
6213         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6214                 log_stderr("failure: sys_mount_setattr");
6215                 goto out;
6216         }
6217
6218         /* validate file can be directly read */
6219         fd = openat(open_tree_fd, DIR1 "/"  FILE1, O_RDONLY | O_CLOEXEC, 0);
6220         if (fd < 0) {
6221                 log_stderr("failure: openat");
6222                 goto out;
6223         }
6224         safe_close(fd);
6225
6226         /* validate file can be read through own symlink */
6227         fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6228         if (fd < 0) {
6229                 log_stderr("failure: openat");
6230                 goto out;
6231         }
6232         safe_close(fd);
6233
6234         pid = fork();
6235         if (pid < 0) {
6236                 log_stderr("failure: fork");
6237                 goto out;
6238         }
6239         if (pid == 0) {
6240                 if (!switch_ids(1000, 1000))
6241                         die("failure: switch_ids");
6242
6243                 /* validate file can be directly read */
6244                 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6245                 if (fd < 0)
6246                         die("failure: openat");
6247                 safe_close(fd);
6248
6249                 /* validate file can be read through own symlink */
6250                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6251                 if (fd < 0)
6252                         die("failure: openat");
6253                 safe_close(fd);
6254
6255                 /* validate file can be read through root symlink */
6256                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6257                 if (fd < 0)
6258                         die("failure: openat");
6259                 safe_close(fd);
6260
6261                 /* validate file can't be read through other users symlink */
6262                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6263                 if (fd >= 0)
6264                         die("failure: openat");
6265                 if (errno != EACCES)
6266                         die("failure: errno");
6267
6268                 exit(EXIT_SUCCESS);
6269         }
6270         if (wait_for_pid(pid)) {
6271                 log_stderr("failure: wait_for_pid");
6272                 goto out;
6273         }
6274
6275         pid = fork();
6276         if (pid < 0) {
6277                 log_stderr("failure: fork");
6278                 goto out;
6279         }
6280         if (pid == 0) {
6281                 if (!switch_ids(2000, 2000))
6282                         die("failure: switch_ids");
6283
6284                 /* validate file can be directly read */
6285                 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6286                 if (fd < 0)
6287                         die("failure: openat");
6288                 safe_close(fd);
6289
6290                 /* validate file can be read through own symlink */
6291                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6292                 if (fd < 0)
6293                         die("failure: openat");
6294                 safe_close(fd);
6295
6296                 /* validate file can be read through root symlink */
6297                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6298                 if (fd < 0)
6299                         die("failure: openat");
6300                 safe_close(fd);
6301
6302                 /* validate file can't be read through other users symlink */
6303                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6304                 if (fd >= 0)
6305                         die("failure: openat");
6306                 if (errno != EACCES)
6307                         die("failure: errno");
6308
6309                 exit(EXIT_SUCCESS);
6310         }
6311         if (wait_for_pid(pid)) {
6312                 log_stderr("failure: wait_for_pid");
6313                 goto out;
6314         }
6315
6316         fret = 0;
6317         log_debug("Ran test");
6318 out:
6319         safe_close(attr.userns_fd);
6320         safe_close(fd);
6321         safe_close(dir_fd);
6322         safe_close(open_tree_fd);
6323
6324         return fret;
6325 }
6326
6327 /* Validate that protected symlinks work correctly on idmapped mounts inside a
6328  * user namespace.
6329  */
6330 static int protected_symlinks_idmapped_mounts_in_userns(void)
6331 {
6332         int fret = -1;
6333         int dir_fd = -EBADF, fd = -EBADF, open_tree_fd = -EBADF;
6334         struct mount_attr attr = {
6335                 .attr_set = MOUNT_ATTR_IDMAP,
6336         };
6337         pid_t pid;
6338
6339         if (!protected_symlinks_enabled())
6340                 return 0;
6341
6342         if (!caps_supported())
6343                 return 0;
6344
6345         /* create directory */
6346         if (mkdirat(t_dir1_fd, DIR1, 0000)) {
6347                 log_stderr("failure: mkdirat");
6348                 goto out;
6349         }
6350
6351         dir_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6352         if (dir_fd < 0) {
6353                 log_stderr("failure: openat");
6354                 goto out;
6355         }
6356         if (fchown(dir_fd, 0, 0)) {
6357                 log_stderr("failure: fchown");
6358                 goto out;
6359         }
6360         if (fchmod(dir_fd, 0777 | S_ISVTX)) {
6361                 log_stderr("failure: fchmod");
6362                 goto out;
6363         }
6364         /* validate sticky bit is set */
6365         if (!is_sticky(t_dir1_fd, DIR1, 0)) {
6366                 log_stderr("failure: is_sticky");
6367                 goto out;
6368         }
6369
6370         /* create regular file via mknod */
6371         if (mknodat(dir_fd, FILE1, S_IFREG | 0000, 0)) {
6372                 log_stderr("failure: mknodat");
6373                 goto out;
6374         }
6375         if (fchownat(dir_fd, FILE1, 0, 0, 0)) {
6376                 log_stderr("failure: fchownat");
6377                 goto out;
6378         }
6379         if (fchmodat(dir_fd, FILE1, 0644, 0)) {
6380                 log_stderr("failure: fchmodat");
6381                 goto out;
6382         }
6383
6384         /* create symlinks */
6385         if (symlinkat(FILE1, dir_fd, SYMLINK_USER1)) {
6386                 log_stderr("failure: symlinkat");
6387                 goto out;
6388         }
6389         if (fchownat(dir_fd, SYMLINK_USER1, 0, 0, AT_SYMLINK_NOFOLLOW)) {
6390                 log_stderr("failure: fchownat");
6391                 goto out;
6392         }
6393         if (!expected_uid_gid(dir_fd, SYMLINK_USER1, AT_SYMLINK_NOFOLLOW, 0, 0)) {
6394                 log_stderr("failure: expected_uid_gid");
6395                 goto out;
6396         }
6397         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6398                 log_stderr("failure: expected_uid_gid");
6399                 goto out;
6400         }
6401
6402         if (symlinkat(FILE1, dir_fd, SYMLINK_USER2)) {
6403                 log_stderr("failure: symlinkat");
6404                 goto out;
6405         }
6406         if (fchownat(dir_fd, SYMLINK_USER2, 1000, 1000, AT_SYMLINK_NOFOLLOW)) {
6407                 log_stderr("failure: fchownat");
6408                 goto out;
6409         }
6410         if (!expected_uid_gid(dir_fd, SYMLINK_USER2, AT_SYMLINK_NOFOLLOW, 1000, 1000)) {
6411                 log_stderr("failure: expected_uid_gid");
6412                 goto out;
6413         }
6414         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6415                 log_stderr("failure: expected_uid_gid");
6416                 goto out;
6417         }
6418
6419         if (symlinkat(FILE1, dir_fd, SYMLINK_USER3)) {
6420                 log_stderr("failure: symlinkat");
6421                 goto out;
6422         }
6423         if (fchownat(dir_fd, SYMLINK_USER3, 2000, 2000, AT_SYMLINK_NOFOLLOW)) {
6424                 log_stderr("failure: fchownat");
6425                 goto out;
6426         }
6427         if (!expected_uid_gid(dir_fd, SYMLINK_USER3, AT_SYMLINK_NOFOLLOW, 2000, 2000)) {
6428                 log_stderr("failure: expected_uid_gid");
6429                 goto out;
6430         }
6431         if (!expected_uid_gid(dir_fd, FILE1, 0, 0, 0)) {
6432                 log_stderr("failure: expected_uid_gid");
6433                 goto out;
6434         }
6435
6436         /* Changing mount properties on a detached mount. */
6437         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
6438         if (attr.userns_fd < 0) {
6439                 log_stderr("failure: get_userns_fd");
6440                 goto out;
6441         }
6442
6443         open_tree_fd = sys_open_tree(t_dir1_fd, "",
6444                                      AT_EMPTY_PATH |
6445                                      AT_NO_AUTOMOUNT |
6446                                      AT_SYMLINK_NOFOLLOW |
6447                                      OPEN_TREE_CLOEXEC |
6448                                      OPEN_TREE_CLONE);
6449         if (open_tree_fd < 0) {
6450                 log_stderr("failure: sys_open_tree");
6451                 goto out;
6452         }
6453
6454         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6455                 log_stderr("failure: sys_mount_setattr");
6456                 goto out;
6457         }
6458
6459         /* validate file can be directly read */
6460         fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6461         if (fd < 0) {
6462                 log_stderr("failure: openat");
6463                 goto out;
6464         }
6465         safe_close(fd);
6466
6467         /* validate file can be read through own symlink */
6468         fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6469         if (fd < 0) {
6470                 log_stderr("failure: openat");
6471                 goto out;
6472         }
6473         safe_close(fd);
6474
6475         pid = fork();
6476         if (pid < 0) {
6477                 log_stderr("failure: fork");
6478                 goto out;
6479         }
6480         if (pid == 0) {
6481                 if (!caps_supported()) {
6482                         log_debug("skip: capability library not installed");
6483                         exit(EXIT_SUCCESS);
6484                 }
6485
6486                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
6487                         die("failure: switch_userns");
6488
6489                 /* validate file can be directly read */
6490                 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6491                 if (fd < 0)
6492                         die("failure: openat");
6493                 safe_close(fd);
6494
6495                 /* validate file can be read through own symlink */
6496                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6497                 if (fd < 0)
6498                         die("failure: openat");
6499                 safe_close(fd);
6500
6501                 /* validate file can be read through root symlink */
6502                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6503                 if (fd < 0)
6504                         die("failure: openat");
6505                 safe_close(fd);
6506
6507                 /* validate file can't be read through other users symlink */
6508                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6509                 if (fd >= 0)
6510                         die("failure: openat");
6511                 if (errno != EACCES)
6512                         die("failure: errno");
6513
6514                 exit(EXIT_SUCCESS);
6515         }
6516         if (wait_for_pid(pid)) {
6517                 log_stderr("failure: wait_for_pid");
6518                 goto out;
6519         }
6520
6521         pid = fork();
6522         if (pid < 0) {
6523                 log_stderr("failure: fork");
6524                 goto out;
6525         }
6526         if (pid == 0) {
6527                 if (!caps_supported()) {
6528                         log_debug("skip: capability library not installed");
6529                         exit(EXIT_SUCCESS);
6530                 }
6531
6532                 if (!switch_userns(attr.userns_fd, 2000, 2000, true))
6533                         die("failure: switch_userns");
6534
6535                 /* validate file can be directly read */
6536                 fd = openat(open_tree_fd, DIR1 "/" FILE1, O_RDONLY | O_CLOEXEC, 0);
6537                 if (fd < 0)
6538                         die("failure: openat");
6539                 safe_close(fd);
6540
6541                 /* validate file can be read through own symlink */
6542                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER3, O_RDONLY | O_CLOEXEC, 0);
6543                 if (fd < 0)
6544                         die("failure: openat");
6545                 safe_close(fd);
6546
6547                 /* validate file can be read through root symlink */
6548                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER1, O_RDONLY | O_CLOEXEC, 0);
6549                 if (fd < 0)
6550                         die("failure: openat");
6551                 safe_close(fd);
6552
6553                 /* validate file can't be read through other users symlink */
6554                 fd = openat(open_tree_fd, DIR1 "/" SYMLINK_USER2, O_RDONLY | O_CLOEXEC, 0);
6555                 if (fd >= 0)
6556                         die("failure: openat");
6557                 if (errno != EACCES)
6558                         die("failure: errno");
6559
6560                 exit(EXIT_SUCCESS);
6561         }
6562         if (wait_for_pid(pid)) {
6563                 log_stderr("failure: wait_for_pid");
6564                 goto out;
6565         }
6566
6567         fret = 0;
6568         log_debug("Ran test");
6569 out:
6570         safe_close(dir_fd);
6571         safe_close(open_tree_fd);
6572         safe_close(attr.userns_fd);
6573
6574         return fret;
6575 }
6576
6577 static int acls(void)
6578 {
6579         int fret = -1;
6580         int dir1_fd = -EBADF, open_tree_fd = -EBADF;
6581         struct mount_attr attr = {
6582                 .attr_set = MOUNT_ATTR_IDMAP,
6583         };
6584         pid_t pid;
6585
6586         if (mkdirat(t_dir1_fd, DIR1, 0777)) {
6587                 log_stderr("failure: mkdirat");
6588                 goto out;
6589         }
6590         if (fchmodat(t_dir1_fd, DIR1, 0777, 0)) {
6591                 log_stderr("failure: fchmodat");
6592                 goto out;
6593         }
6594
6595         if (mkdirat(t_dir1_fd, DIR2, 0777)) {
6596                 log_stderr("failure: mkdirat");
6597                 goto out;
6598         }
6599         if (fchmodat(t_dir1_fd, DIR2, 0777, 0)) {
6600                 log_stderr("failure: fchmodat");
6601                 goto out;
6602         }
6603
6604         /* Changing mount properties on a detached mount. */
6605         attr.userns_fd = get_userns_fd(100010, 100020, 5);
6606         if (attr.userns_fd < 0) {
6607                 log_stderr("failure: get_userns_fd");
6608                 goto out;
6609         }
6610
6611         open_tree_fd = sys_open_tree(t_dir1_fd, DIR1,
6612                                      AT_NO_AUTOMOUNT |
6613                                      AT_SYMLINK_NOFOLLOW |
6614                                      OPEN_TREE_CLOEXEC |
6615                                      OPEN_TREE_CLONE);
6616         if (open_tree_fd < 0) {
6617                 log_stderr("failure: sys_open_tree");
6618                 goto out;
6619         }
6620
6621         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
6622                 log_stderr("failure: sys_mount_setattr");
6623                 goto out;
6624         }
6625
6626         if (sys_move_mount(open_tree_fd, "", t_dir1_fd, DIR2, MOVE_MOUNT_F_EMPTY_PATH)) {
6627                 log_stderr("failure: sys_move_mount");
6628                 goto out;
6629         }
6630
6631         dir1_fd = openat(t_dir1_fd, DIR1, O_DIRECTORY | O_CLOEXEC);
6632         if (dir1_fd < 0) {
6633                 log_stderr("failure: openat");
6634                 goto out;
6635         }
6636
6637         if (mkdirat(dir1_fd, DIR3, 0000)) {
6638                 log_stderr("failure: mkdirat");
6639                 goto out;
6640         }
6641         if (fchown(dir1_fd, 100010, 100010)) {
6642                 log_stderr("failure: fchown");
6643                 goto out;
6644         }
6645         if (fchmod(dir1_fd, 0777)) {
6646                 log_stderr("failure: fchmod");
6647                 goto out;
6648         }
6649
6650         snprintf(t_buf, sizeof(t_buf), "setfacl -m u:100010:rwx %s/%s/%s/%s", t_mountpoint, T_DIR1, DIR1, DIR3);
6651         if (system(t_buf)) {
6652                 log_stderr("failure: system");
6653                 goto out;
6654         }
6655
6656         snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:100010:rwx", t_mountpoint, T_DIR1, DIR1, DIR3);
6657         if (system(t_buf)) {
6658                 log_stderr("failure: system");
6659                 goto out;
6660         }
6661
6662         snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:100020:rwx", t_mountpoint, T_DIR1, DIR2, DIR3);
6663         if (system(t_buf)) {
6664                 log_stderr("failure: system");
6665                 goto out;
6666         }
6667
6668         pid = fork();
6669         if (pid < 0) {
6670                 log_stderr("failure: fork");
6671                 goto out;
6672         }
6673         if (pid == 0) {
6674                 if (!caps_supported()) {
6675                         log_debug("skip: capability library not installed");
6676                         exit(EXIT_SUCCESS);
6677                 }
6678
6679                 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6680                         die("failure: switch_userns");
6681
6682                 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:%lu:rwx",
6683                          t_mountpoint, T_DIR1, DIR1, DIR3, 4294967295LU);
6684                 if (system(t_buf))
6685                         die("failure: system");
6686
6687                 exit(EXIT_SUCCESS);
6688         }
6689         if (wait_for_pid(pid)) {
6690                 log_stderr("failure: wait_for_pid");
6691                 goto out;
6692         }
6693
6694         pid = fork();
6695         if (pid < 0) {
6696                 log_stderr("failure: fork");
6697                 goto out;
6698         }
6699         if (pid == 0) {
6700                 if (!caps_supported()) {
6701                         log_debug("skip: capability library not installed");
6702                         exit(EXIT_SUCCESS);
6703                 }
6704
6705                 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6706                         die("failure: switch_userns");
6707
6708                 snprintf(t_buf, sizeof(t_buf), "getfacl -p %s/%s/%s/%s | grep -q user:%lu:rwx",
6709                          t_mountpoint, T_DIR1, DIR2, DIR3, 100010LU);
6710                 if (system(t_buf))
6711                         die("failure: system");
6712
6713                 exit(EXIT_SUCCESS);
6714         }
6715         if (wait_for_pid(pid)) {
6716                 log_stderr("failure: wait_for_pid");
6717                 goto out;
6718         }
6719
6720         /* Now, dir is owned by someone else in the user namespace, but we can
6721          * still read it because of acls.
6722          */
6723         if (fchown(dir1_fd, 100012, 100012)) {
6724                 log_stderr("failure: fchown");
6725                 goto out;
6726         }
6727
6728         pid = fork();
6729         if (pid < 0) {
6730                 log_stderr("failure: fork");
6731                 goto out;
6732         }
6733         if (pid == 0) {
6734                 int fd;
6735
6736                 if (!caps_supported()) {
6737                         log_debug("skip: capability library not installed");
6738                         exit(EXIT_SUCCESS);
6739                 }
6740
6741                 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6742                         die("failure: switch_userns");
6743
6744                 fd = openat(open_tree_fd, DIR3, O_CLOEXEC | O_DIRECTORY);
6745                 if (fd < 0)
6746                         die("failure: openat");
6747
6748                 exit(EXIT_SUCCESS);
6749         }
6750         if (wait_for_pid(pid)) {
6751                 log_stderr("failure: wait_for_pid");
6752                 goto out;
6753         }
6754
6755         /* if we delete the acls, the ls should fail because it's 700. */
6756         snprintf(t_buf, sizeof(t_buf), "%s/%s/%s/%s", t_mountpoint, T_DIR1, DIR1, DIR3);
6757         if (removexattr(t_buf, "system.posix_acl_access")) {
6758                 log_stderr("failure: removexattr");
6759                 goto out;
6760         }
6761
6762         pid = fork();
6763         if (pid < 0) {
6764                 log_stderr("failure: fork");
6765                 goto out;
6766         }
6767         if (pid == 0) {
6768                 int fd;
6769
6770                 if (!caps_supported()) {
6771                         log_debug("skip: capability library not installed");
6772                         exit(EXIT_SUCCESS);
6773                 }
6774
6775                 if (!switch_userns(attr.userns_fd, 100010, 100010, true))
6776                         die("failure: switch_userns");
6777
6778                 fd = openat(open_tree_fd, DIR3, O_CLOEXEC | O_DIRECTORY);
6779                 if (fd >= 0)
6780                         die("failure: openat");
6781
6782                 exit(EXIT_SUCCESS);
6783         }
6784         if (wait_for_pid(pid)) {
6785                 log_stderr("failure: wait_for_pid");
6786                 goto out;
6787         }
6788
6789         snprintf(t_buf, sizeof(t_buf), "%s/" T_DIR1 "/" DIR2, t_mountpoint);
6790         sys_umount2(t_buf, MNT_DETACH);
6791
6792         fret = 0;
6793         log_debug("Ran test");
6794 out:
6795         safe_close(attr.userns_fd);
6796         safe_close(dir1_fd);
6797         safe_close(open_tree_fd);
6798
6799         return fret;
6800 }
6801
6802 #ifdef HAVE_LIBURING_H
6803 static int io_uring_openat_with_creds(struct io_uring *ring, int dfd, const char *path, int cred_id,
6804                                       bool with_link, int *ret_cqe)
6805 {
6806         struct io_uring_cqe *cqe;
6807         struct io_uring_sqe *sqe;
6808         int ret, i, to_submit = 1;
6809
6810         if (with_link) {
6811                 sqe = io_uring_get_sqe(ring);
6812                 if (!sqe)
6813                         return log_error_errno(-EINVAL, EINVAL, "failure: io_uring_sqe");
6814                 io_uring_prep_nop(sqe);
6815                 sqe->flags |= IOSQE_IO_LINK;
6816                 sqe->user_data = 1;
6817                 to_submit++;
6818         }
6819
6820         sqe = io_uring_get_sqe(ring);
6821         if (!sqe)
6822                 return log_error_errno(-EINVAL, EINVAL, "failure: io_uring_sqe");
6823         io_uring_prep_openat(sqe, dfd, path, O_RDONLY | O_CLOEXEC, 0);
6824         sqe->user_data = 2;
6825
6826         if (cred_id != -1)
6827                 sqe->personality = cred_id;
6828
6829         ret = io_uring_submit(ring);
6830         if (ret != to_submit) {
6831                 log_stderr("failure: io_uring_submit");
6832                 goto out;
6833         }
6834
6835         for (i = 0; i < to_submit; i++) {
6836                 ret = io_uring_wait_cqe(ring, &cqe);
6837                 if (ret < 0) {
6838                         log_stderr("failure: io_uring_wait_cqe");
6839                         goto out;
6840                 }
6841
6842                 ret = cqe->res;
6843                 /*
6844                  * Make sure caller can identify that this is a proper io_uring
6845                  * failure and not some earlier error.
6846                  */
6847                 if (ret_cqe)
6848                         *ret_cqe = ret;
6849                 io_uring_cqe_seen(ring, cqe);
6850         }
6851         log_debug("Ran test");
6852 out:
6853         return ret;
6854 }
6855
6856 static int io_uring(void)
6857 {
6858         int fret = -1;
6859         int file1_fd = -EBADF;
6860         struct io_uring *ring;
6861         int cred_id, ret, ret_cqe;
6862         pid_t pid;
6863
6864         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
6865                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
6866         if (!ring)
6867                 return log_errno(-1, "failure: io_uring_queue_init");
6868
6869         ret = io_uring_queue_init(8, ring, 0);
6870         if (ret) {
6871                 log_stderr("failure: io_uring_queue_init");
6872                 goto out_unmap;
6873         }
6874
6875         ret = io_uring_register_personality(ring);
6876         if (ret < 0) {
6877                 fret = 0;
6878                 goto out_unmap; /* personalities not supported */
6879         }
6880         cred_id = ret;
6881
6882         /* create file only owner can open */
6883         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
6884         if (file1_fd < 0) {
6885                 log_stderr("failure: openat");
6886                 goto out;
6887         }
6888         if (fchown(file1_fd, 0, 0)) {
6889                 log_stderr("failure: fchown");
6890                 goto out;
6891         }
6892         if (fchmod(file1_fd, 0600)) {
6893                 log_stderr("failure: fchmod");
6894                 goto out;
6895         }
6896         safe_close(file1_fd);
6897
6898         pid = fork();
6899         if (pid < 0) {
6900                 log_stderr("failure: fork");
6901                 goto out;
6902         }
6903         if (pid == 0) {
6904                 /* Verify we can open it with our current credentials. */
6905                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6906                                                       -1, false, NULL);
6907                 if (file1_fd < 0)
6908                         die("failure: io_uring_open_file");
6909
6910                 exit(EXIT_SUCCESS);
6911         }
6912         if (wait_for_pid(pid)) {
6913                 log_stderr("failure: wait_for_pid");
6914                 goto out;
6915         }
6916
6917         pid = fork();
6918         if (pid < 0) {
6919                 log_stderr("failure: fork");
6920                 goto out;
6921         }
6922         if (pid == 0) {
6923                 if (!switch_ids(1000, 1000))
6924                         die("failure: switch_ids");
6925
6926                 /* Verify we can't open it with our current credentials. */
6927                 ret_cqe = 0;
6928                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6929                                                       -1, false, &ret_cqe);
6930                 if (file1_fd >= 0)
6931                         die("failure: io_uring_open_file");
6932                 if (ret_cqe == 0)
6933                         die("failure: non-open() related io_uring_open_file failure %d", ret_cqe);
6934                 if (ret_cqe != -EACCES)
6935                         die("failure: errno(%d)", abs(ret_cqe));
6936
6937                 exit(EXIT_SUCCESS);
6938         }
6939         if (wait_for_pid(pid)) {
6940                 log_stderr("failure: wait_for_pid");
6941                 goto out;
6942         }
6943
6944         pid = fork();
6945         if (pid < 0) {
6946                 log_stderr("failure: fork");
6947                 goto out;
6948         }
6949         if (pid == 0) {
6950                 if (!switch_ids(1000, 1000))
6951                         die("failure: switch_ids");
6952
6953                 /* Verify we can open it with the registered credentials. */
6954                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6955                                                       cred_id, false, NULL);
6956                 if (file1_fd < 0)
6957                         die("failure: io_uring_open_file");
6958
6959                 /* Verify we can open it with the registered credentials and as
6960                  * a link.
6961                  */
6962                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
6963                                                       cred_id, true, NULL);
6964                 if (file1_fd < 0)
6965                         die("failure: io_uring_open_file");
6966
6967                 exit(EXIT_SUCCESS);
6968         }
6969         if (wait_for_pid(pid)) {
6970                 log_stderr("failure: wait_for_pid");
6971                 goto out;
6972         }
6973
6974         fret = 0;
6975         log_debug("Ran test");
6976 out:
6977         ret = io_uring_unregister_personality(ring, cred_id);
6978         if (ret)
6979                 log_stderr("failure: io_uring_unregister_personality");
6980
6981 out_unmap:
6982         munmap(ring, sizeof(struct io_uring));
6983
6984         safe_close(file1_fd);
6985
6986         return fret;
6987 }
6988
6989 static int io_uring_userns(void)
6990 {
6991         int fret = -1;
6992         int file1_fd = -EBADF, userns_fd = -EBADF;
6993         struct io_uring *ring;
6994         int cred_id, ret, ret_cqe;
6995         pid_t pid;
6996
6997         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
6998                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
6999         if (!ring)
7000                 return log_errno(-1, "failure: io_uring_queue_init");
7001
7002         ret = io_uring_queue_init(8, ring, 0);
7003         if (ret) {
7004                 log_stderr("failure: io_uring_queue_init");
7005                 goto out_unmap;
7006         }
7007
7008         ret = io_uring_register_personality(ring);
7009         if (ret < 0) {
7010                 fret = 0;
7011                 goto out_unmap; /* personalities not supported */
7012         }
7013         cred_id = ret;
7014
7015         /* create file only owner can open */
7016         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7017         if (file1_fd < 0) {
7018                 log_stderr("failure: openat");
7019                 goto out;
7020         }
7021         if (fchown(file1_fd, 0, 0)) {
7022                 log_stderr("failure: fchown");
7023                 goto out;
7024         }
7025         if (fchmod(file1_fd, 0600)) {
7026                 log_stderr("failure: fchmod");
7027                 goto out;
7028         }
7029         safe_close(file1_fd);
7030
7031         userns_fd = get_userns_fd(0, 10000, 10000);
7032         if (userns_fd < 0) {
7033                 log_stderr("failure: get_userns_fd");
7034                 goto out;
7035         }
7036
7037         pid = fork();
7038         if (pid < 0) {
7039                 log_stderr("failure: fork");
7040                 goto out;
7041         }
7042         if (pid == 0) {
7043                 /* Verify we can open it with our current credentials. */
7044                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7045                                                       -1, false, NULL);
7046                 if (file1_fd < 0)
7047                         die("failure: io_uring_open_file");
7048
7049                 exit(EXIT_SUCCESS);
7050         }
7051         if (wait_for_pid(pid)) {
7052                 log_stderr("failure: wait_for_pid");
7053                 goto out;
7054         }
7055
7056         pid = fork();
7057         if (pid < 0) {
7058                 log_stderr("failure: fork");
7059                 goto out;
7060         }
7061         if (pid == 0) {
7062                 if (!switch_userns(userns_fd, 0, 0, false))
7063                         die("failure: switch_userns");
7064
7065                 /* Verify we can't open it with our current credentials. */
7066                 ret_cqe = 0;
7067                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7068                                                       -1, false, &ret_cqe);
7069                 if (file1_fd >= 0)
7070                         die("failure: io_uring_open_file");
7071                 if (ret_cqe == 0)
7072                         die("failure: non-open() related io_uring_open_file failure");
7073                 if (ret_cqe != -EACCES)
7074                         die("failure: errno(%d)", abs(ret_cqe));
7075
7076                 exit(EXIT_SUCCESS);
7077         }
7078         if (wait_for_pid(pid)) {
7079                 log_stderr("failure: wait_for_pid");
7080                 goto out;
7081         }
7082
7083         pid = fork();
7084         if (pid < 0) {
7085                 log_stderr("failure: fork");
7086                 goto out;
7087         }
7088         if (pid == 0) {
7089                 if (!switch_userns(userns_fd, 0, 0, false))
7090                         die("failure: switch_userns");
7091
7092                 /* Verify we can open it with the registered credentials. */
7093                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7094                                                       cred_id, false, NULL);
7095                 if (file1_fd < 0)
7096                         die("failure: io_uring_open_file");
7097
7098                 /* Verify we can open it with the registered credentials and as
7099                  * a link.
7100                  */
7101                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7102                                                       cred_id, true, NULL);
7103                 if (file1_fd < 0)
7104                         die("failure: io_uring_open_file");
7105
7106                 exit(EXIT_SUCCESS);
7107         }
7108         if (wait_for_pid(pid)) {
7109                 log_stderr("failure: wait_for_pid");
7110                 goto out;
7111         }
7112
7113         fret = 0;
7114         log_debug("Ran test");
7115 out:
7116         ret = io_uring_unregister_personality(ring, cred_id);
7117         if (ret)
7118                 log_stderr("failure: io_uring_unregister_personality");
7119
7120 out_unmap:
7121         munmap(ring, sizeof(struct io_uring));
7122
7123         safe_close(file1_fd);
7124         safe_close(userns_fd);
7125
7126         return fret;
7127 }
7128
7129 static int io_uring_idmapped(void)
7130 {
7131         int fret = -1;
7132         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7133         struct io_uring *ring;
7134         struct mount_attr attr = {
7135                 .attr_set = MOUNT_ATTR_IDMAP,
7136         };
7137         int cred_id, ret;
7138         pid_t pid;
7139
7140         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7141                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7142         if (!ring)
7143                 return log_errno(-1, "failure: io_uring_queue_init");
7144
7145         ret = io_uring_queue_init(8, ring, 0);
7146         if (ret) {
7147                 log_stderr("failure: io_uring_queue_init");
7148                 goto out_unmap;
7149         }
7150
7151         ret = io_uring_register_personality(ring);
7152         if (ret < 0) {
7153                 fret = 0;
7154                 goto out_unmap; /* personalities not supported */
7155         }
7156         cred_id = ret;
7157
7158         /* create file only owner can open */
7159         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7160         if (file1_fd < 0) {
7161                 log_stderr("failure: openat");
7162                 goto out;
7163         }
7164         if (fchown(file1_fd, 0, 0)) {
7165                 log_stderr("failure: fchown");
7166                 goto out;
7167         }
7168         if (fchmod(file1_fd, 0600)) {
7169                 log_stderr("failure: fchmod");
7170                 goto out;
7171         }
7172         safe_close(file1_fd);
7173
7174         /* Changing mount properties on a detached mount. */
7175         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
7176         if (attr.userns_fd < 0)
7177                 return log_errno(-1, "failure: create user namespace");
7178
7179         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7180                                      AT_EMPTY_PATH |
7181                                      AT_NO_AUTOMOUNT |
7182                                      AT_SYMLINK_NOFOLLOW |
7183                                      OPEN_TREE_CLOEXEC |
7184                                      OPEN_TREE_CLONE);
7185         if (open_tree_fd < 0)
7186                 return log_errno(-1, "failure: create detached mount");
7187
7188         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7189                 return log_errno(-1, "failure: set mount attributes");
7190
7191         pid = fork();
7192         if (pid < 0) {
7193                 log_stderr("failure: fork");
7194                 goto out;
7195         }
7196         if (pid == 0) {
7197                 if (!switch_ids(10000, 10000))
7198                         die("failure: switch_ids");
7199
7200                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7201                                                       -1, false, NULL);
7202                 if (file1_fd < 0)
7203                         die("failure: io_uring_open_file");
7204
7205                 exit(EXIT_SUCCESS);
7206         }
7207         if (wait_for_pid(pid)) {
7208                 log_stderr("failure: wait_for_pid");
7209                 goto out;
7210         }
7211
7212         pid = fork();
7213         if (pid < 0) {
7214                 log_stderr("failure: fork");
7215                 goto out;
7216         }
7217         if (pid == 0) {
7218                 if (!switch_ids(10001, 10001))
7219                         die("failure: switch_ids");
7220
7221                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7222                                                       cred_id, false, NULL);
7223                 if (file1_fd < 0)
7224                         die("failure: io_uring_open_file");
7225
7226                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7227                                                       cred_id, true, NULL);
7228                 if (file1_fd < 0)
7229                         die("failure: io_uring_open_file");
7230
7231                 exit(EXIT_SUCCESS);
7232         }
7233         if (wait_for_pid(pid)) {
7234                 log_stderr("failure: wait_for_pid");
7235                 goto out;
7236         }
7237
7238         fret = 0;
7239         log_debug("Ran test");
7240 out:
7241         ret = io_uring_unregister_personality(ring, cred_id);
7242         if (ret)
7243                 log_stderr("failure: io_uring_unregister_personality");
7244
7245 out_unmap:
7246         munmap(ring, sizeof(struct io_uring));
7247
7248         safe_close(attr.userns_fd);
7249         safe_close(file1_fd);
7250         safe_close(open_tree_fd);
7251
7252         return fret;
7253 }
7254
7255 /*
7256  * Create an idmapped mount where the we leave the owner of the file unmapped.
7257  * In no circumstances, even with recorded credentials can it be allowed to
7258  * open the file.
7259  */
7260 static int io_uring_idmapped_unmapped(void)
7261 {
7262         int fret = -1;
7263         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7264         struct io_uring *ring;
7265         struct mount_attr attr = {
7266                 .attr_set = MOUNT_ATTR_IDMAP,
7267         };
7268         int cred_id, ret, ret_cqe;
7269         pid_t pid;
7270
7271         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7272                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7273         if (!ring)
7274                 return log_errno(-1, "failure: io_uring_queue_init");
7275
7276         ret = io_uring_queue_init(8, ring, 0);
7277         if (ret) {
7278                 log_stderr("failure: io_uring_queue_init");
7279                 goto out_unmap;
7280         }
7281
7282         ret = io_uring_register_personality(ring);
7283         if (ret < 0) {
7284                 fret = 0;
7285                 goto out_unmap; /* personalities not supported */
7286         }
7287         cred_id = ret;
7288
7289         /* create file only owner can open */
7290         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7291         if (file1_fd < 0) {
7292                 log_stderr("failure: openat");
7293                 goto out;
7294         }
7295         if (fchown(file1_fd, 0, 0)) {
7296                 log_stderr("failure: fchown");
7297                 goto out;
7298         }
7299         if (fchmod(file1_fd, 0600)) {
7300                 log_stderr("failure: fchmod");
7301                 goto out;
7302         }
7303         safe_close(file1_fd);
7304
7305         /* Changing mount properties on a detached mount. */
7306         attr.userns_fd  = get_userns_fd(1, 10000, 10000);
7307         if (attr.userns_fd < 0)
7308                 return log_errno(-1, "failure: create user namespace");
7309
7310         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7311                                      AT_EMPTY_PATH |
7312                                      AT_NO_AUTOMOUNT |
7313                                      AT_SYMLINK_NOFOLLOW |
7314                                      OPEN_TREE_CLOEXEC |
7315                                      OPEN_TREE_CLONE);
7316         if (open_tree_fd < 0)
7317                 return log_errno(-1, "failure: create detached mount");
7318
7319         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7320                 return log_errno(-1, "failure: set mount attributes");
7321
7322         pid = fork();
7323         if (pid < 0) {
7324                 log_stderr("failure: fork");
7325                 goto out;
7326         }
7327         if (pid == 0) {
7328                 if (!switch_ids(10000, 10000))
7329                         die("failure: switch_ids");
7330
7331                 ret_cqe = 0;
7332                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7333                                                       cred_id, false, &ret_cqe);
7334                 if (file1_fd >= 0)
7335                         die("failure: io_uring_open_file");
7336                 if (ret_cqe == 0)
7337                         die("failure: non-open() related io_uring_open_file failure");
7338                 if (ret_cqe != -EACCES)
7339                         die("failure: errno(%d)", abs(ret_cqe));
7340
7341                 ret_cqe = 0;
7342                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7343                                                       cred_id, true, &ret_cqe);
7344                 if (file1_fd >= 0)
7345                         die("failure: io_uring_open_file");
7346                 if (ret_cqe == 0)
7347                         die("failure: non-open() related io_uring_open_file failure");
7348                 if (ret_cqe != -EACCES)
7349                         die("failure: errno(%d)", abs(ret_cqe));
7350
7351                 exit(EXIT_SUCCESS);
7352         }
7353         if (wait_for_pid(pid)) {
7354                 log_stderr("failure: wait_for_pid");
7355                 goto out;
7356         }
7357
7358         fret = 0;
7359         log_debug("Ran test");
7360 out:
7361         ret = io_uring_unregister_personality(ring, cred_id);
7362         if (ret)
7363                 log_stderr("failure: io_uring_unregister_personality");
7364
7365 out_unmap:
7366         munmap(ring, sizeof(struct io_uring));
7367
7368         safe_close(attr.userns_fd);
7369         safe_close(file1_fd);
7370         safe_close(open_tree_fd);
7371
7372         return fret;
7373 }
7374
7375 static int io_uring_idmapped_userns(void)
7376 {
7377         int fret = -1;
7378         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7379         struct io_uring *ring;
7380         struct mount_attr attr = {
7381                 .attr_set = MOUNT_ATTR_IDMAP,
7382         };
7383         int cred_id, ret, ret_cqe;
7384         pid_t pid;
7385
7386         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7387                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7388         if (!ring)
7389                 return log_errno(-1, "failure: io_uring_queue_init");
7390
7391         ret = io_uring_queue_init(8, ring, 0);
7392         if (ret) {
7393                 log_stderr("failure: io_uring_queue_init");
7394                 goto out_unmap;
7395         }
7396
7397         ret = io_uring_register_personality(ring);
7398         if (ret < 0) {
7399                 fret = 0;
7400                 goto out_unmap; /* personalities not supported */
7401         }
7402         cred_id = ret;
7403
7404         /* create file only owner can open */
7405         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7406         if (file1_fd < 0) {
7407                 log_stderr("failure: openat");
7408                 goto out;
7409         }
7410         if (fchown(file1_fd, 0, 0)) {
7411                 log_stderr("failure: fchown");
7412                 goto out;
7413         }
7414         if (fchmod(file1_fd, 0600)) {
7415                 log_stderr("failure: fchmod");
7416                 goto out;
7417         }
7418         safe_close(file1_fd);
7419
7420         /* Changing mount properties on a detached mount. */
7421         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
7422         if (attr.userns_fd < 0)
7423                 return log_errno(-1, "failure: create user namespace");
7424
7425         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7426                                      AT_EMPTY_PATH |
7427                                      AT_NO_AUTOMOUNT |
7428                                      AT_SYMLINK_NOFOLLOW |
7429                                      OPEN_TREE_CLOEXEC |
7430                                      OPEN_TREE_CLONE);
7431         if (open_tree_fd < 0)
7432                 return log_errno(-1, "failure: create detached mount");
7433
7434         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7435                 return log_errno(-1, "failure: set mount attributes");
7436
7437         pid = fork();
7438         if (pid < 0) {
7439                 log_stderr("failure: fork");
7440                 goto out;
7441         }
7442         if (pid == 0) {
7443                 if (!switch_userns(attr.userns_fd, 0, 0, false))
7444                         die("failure: switch_userns");
7445
7446                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7447                                                       -1, false, NULL);
7448                 if (file1_fd < 0)
7449                         die("failure: io_uring_open_file");
7450
7451                 exit(EXIT_SUCCESS);
7452         }
7453         if (wait_for_pid(pid)) {
7454                 log_stderr("failure: wait_for_pid");
7455                 goto out;
7456         }
7457
7458         pid = fork();
7459         if (pid < 0) {
7460                 log_stderr("failure: fork");
7461                 goto out;
7462         }
7463         if (pid == 0) {
7464                 if (!caps_supported()) {
7465                         log_debug("skip: capability library not installed");
7466                         exit(EXIT_SUCCESS);
7467                 }
7468
7469                 if (!switch_userns(attr.userns_fd, 1000, 1000, true))
7470                         die("failure: switch_userns");
7471
7472                 ret_cqe = 0;
7473                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7474                                                       -1, false, &ret_cqe);
7475                 if (file1_fd >= 0)
7476                         die("failure: io_uring_open_file");
7477                 if (ret_cqe == 0)
7478                         die("failure: non-open() related io_uring_open_file failure");
7479                 if (ret_cqe != -EACCES)
7480                         die("failure: errno(%d)", abs(ret_cqe));
7481
7482                 ret_cqe = 0;
7483                 file1_fd = io_uring_openat_with_creds(ring, t_dir1_fd, FILE1,
7484                                                       -1, true, &ret_cqe);
7485                 if (file1_fd >= 0)
7486                         die("failure: io_uring_open_file");
7487                 if (ret_cqe == 0)
7488                         die("failure: non-open() related io_uring_open_file failure");
7489                 if (ret_cqe != -EACCES)
7490                         die("failure: errno(%d)", abs(ret_cqe));
7491
7492                 ret_cqe = 0;
7493                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7494                                                       -1, false, &ret_cqe);
7495                 if (file1_fd >= 0)
7496                         die("failure: io_uring_open_file");
7497                 if (ret_cqe == 0)
7498                         die("failure: non-open() related io_uring_open_file failure");
7499                 if (ret_cqe != -EACCES)
7500                         die("failure: errno(%d)", abs(ret_cqe));
7501
7502                 ret_cqe = 0;
7503                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7504                                                       -1, true, &ret_cqe);
7505                 if (file1_fd >= 0)
7506                         die("failure: io_uring_open_file");
7507                 if (ret_cqe == 0)
7508                         die("failure: non-open() related io_uring_open_file failure");
7509                 if (ret_cqe != -EACCES)
7510                         die("failure: errno(%d)", abs(ret_cqe));
7511
7512                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7513                                                       cred_id, false, NULL);
7514                 if (file1_fd < 0)
7515                         die("failure: io_uring_open_file");
7516
7517                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7518                                                       cred_id, true, NULL);
7519                 if (file1_fd < 0)
7520                         die("failure: io_uring_open_file");
7521
7522                 exit(EXIT_SUCCESS);
7523         }
7524         if (wait_for_pid(pid)) {
7525                 log_stderr("failure: wait_for_pid");
7526                 goto out;
7527         }
7528
7529         fret = 0;
7530         log_debug("Ran test");
7531 out:
7532         ret = io_uring_unregister_personality(ring, cred_id);
7533         if (ret)
7534                 log_stderr("failure: io_uring_unregister_personality");
7535
7536 out_unmap:
7537         munmap(ring, sizeof(struct io_uring));
7538
7539         safe_close(attr.userns_fd);
7540         safe_close(file1_fd);
7541         safe_close(open_tree_fd);
7542
7543         return fret;
7544 }
7545
7546 static int io_uring_idmapped_unmapped_userns(void)
7547 {
7548         int fret = -1;
7549         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7550         struct io_uring *ring;
7551         struct mount_attr attr = {
7552                 .attr_set = MOUNT_ATTR_IDMAP,
7553         };
7554         int cred_id, ret, ret_cqe;
7555         pid_t pid;
7556
7557         ring = mmap(0, sizeof(struct io_uring), PROT_READ|PROT_WRITE,
7558                    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
7559         if (!ring)
7560                 return log_errno(-1, "failure: io_uring_queue_init");
7561
7562         ret = io_uring_queue_init(8, ring, 0);
7563         if (ret) {
7564                 log_stderr("failure: io_uring_queue_init");
7565                 goto out_unmap;
7566         }
7567
7568         ret = io_uring_register_personality(ring);
7569         if (ret < 0) {
7570                 fret = 0;
7571                 goto out_unmap; /* personalities not supported */
7572         }
7573         cred_id = ret;
7574
7575         /* create file only owner can open */
7576         file1_fd = openat(t_dir1_fd, FILE1, O_RDONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
7577         if (file1_fd < 0) {
7578                 log_stderr("failure: openat");
7579                 goto out;
7580         }
7581         if (fchown(file1_fd, 0, 0)) {
7582                 log_stderr("failure: fchown");
7583                 goto out;
7584         }
7585         if (fchmod(file1_fd, 0600)) {
7586                 log_stderr("failure: fchmod");
7587                 goto out;
7588         }
7589         safe_close(file1_fd);
7590
7591         /* Changing mount properties on a detached mount. */
7592         attr.userns_fd  = get_userns_fd(1, 10000, 10000);
7593         if (attr.userns_fd < 0)
7594                 return log_errno(-1, "failure: create user namespace");
7595
7596         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7597                                      AT_EMPTY_PATH |
7598                                      AT_NO_AUTOMOUNT |
7599                                      AT_SYMLINK_NOFOLLOW |
7600                                      OPEN_TREE_CLOEXEC |
7601                                      OPEN_TREE_CLONE);
7602         if (open_tree_fd < 0)
7603                 return log_errno(-1, "failure: create detached mount");
7604
7605         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)))
7606                 return log_errno(-1, "failure: set mount attributes");
7607
7608         pid = fork();
7609         if (pid < 0) {
7610                 log_stderr("failure: fork");
7611                 goto out;
7612         }
7613         if (pid == 0) {
7614                 if (!caps_supported()) {
7615                         log_debug("skip: capability library not installed");
7616                         exit(EXIT_SUCCESS);
7617                 }
7618
7619                 if (!switch_userns(attr.userns_fd, 10000, 10000, true))
7620                         die("failure: switch_ids");
7621
7622                 ret_cqe = 0;
7623                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7624                                                       cred_id, false, &ret_cqe);
7625                 if (file1_fd >= 0)
7626                         die("failure: io_uring_open_file");
7627                 if (ret_cqe == 0)
7628                         die("failure: non-open() related io_uring_open_file failure");
7629                 if (ret_cqe != -EACCES)
7630                         die("failure: errno(%d)", abs(ret_cqe));
7631
7632                 ret_cqe = 0;
7633                 file1_fd = io_uring_openat_with_creds(ring, open_tree_fd, FILE1,
7634                                                       cred_id, true, &ret_cqe);
7635                 if (file1_fd >= 0)
7636                         die("failure: io_uring_open_file");
7637                 if (ret_cqe == 0)
7638                         die("failure: non-open() related io_uring_open_file failure");
7639                 if (ret_cqe != -EACCES)
7640                         die("failure: errno(%d)", abs(ret_cqe));
7641
7642                 exit(EXIT_SUCCESS);
7643         }
7644         if (wait_for_pid(pid)) {
7645                 log_stderr("failure: wait_for_pid");
7646                 goto out;
7647         }
7648
7649         fret = 0;
7650         log_debug("Ran test");
7651 out:
7652         ret = io_uring_unregister_personality(ring, cred_id);
7653         if (ret)
7654                 log_stderr("failure: io_uring_unregister_personality");
7655
7656 out_unmap:
7657         munmap(ring, sizeof(struct io_uring));
7658
7659         safe_close(attr.userns_fd);
7660         safe_close(file1_fd);
7661         safe_close(open_tree_fd);
7662
7663         return fret;
7664 }
7665 #endif /* HAVE_LIBURING_H */
7666
7667 /* The following tests are concerned with setgid inheritance. These can be
7668  * filesystem type specific. For xfs, if a new file or directory is created
7669  * within a setgid directory and irix_sgid_inhiert is set then inherit the
7670  * setgid bit if the caller is in the group of the directory.
7671  */
7672 static int setgid_create(void)
7673 {
7674         int fret = -1;
7675         int file1_fd = -EBADF;
7676         pid_t pid;
7677
7678         if (!caps_supported())
7679                 return 0;
7680
7681         if (fchmod(t_dir1_fd, S_IRUSR |
7682                               S_IWUSR |
7683                               S_IRGRP |
7684                               S_IWGRP |
7685                               S_IROTH |
7686                               S_IWOTH |
7687                               S_IXUSR |
7688                               S_IXGRP |
7689                               S_IXOTH |
7690                               S_ISGID), 0) {
7691                 log_stderr("failure: fchmod");
7692                 goto out;
7693         }
7694
7695         /* Verify that the setgid bit got raised. */
7696         if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7697                 log_stderr("failure: is_setgid");
7698                 goto out;
7699         }
7700
7701         pid = fork();
7702         if (pid < 0) {
7703                 log_stderr("failure: fork");
7704                 goto out;
7705         }
7706         if (pid == 0) {
7707                 /* create regular file via open() */
7708                 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7709                 if (file1_fd < 0)
7710                         die("failure: create");
7711
7712                 /* We're capable_wrt_inode_uidgid() and also our fsgid matches
7713                  * the directories gid.
7714                  */
7715                 if (!is_setgid(t_dir1_fd, FILE1, 0))
7716                         die("failure: is_setgid");
7717
7718                 /* create directory */
7719                 if (mkdirat(t_dir1_fd, DIR1, 0000))
7720                         die("failure: create");
7721
7722                 /* Directories always inherit the setgid bit. */
7723                 if (!is_setgid(t_dir1_fd, DIR1, 0))
7724                         die("failure: is_setgid");
7725
7726                 if (unlinkat(t_dir1_fd, FILE1, 0))
7727                         die("failure: delete");
7728
7729                 if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
7730                         die("failure: delete");
7731
7732                 exit(EXIT_SUCCESS);
7733         }
7734         if (wait_for_pid(pid))
7735                 goto out;
7736
7737         pid = fork();
7738         if (pid < 0) {
7739                 log_stderr("failure: fork");
7740                 goto out;
7741         }
7742         if (pid == 0) {
7743                 if (!switch_ids(0, 10000))
7744                         die("failure: switch_ids");
7745
7746                 if (!caps_down())
7747                         die("failure: caps_down");
7748
7749                 /* create regular file via open() */
7750                 file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7751                 if (file1_fd < 0)
7752                         die("failure: create");
7753
7754                 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
7755                  * bit needs to be stripped.
7756                  */
7757                 if (is_setgid(t_dir1_fd, FILE1, 0))
7758                         die("failure: is_setgid");
7759
7760                 /* create directory */
7761                 if (mkdirat(t_dir1_fd, DIR1, 0000))
7762                         die("failure: create");
7763
7764                 if (xfs_irix_sgid_inherit_enabled()) {
7765                         /* We're not in_group_p(). */
7766                         if (is_setgid(t_dir1_fd, DIR1, 0))
7767                                 die("failure: is_setgid");
7768                 } else {
7769                         /* Directories always inherit the setgid bit. */
7770                         if (!is_setgid(t_dir1_fd, DIR1, 0))
7771                                 die("failure: is_setgid");
7772                 }
7773
7774                 exit(EXIT_SUCCESS);
7775         }
7776         if (wait_for_pid(pid))
7777                 goto out;
7778
7779         fret = 0;
7780         log_debug("Ran test");
7781 out:
7782         safe_close(file1_fd);
7783
7784         return fret;
7785 }
7786
7787 static int setgid_create_idmapped(void)
7788 {
7789         int fret = -1;
7790         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7791         struct mount_attr attr = {
7792                 .attr_set = MOUNT_ATTR_IDMAP,
7793         };
7794         pid_t pid;
7795
7796         if (!caps_supported())
7797                 return 0;
7798
7799         if (fchmod(t_dir1_fd, S_IRUSR |
7800                               S_IWUSR |
7801                               S_IRGRP |
7802                               S_IWGRP |
7803                               S_IROTH |
7804                               S_IWOTH |
7805                               S_IXUSR |
7806                               S_IXGRP |
7807                               S_IXOTH |
7808                               S_ISGID), 0) {
7809                 log_stderr("failure: fchmod");
7810                 goto out;
7811         }
7812
7813         /* Verify that the sid bits got raised. */
7814         if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7815                 log_stderr("failure: is_setgid");
7816                 goto out;
7817         }
7818
7819         /* Changing mount properties on a detached mount. */
7820         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
7821         if (attr.userns_fd < 0) {
7822                 log_stderr("failure: get_userns_fd");
7823                 goto out;
7824         }
7825
7826         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7827                                      AT_EMPTY_PATH |
7828                                      AT_NO_AUTOMOUNT |
7829                                      AT_SYMLINK_NOFOLLOW |
7830                                      OPEN_TREE_CLOEXEC |
7831                                      OPEN_TREE_CLONE);
7832         if (open_tree_fd < 0) {
7833                 log_stderr("failure: sys_open_tree");
7834                 goto out;
7835         }
7836
7837         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
7838                 log_stderr("failure: sys_mount_setattr");
7839                 goto out;
7840         }
7841
7842         pid = fork();
7843         if (pid < 0) {
7844                 log_stderr("failure: fork");
7845                 goto out;
7846         }
7847         if (pid == 0) {
7848                 if (!switch_ids(10000, 11000))
7849                         die("failure: switch fsids");
7850
7851                 /* create regular file via open() */
7852                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7853                 if (file1_fd < 0)
7854                         die("failure: create");
7855
7856                 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
7857                  * bit needs to be stripped.
7858                  */
7859                 if (is_setgid(open_tree_fd, FILE1, 0))
7860                         die("failure: is_setgid");
7861
7862                 /* create directory */
7863                 if (mkdirat(open_tree_fd, DIR1, 0000))
7864                         die("failure: create");
7865
7866                 if (xfs_irix_sgid_inherit_enabled()) {
7867                         /* We're not in_group_p(). */
7868                         if (is_setgid(open_tree_fd, DIR1, 0))
7869                                 die("failure: is_setgid");
7870                 } else {
7871                         /* Directories always inherit the setgid bit. */
7872                         if (!is_setgid(open_tree_fd, DIR1, 0))
7873                                 die("failure: is_setgid");
7874                 }
7875
7876                 exit(EXIT_SUCCESS);
7877         }
7878         if (wait_for_pid(pid))
7879                 goto out;
7880
7881         fret = 0;
7882         log_debug("Ran test");
7883 out:
7884         safe_close(attr.userns_fd);
7885         safe_close(file1_fd);
7886         safe_close(open_tree_fd);
7887
7888         return fret;
7889 }
7890
7891 static int setgid_create_idmapped_in_userns(void)
7892 {
7893         int fret = -1;
7894         int file1_fd = -EBADF, open_tree_fd = -EBADF;
7895         struct mount_attr attr = {
7896                 .attr_set = MOUNT_ATTR_IDMAP,
7897         };
7898         pid_t pid;
7899
7900         if (!caps_supported())
7901                 return 0;
7902
7903         if (fchmod(t_dir1_fd, S_IRUSR |
7904                               S_IWUSR |
7905                               S_IRGRP |
7906                               S_IWGRP |
7907                               S_IROTH |
7908                               S_IWOTH |
7909                               S_IXUSR |
7910                               S_IXGRP |
7911                               S_IXOTH |
7912                               S_ISGID), 0) {
7913                 log_stderr("failure: fchmod");
7914                 goto out;
7915         }
7916
7917         /* Verify that the sid bits got raised. */
7918         if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
7919                 log_stderr("failure: is_setgid");
7920                 goto out;
7921         }
7922
7923         /* Changing mount properties on a detached mount. */
7924         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
7925         if (attr.userns_fd < 0) {
7926                 log_stderr("failure: get_userns_fd");
7927                 goto out;
7928         }
7929
7930         open_tree_fd = sys_open_tree(t_dir1_fd, "",
7931                                      AT_EMPTY_PATH |
7932                                      AT_NO_AUTOMOUNT |
7933                                      AT_SYMLINK_NOFOLLOW |
7934                                      OPEN_TREE_CLOEXEC |
7935                                      OPEN_TREE_CLONE);
7936         if (open_tree_fd < 0) {
7937                 log_stderr("failure: sys_open_tree");
7938                 goto out;
7939         }
7940
7941         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
7942                 log_stderr("failure: sys_mount_setattr");
7943                 goto out;
7944         }
7945
7946         pid = fork();
7947         if (pid < 0) {
7948                 log_stderr("failure: fork");
7949                 goto out;
7950         }
7951         if (pid == 0) {
7952                 if (!switch_userns(attr.userns_fd, 0, 0, false))
7953                         die("failure: switch_userns");
7954
7955                 /* create regular file via open() */
7956                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
7957                 if (file1_fd < 0)
7958                         die("failure: create");
7959
7960                 /* We're in_group_p() and capable_wrt_inode_uidgid() so setgid
7961                  * bit needs to be set.
7962                  */
7963                 if (!is_setgid(open_tree_fd, FILE1, 0))
7964                         die("failure: is_setgid");
7965
7966                 /* create directory */
7967                 if (mkdirat(open_tree_fd, DIR1, 0000))
7968                         die("failure: create");
7969
7970                 /* Directories always inherit the setgid bit. */
7971                 if (!is_setgid(open_tree_fd, DIR1, 0))
7972                         die("failure: is_setgid");
7973
7974                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
7975                         die("failure: check ownership");
7976
7977                 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
7978                         die("failure: check ownership");
7979
7980                 if (unlinkat(open_tree_fd, FILE1, 0))
7981                         die("failure: delete");
7982
7983                 if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
7984                         die("failure: delete");
7985
7986                 exit(EXIT_SUCCESS);
7987         }
7988         if (wait_for_pid(pid))
7989                 goto out;
7990
7991         if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
7992                 log_stderr("failure: fchownat");
7993                 goto out;
7994         }
7995
7996         if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
7997                 log_stderr("failure: fchownat");
7998                 goto out;
7999         }
8000
8001         pid = fork();
8002         if (pid < 0) {
8003                 log_stderr("failure: fork");
8004                 goto out;
8005         }
8006         if (pid == 0) {
8007                 if (!caps_supported()) {
8008                         log_debug("skip: capability library not installed");
8009                         exit(EXIT_SUCCESS);
8010                 }
8011
8012                 if (!switch_userns(attr.userns_fd, 0, 0, true))
8013                         die("failure: switch_userns");
8014
8015                 /* create regular file via open() */
8016                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
8017                 if (file1_fd < 0)
8018                         die("failure: create");
8019
8020                 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
8021                  * bit needs to be stripped.
8022                  */
8023                 if (is_setgid(open_tree_fd, FILE1, 0))
8024                         die("failure: is_setgid");
8025
8026                 /* create directory */
8027                 if (mkdirat(open_tree_fd, DIR1, 0000))
8028                         die("failure: create");
8029
8030                 if (xfs_irix_sgid_inherit_enabled()) {
8031                         /* We're not in_group_p(). */
8032                         if (is_setgid(open_tree_fd, DIR1, 0))
8033                                 die("failure: is_setgid");
8034                 } else {
8035                         /* Directories always inherit the setgid bit. */
8036                         if (!is_setgid(open_tree_fd, DIR1, 0))
8037                                 die("failure: is_setgid");
8038                 }
8039
8040                 /* Files and directories created in setgid directories inherit
8041                  * the i_gid of the parent directory.
8042                  */
8043                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8044                         die("failure: check ownership");
8045
8046                 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 1000))
8047                         die("failure: check ownership");
8048
8049                 if (unlinkat(open_tree_fd, FILE1, 0))
8050                         die("failure: delete");
8051
8052                 if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
8053                         die("failure: delete");
8054
8055                 exit(EXIT_SUCCESS);
8056         }
8057         if (wait_for_pid(pid))
8058                 goto out;
8059
8060         if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8061                 log_stderr("failure: fchownat");
8062                 goto out;
8063         }
8064
8065         if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8066                 log_stderr("failure: fchownat");
8067                 goto out;
8068         }
8069
8070         pid = fork();
8071         if (pid < 0) {
8072                 log_stderr("failure: fork");
8073                 goto out;
8074         }
8075         if (pid == 0) {
8076                 if (!caps_supported()) {
8077                         log_debug("skip: capability library not installed");
8078                         exit(EXIT_SUCCESS);
8079                 }
8080
8081                 if (!switch_userns(attr.userns_fd, 0, 1000, true))
8082                         die("failure: switch_userns");
8083
8084                 /* create regular file via open() */
8085                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
8086                 if (file1_fd < 0)
8087                         die("failure: create");
8088
8089                 /* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
8090                  * bit needs to be stripped.
8091                  */
8092                 if (is_setgid(open_tree_fd, FILE1, 0))
8093                         die("failure: is_setgid");
8094
8095                 /* create directory */
8096                 if (mkdirat(open_tree_fd, DIR1, 0000))
8097                         die("failure: create");
8098
8099                 /* Directories always inherit the setgid bit. */
8100                 if (xfs_irix_sgid_inherit_enabled()) {
8101                         /* We're not in_group_p(). */
8102                         if (is_setgid(open_tree_fd, DIR1, 0))
8103                                 die("failure: is_setgid");
8104                 } else {
8105                         /* Directories always inherit the setgid bit. */
8106                         if (!is_setgid(open_tree_fd, DIR1, 0))
8107                                 die("failure: is_setgid");
8108                 }
8109
8110                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8111                         die("failure: check ownership");
8112
8113                 if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
8114                         die("failure: check ownership");
8115
8116                 exit(EXIT_SUCCESS);
8117         }
8118         if (wait_for_pid(pid))
8119                 goto out;
8120
8121         fret = 0;
8122         log_debug("Ran test");
8123 out:
8124         safe_close(attr.userns_fd);
8125         safe_close(file1_fd);
8126         safe_close(open_tree_fd);
8127
8128         return fret;
8129 }
8130
8131 #define PTR_TO_INT(p) ((int)((intptr_t)(p)))
8132 #define INT_TO_PTR(u) ((void *)((intptr_t)(u)))
8133
8134 static void *idmapped_mount_create_cb(void *data)
8135 {
8136         int fret = EXIT_FAILURE, open_tree_fd = PTR_TO_INT(data);
8137         struct mount_attr attr = {
8138                 .attr_set = MOUNT_ATTR_IDMAP,
8139         };
8140
8141         /* Changing mount properties on a detached mount. */
8142         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
8143         if (attr.userns_fd < 0) {
8144                 log_stderr("failure: get_userns_fd");
8145                 goto out;
8146         }
8147
8148         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8149                 log_stderr("failure: sys_mount_setattr");
8150                 goto out;
8151         }
8152
8153         fret = EXIT_SUCCESS;
8154
8155 out:
8156         safe_close(attr.userns_fd);
8157         pthread_exit(INT_TO_PTR(fret));
8158 }
8159
8160 /* This tries to verify that we never see an inconistent ownership on-disk and
8161  * can't write invalid ids to disk. To do this we create a race between
8162  * idmapping a mount and creating files on it.
8163  * Note, while it is perfectly fine to see overflowuid and overflowgid as owner
8164  * if we create files through the open_tree_fd before the mount is idmapped but
8165  * look at the files after the mount has been idmapped in this test it can never
8166  * be the case that we see overflowuid and overflowgid when we access the file
8167  * through a non-idmapped mount (in the initial user namespace).
8168  */
8169 static void *idmapped_mount_operations_cb(void *data)
8170 {
8171         int file1_fd = -EBADF, file2_fd = -EBADF, dir1_fd = -EBADF,
8172             dir1_fd2 = -EBADF, fret = EXIT_FAILURE,
8173             open_tree_fd = PTR_TO_INT(data);
8174
8175         if (!switch_fsids(10000, 10000)) {
8176                 log_stderr("failure: switch fsids");
8177                 goto out;
8178         }
8179
8180         file1_fd = openat(open_tree_fd, FILE1,
8181                           O_CREAT | O_EXCL | O_CLOEXEC, 0644);
8182         if (file1_fd < 0) {
8183                 log_stderr("failure: openat");
8184                 goto out;
8185         }
8186
8187         file2_fd = openat(open_tree_fd, FILE2,
8188                           O_CREAT | O_EXCL | O_CLOEXEC, 0644);
8189         if (file2_fd < 0) {
8190                 log_stderr("failure: openat");
8191                 goto out;
8192         }
8193
8194         if (mkdirat(open_tree_fd, DIR1, 0777)) {
8195                 log_stderr("failure: mkdirat");
8196                 goto out;
8197         }
8198
8199         dir1_fd = openat(open_tree_fd, DIR1,
8200                          O_RDONLY | O_DIRECTORY | O_CLOEXEC);
8201         if (dir1_fd < 0) {
8202                 log_stderr("failure: openat");
8203                 goto out;
8204         }
8205
8206         if (!__expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0, false) &&
8207             !__expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000, false) &&
8208             !__expected_uid_gid(open_tree_fd, FILE1, 0, t_overflowuid, t_overflowgid, false)) {
8209                 log_stderr("failure: expected_uid_gid");
8210                 goto out;
8211         }
8212
8213         if (!__expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0, false) &&
8214             !__expected_uid_gid(open_tree_fd, FILE2, 0, 10000, 10000, false) &&
8215             !__expected_uid_gid(open_tree_fd, FILE2, 0, t_overflowuid, t_overflowgid, false)) {
8216                 log_stderr("failure: expected_uid_gid");
8217                 goto out;
8218         }
8219
8220         if (!__expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0, false) &&
8221             !__expected_uid_gid(open_tree_fd, DIR1, 0, 10000, 10000, false) &&
8222             !__expected_uid_gid(open_tree_fd, DIR1, 0, t_overflowuid, t_overflowgid, false)) {
8223                 log_stderr("failure: expected_uid_gid");
8224                 goto out;
8225         }
8226
8227         if (!__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, 0, 0, false) &&
8228             !__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, 10000, 10000, false) &&
8229             !__expected_uid_gid(dir1_fd, "", AT_EMPTY_PATH, t_overflowuid, t_overflowgid, false)) {
8230                 log_stderr("failure: expected_uid_gid");
8231                 goto out;
8232         }
8233
8234         dir1_fd2 = openat(t_dir1_fd, DIR1,
8235                          O_RDONLY | O_DIRECTORY | O_CLOEXEC);
8236         if (dir1_fd2 < 0) {
8237                 log_stderr("failure: openat");
8238                 goto out;
8239         }
8240
8241         if (!__expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0, false) &&
8242             !__expected_uid_gid(t_dir1_fd, FILE1, 0, 10000, 10000, false)) {
8243                 log_stderr("failure: expected_uid_gid");
8244                 goto out;
8245         }
8246
8247         if (!__expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0, false) &&
8248             !__expected_uid_gid(t_dir1_fd, FILE2, 0, 10000, 10000, false)) {
8249                 log_stderr("failure: expected_uid_gid");
8250                 goto out;
8251         }
8252
8253         if (!__expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0, false) &&
8254             !__expected_uid_gid(t_dir1_fd, DIR1, 0, 10000, 10000, false)) {
8255                 log_stderr("failure: expected_uid_gid");
8256                 goto out;
8257         }
8258
8259         if (!__expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0, false) &&
8260             !__expected_uid_gid(t_dir1_fd, DIR1, 0, 10000, 10000, false)) {
8261                 log_stderr("failure: expected_uid_gid");
8262                 goto out;
8263         }
8264
8265         if (!__expected_uid_gid(dir1_fd2, "", AT_EMPTY_PATH, 0, 0, false) &&
8266             !__expected_uid_gid(dir1_fd2, "", AT_EMPTY_PATH, 10000, 10000, false)) {
8267                 log_stderr("failure: expected_uid_gid");
8268                 goto out;
8269         }
8270
8271         fret = EXIT_SUCCESS;
8272
8273 out:
8274         safe_close(file1_fd);
8275         safe_close(file2_fd);
8276         safe_close(dir1_fd);
8277         safe_close(dir1_fd2);
8278
8279         pthread_exit(INT_TO_PTR(fret));
8280 }
8281
8282 static int threaded_idmapped_mount_interactions(void)
8283 {
8284         int i;
8285         int fret = -1;
8286         pid_t pid;
8287         pthread_attr_t thread_attr;
8288         pthread_t threads[2];
8289
8290         pthread_attr_init(&thread_attr);
8291
8292         for (i = 0; i < 1000; i++) {
8293                 int ret1 = 0, ret2 = 0, tret1 = 0, tret2 = 0;
8294
8295                 pid = fork();
8296                 if (pid < 0) {
8297                         log_stderr("failure: fork");
8298                         goto out;
8299                 }
8300                 if (pid == 0) {
8301                         int open_tree_fd = -EBADF;
8302
8303                         open_tree_fd = sys_open_tree(t_dir1_fd, "",
8304                                                      AT_EMPTY_PATH |
8305                                                      AT_NO_AUTOMOUNT |
8306                                                      AT_SYMLINK_NOFOLLOW |
8307                                                      OPEN_TREE_CLOEXEC |
8308                                                      OPEN_TREE_CLONE);
8309                         if (open_tree_fd < 0)
8310                                 die("failure: sys_open_tree");
8311
8312                         if (pthread_create(&threads[0], &thread_attr,
8313                                            idmapped_mount_create_cb,
8314                                            INT_TO_PTR(open_tree_fd)))
8315                                 die("failure: pthread_create");
8316
8317                         if (pthread_create(&threads[1], &thread_attr,
8318                                            idmapped_mount_operations_cb,
8319                                            INT_TO_PTR(open_tree_fd)))
8320                                 die("failure: pthread_create");
8321
8322                         ret1 = pthread_join(threads[0], INT_TO_PTR(tret1));
8323                         ret2 = pthread_join(threads[1], INT_TO_PTR(tret2));
8324
8325                         if (ret1) {
8326                                 errno = ret1;
8327                                 die("failure: pthread_join");
8328                         }
8329
8330                         if (ret2) {
8331                                 errno = ret2;
8332                                 die("failure: pthread_join");
8333                         }
8334
8335                         if (tret1 || tret2)
8336                                 exit(EXIT_FAILURE);
8337
8338                         exit(EXIT_SUCCESS);
8339
8340                 }
8341
8342                 if (wait_for_pid(pid)) {
8343                         log_stderr("failure: iteration %d", i);
8344                         goto out;
8345                 }
8346
8347                 rm_r(t_dir1_fd, ".");
8348
8349         }
8350
8351         fret = 0;
8352         log_debug("Ran test");
8353
8354 out:
8355         return fret;
8356 }
8357
8358 static int setattr_truncate(void)
8359 {
8360         int fret = -1;
8361         int file1_fd = -EBADF;
8362
8363         /* create regular file via open() */
8364         file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8365         if (file1_fd < 0) {
8366                 log_stderr("failure: create");
8367                 goto out;
8368         }
8369
8370         if (ftruncate(file1_fd, 10000)) {
8371                 log_stderr("failure: ftruncate");
8372                 goto out;
8373         }
8374
8375         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
8376                 log_stderr("failure: check ownership");
8377                 goto out;
8378         }
8379
8380         if (!expected_file_size(file1_fd, "", AT_EMPTY_PATH, 10000)) {
8381                 log_stderr("failure: expected_file_size");
8382                 goto out;
8383         }
8384
8385         if (ftruncate(file1_fd, 0)) {
8386                 log_stderr("failure: ftruncate");
8387                 goto out;
8388         }
8389
8390         if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0)) {
8391                 log_stderr("failure: check ownership");
8392                 goto out;
8393         }
8394
8395         if (!expected_file_size(file1_fd, "", AT_EMPTY_PATH, 0)) {
8396                 log_stderr("failure: expected_file_size");
8397                 goto out;
8398         }
8399
8400         if (unlinkat(t_dir1_fd, FILE1, 0)) {
8401                 log_stderr("failure: remove");
8402                 goto out;
8403         }
8404
8405         fret = 0;
8406         log_debug("Ran test");
8407 out:
8408         safe_close(file1_fd);
8409
8410         return fret;
8411 }
8412
8413 static int setattr_truncate_idmapped(void)
8414 {
8415         int fret = -1;
8416         int file1_fd = -EBADF, open_tree_fd = -EBADF;
8417         pid_t pid;
8418         struct mount_attr attr = {
8419                 .attr_set = MOUNT_ATTR_IDMAP,
8420         };
8421
8422         /* Changing mount properties on a detached mount. */
8423         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
8424         if (attr.userns_fd < 0) {
8425                 log_stderr("failure: get_userns_fd");
8426                 goto out;
8427         }
8428
8429         open_tree_fd = sys_open_tree(t_dir1_fd, "",
8430                                      AT_EMPTY_PATH |
8431                                      AT_NO_AUTOMOUNT |
8432                                      AT_SYMLINK_NOFOLLOW |
8433                                      OPEN_TREE_CLOEXEC |
8434                                      OPEN_TREE_CLONE);
8435         if (open_tree_fd < 0) {
8436                 log_stderr("failure: sys_open_tree");
8437                 goto out;
8438         }
8439
8440         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8441                 log_stderr("failure: sys_mount_setattr");
8442                 goto out;
8443         }
8444
8445         pid = fork();
8446         if (pid < 0) {
8447                 log_stderr("failure: fork");
8448                 goto out;
8449         }
8450         if (pid == 0) {
8451                 if (!switch_ids(10000, 10000))
8452                         die("failure: switch_ids");
8453
8454                 /* create regular file via open() */
8455                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8456                 if (file1_fd < 0)
8457                         die("failure: create");
8458
8459                 if (ftruncate(file1_fd, 10000))
8460                         die("failure: ftruncate");
8461
8462                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8463                         die("failure: check ownership");
8464
8465                 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8466                         die("failure: expected_file_size");
8467
8468                 if (ftruncate(file1_fd, 0))
8469                         die("failure: ftruncate");
8470
8471                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8472                         die("failure: check ownership");
8473
8474                 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8475                         die("failure: expected_file_size");
8476
8477                 exit(EXIT_SUCCESS);
8478         }
8479         if (wait_for_pid(pid))
8480                 goto out;
8481
8482         pid = fork();
8483         if (pid < 0) {
8484                 log_stderr("failure: fork");
8485                 goto out;
8486         }
8487         if (pid == 0) {
8488                 int file1_fd2 = -EBADF;
8489
8490                 /* create regular file via open() */
8491                 file1_fd2 = openat(open_tree_fd, FILE1, O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8492                 if (file1_fd2 < 0)
8493                         die("failure: create");
8494
8495                 if (ftruncate(file1_fd2, 10000))
8496                         die("failure: ftruncate");
8497
8498                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8499                         die("failure: check ownership");
8500
8501                 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8502                         die("failure: expected_file_size");
8503
8504                 if (ftruncate(file1_fd2, 0))
8505                         die("failure: ftruncate");
8506
8507                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
8508                         die("failure: check ownership");
8509
8510                 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8511                         die("failure: expected_file_size");
8512
8513                 exit(EXIT_SUCCESS);
8514         }
8515         if (wait_for_pid(pid))
8516                 goto out;
8517
8518         fret = 0;
8519         log_debug("Ran test");
8520 out:
8521         safe_close(file1_fd);
8522         safe_close(open_tree_fd);
8523
8524         return fret;
8525 }
8526
8527 static int setattr_truncate_idmapped_in_userns(void)
8528 {
8529         int fret = -1;
8530         int file1_fd = -EBADF, open_tree_fd = -EBADF;
8531         struct mount_attr attr = {
8532                 .attr_set = MOUNT_ATTR_IDMAP,
8533         };
8534         pid_t pid;
8535
8536         /* Changing mount properties on a detached mount. */
8537         attr.userns_fd  = get_userns_fd(0, 10000, 10000);
8538         if (attr.userns_fd < 0) {
8539                 log_stderr("failure: get_userns_fd");
8540                 goto out;
8541         }
8542
8543         open_tree_fd = sys_open_tree(t_dir1_fd, "",
8544                                      AT_EMPTY_PATH |
8545                                      AT_NO_AUTOMOUNT |
8546                                      AT_SYMLINK_NOFOLLOW |
8547                                      OPEN_TREE_CLOEXEC |
8548                                      OPEN_TREE_CLONE);
8549         if (open_tree_fd < 0) {
8550                 log_stderr("failure: sys_open_tree");
8551                 goto out;
8552         }
8553
8554         if (sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr))) {
8555                 log_stderr("failure: sys_mount_setattr");
8556                 goto out;
8557         }
8558
8559         pid = fork();
8560         if (pid < 0) {
8561                 log_stderr("failure: fork");
8562                 goto out;
8563         }
8564         if (pid == 0) {
8565                 if (!switch_userns(attr.userns_fd, 0, 0, false))
8566                         die("failure: switch_userns");
8567
8568                 /* create regular file via open() */
8569                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8570                 if (file1_fd < 0)
8571                         die("failure: create");
8572
8573                 if (ftruncate(file1_fd, 10000))
8574                         die("failure: ftruncate");
8575
8576                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8577                         die("failure: check ownership");
8578
8579                 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8580                         die("failure: expected_file_size");
8581
8582                 if (ftruncate(file1_fd, 0))
8583                         die("failure: ftruncate");
8584
8585                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8586                         die("failure: check ownership");
8587
8588                 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8589                         die("failure: expected_file_size");
8590
8591                 if (unlinkat(open_tree_fd, FILE1, 0))
8592                         die("failure: delete");
8593
8594                 exit(EXIT_SUCCESS);
8595         }
8596         if (wait_for_pid(pid))
8597                 goto out;
8598
8599         if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8600                 log_stderr("failure: fchownat");
8601                 goto out;
8602         }
8603
8604         if (fchownat(t_dir1_fd, "", -1, 1000, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8605                 log_stderr("failure: fchownat");
8606                 goto out;
8607         }
8608
8609         pid = fork();
8610         if (pid < 0) {
8611                 log_stderr("failure: fork");
8612                 goto out;
8613         }
8614         if (pid == 0) {
8615                 if (!caps_supported()) {
8616                         log_debug("skip: capability library not installed");
8617                         exit(EXIT_SUCCESS);
8618                 }
8619
8620                 if (!switch_userns(attr.userns_fd, 0, 0, true))
8621                         die("failure: switch_userns");
8622
8623                 /* create regular file via open() */
8624                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8625                 if (file1_fd < 0)
8626                         die("failure: create");
8627
8628                 if (ftruncate(file1_fd, 10000))
8629                         die("failure: ftruncate");
8630
8631                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8632                         die("failure: check ownership");
8633
8634                 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8635                         die("failure: expected_file_size");
8636
8637                 if (ftruncate(file1_fd, 0))
8638                         die("failure: ftruncate");
8639
8640                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
8641                         die("failure: check ownership");
8642
8643                 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8644                         die("failure: expected_file_size");
8645
8646                 if (unlinkat(open_tree_fd, FILE1, 0))
8647                         die("failure: delete");
8648
8649                 exit(EXIT_SUCCESS);
8650         }
8651         if (wait_for_pid(pid))
8652                 goto out;
8653
8654         if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8655                 log_stderr("failure: fchownat");
8656                 goto out;
8657         }
8658
8659         if (fchownat(t_dir1_fd, "", -1, 0, AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) {
8660                 log_stderr("failure: fchownat");
8661                 goto out;
8662         }
8663
8664         pid = fork();
8665         if (pid < 0) {
8666                 log_stderr("failure: fork");
8667                 goto out;
8668         }
8669         if (pid == 0) {
8670                 if (!caps_supported()) {
8671                         log_debug("skip: capability library not installed");
8672                         exit(EXIT_SUCCESS);
8673                 }
8674
8675                 if (!switch_userns(attr.userns_fd, 0, 1000, true))
8676                         die("failure: switch_userns");
8677
8678                 /* create regular file via open() */
8679                 file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, S_IXGRP | S_ISGID);
8680                 if (file1_fd < 0)
8681                         die("failure: create");
8682
8683                 if (ftruncate(file1_fd, 10000))
8684                         die("failure: ftruncate");
8685
8686                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8687                         die("failure: check ownership");
8688
8689                 if (!expected_file_size(open_tree_fd, FILE1, 0, 10000))
8690                         die("failure: expected_file_size");
8691
8692                 if (ftruncate(file1_fd, 0))
8693                         die("failure: ftruncate");
8694
8695                 if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
8696                         die("failure: check ownership");
8697
8698                 if (!expected_file_size(open_tree_fd, FILE1, 0, 0))
8699                         die("failure: expected_file_size");
8700
8701                 if (unlinkat(open_tree_fd, FILE1, 0))
8702                         die("failure: delete");
8703
8704                 exit(EXIT_SUCCESS);
8705         }
8706         if (wait_for_pid(pid))
8707                 goto out;
8708
8709         fret = 0;
8710         log_debug("Ran test");
8711 out:
8712         safe_close(attr.userns_fd);
8713         safe_close(file1_fd);
8714         safe_close(open_tree_fd);
8715
8716         return fret;
8717 }
8718
8719 static void usage(void)
8720 {
8721         fprintf(stderr, "Description:\n");
8722         fprintf(stderr, "    Run idmapped mount tests\n\n");
8723
8724         fprintf(stderr, "Arguments:\n");
8725         fprintf(stderr, "-d --device        Device used in the tests\n");
8726         fprintf(stderr, "-m --mountpoint    Mountpoint of device\n");
8727
8728         _exit(EXIT_SUCCESS);
8729 }
8730
8731 static const struct option longopts[] = {
8732         {"device",      required_argument,      0,      'd'},
8733         {"fstype",      required_argument,      0,      'f'},
8734         {"mountpoint",  required_argument,      0,      'm'},
8735         {"supported",   no_argument,            0,      's'},
8736         {"help",        no_argument,            0,      'h'},
8737         {NULL,          0,                      0,      0  },
8738 };
8739
8740 struct t_idmapped_mounts {
8741         int (*test)(void);
8742         const char *description;
8743 } t_idmapped_mounts[] = {
8744         { acls,                                                         "posix acls on regular mounts",                                                                 },
8745         { create_in_userns,                                             "create operations in user namespace",                                                          },
8746         { device_node_in_userns,                                        "device node in user namespace",                                                                },
8747         { expected_uid_gid_idmapped_mounts,                             "expected ownership on idmapped mounts",                                                        },
8748         { fscaps,                                                       "fscaps on regular mounts",                                                                     },
8749         { fscaps_idmapped_mounts,                                       "fscaps on idmapped mounts",                                                                    },
8750         { fscaps_idmapped_mounts_in_userns,                             "fscaps on idmapped mounts in user namespace",                                                  },
8751         { fscaps_idmapped_mounts_in_userns_separate_userns,             "fscaps on idmapped mounts in user namespace with different id mappings ",                      },
8752         { fsids_mapped,                                                 "mapped fsids",                                                                                 },
8753         { fsids_unmapped,                                               "unmapped fsids",                                                                               },
8754         { hardlink_crossing_mounts,                                     "cross mount hardlink",                                                                         },
8755         { hardlink_crossing_idmapped_mounts,                            "cross idmapped mount hardlink",                                                                },
8756         { hardlink_from_idmapped_mount,                                 "hardlinks from idmapped mounts",                                                               },
8757         { hardlink_from_idmapped_mount_in_userns,                       "hardlinks from idmapped mounts in user namespace",                                             },
8758 #ifdef HAVE_LIBURING_H
8759         { io_uring,                                                     "io_uring",                                                                                     },
8760         { io_uring_userns,                                              "io_uring in user namespace",                                                                   },
8761         { io_uring_idmapped,                                            "io_uring from idmapped mounts",                                                                },
8762         { io_uring_idmapped_userns,                                     "io_uring from idmapped mounts in user namespace",                                              },
8763         { io_uring_idmapped_unmapped,                                   "io_uring from idmapped mounts with unmapped ids",                                              },
8764         { io_uring_idmapped_unmapped_userns,                            "io_uring from idmapped mounts with unmapped ids in user namespace",                            },
8765 #endif
8766         { protected_symlinks,                                           "following protected symlinks on regular mounts",                                               },
8767         { protected_symlinks_idmapped_mounts,                           "following protected symlinks on idmapped mounts",                                              },
8768         { protected_symlinks_idmapped_mounts_in_userns,                 "following protected symlinks on idmapped mounts in user namespace",                            },
8769         { rename_crossing_mounts,                                       "cross mount rename",                                                                           },
8770         { rename_crossing_idmapped_mounts,                              "cross idmapped mount rename",                                                                  },
8771         { rename_from_idmapped_mount,                                   "rename from idmapped mounts",                                                                  },
8772         { rename_from_idmapped_mount_in_userns,                         "rename from idmapped mounts in user namespace",                                                },
8773         { setattr_truncate,                                             "setattr truncate",                                                                             },
8774         { setattr_truncate_idmapped,                                    "setattr truncate on idmapped mounts",                                                          },
8775         { setattr_truncate_idmapped_in_userns,                          "setattr truncate on idmapped mounts in user namespace",                                        },
8776         { setgid_create,                                                "create operations in directories with setgid bit set",                                         },
8777         { setgid_create_idmapped,                                       "create operations in directories with setgid bit set on idmapped mounts",                      },
8778         { setgid_create_idmapped_in_userns,                             "create operations in directories with setgid bit set on idmapped mounts in user namespace",    },
8779         { setid_binaries,                                               "setid binaries on regular mounts",                                                             },
8780         { setid_binaries_idmapped_mounts,                               "setid binaries on idmapped mounts",                                                            },
8781         { setid_binaries_idmapped_mounts_in_userns,                     "setid binaries on idmapped mounts in user namespace",                                          },
8782         { setid_binaries_idmapped_mounts_in_userns_separate_userns,     "setid binaries on idmapped mounts in user namespace with different id mappings",               },
8783         { sticky_bit_unlink,                                            "sticky bit unlink operations on regular mounts",                                               },
8784         { sticky_bit_unlink_idmapped_mounts,                            "sticky bit unlink operations on idmapped mounts",                                              },
8785         { sticky_bit_unlink_idmapped_mounts_in_userns,                  "sticky bit unlink operations on idmapped mounts in user namespace",                            },
8786         { sticky_bit_rename,                                            "sticky bit rename operations on regular mounts",                                               },
8787         { sticky_bit_rename_idmapped_mounts,                            "sticky bit rename operations on idmapped mounts",                                              },
8788         { sticky_bit_rename_idmapped_mounts_in_userns,                  "sticky bit rename operations on idmapped mounts in user namespace",                            },
8789         { symlink_regular_mounts,                                       "symlink from regular mounts",                                                                  },
8790         { symlink_idmapped_mounts,                                      "symlink from idmapped mounts",                                                                 },
8791         { symlink_idmapped_mounts_in_userns,                            "symlink from idmapped mounts in user namespace",                                               },
8792         { threaded_idmapped_mount_interactions,                         "threaded operations on idmapped mounts",                                                       },
8793 };
8794
8795 int main(int argc, char *argv[])
8796 {
8797         int i, fret, ret;
8798         int index = 0;
8799         bool supported = false;
8800
8801         while ((ret = getopt_long(argc, argv, "", longopts, &index)) != -1) {
8802                 switch (ret) {
8803                 case 'd':
8804                         t_device = optarg;
8805                         break;
8806                 case 'f':
8807                         t_fstype = optarg;
8808                         break;
8809                 case 'm':
8810                         t_mountpoint = optarg;
8811                         break;
8812                 case 's':
8813                         supported = true;
8814                         break;
8815                 case 'h':
8816                         /* fallthrough */
8817                 default:
8818                         usage();
8819                 }
8820         }
8821
8822         if (!t_device)
8823                 die_errno(EINVAL, "test device missing");
8824
8825         if (!t_fstype)
8826                 die_errno(EINVAL, "test filesystem type missing");
8827
8828         if (!t_mountpoint)
8829                 die_errno(EINVAL, "mountpoint of test device missing");
8830
8831         /* create separate mount namespace */
8832         if (unshare(CLONE_NEWNS))
8833                 die("failure: create new mount namespace");
8834
8835         /* turn off mount propagation */
8836         if (sys_mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0))
8837                 die("failure: turn mount propagation off");
8838
8839         t_mnt_fd = openat(-EBADF, t_mountpoint, O_CLOEXEC | O_DIRECTORY);
8840         if (t_mnt_fd < 0)
8841                 die("failed to open %s", t_mountpoint);
8842
8843         /*
8844          * Caller just wants to know whether the filesystem we're on supports
8845          * idmapped mounts.
8846          */
8847         if (supported) {
8848                 int open_tree_fd = -EBADF;
8849                 struct mount_attr attr = {
8850                         .attr_set       = MOUNT_ATTR_IDMAP,
8851                         .userns_fd      = -EBADF,
8852                 };
8853
8854                 /* Changing mount properties on a detached mount. */
8855                 attr.userns_fd  = get_userns_fd(0, 1000, 1);
8856                 if (attr.userns_fd < 0)
8857                         exit(EXIT_FAILURE);
8858
8859                 open_tree_fd = sys_open_tree(t_mnt_fd, "",
8860                                              AT_EMPTY_PATH |
8861                                              AT_NO_AUTOMOUNT |
8862                                              AT_SYMLINK_NOFOLLOW |
8863                                              OPEN_TREE_CLOEXEC |
8864                                              OPEN_TREE_CLONE);
8865                 if (open_tree_fd < 0)
8866                         ret = -1;
8867                 else
8868                         ret = sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr));
8869
8870                 close(open_tree_fd);
8871                 close(attr.userns_fd);
8872
8873                 if (ret)
8874                         exit(EXIT_FAILURE);
8875
8876                 exit(EXIT_SUCCESS);
8877         }
8878
8879         stash_overflowuid();
8880         stash_overflowgid();
8881
8882         fret = EXIT_FAILURE;
8883
8884         /* Proper test suite run. */
8885         for (i = 0; i < (sizeof(t_idmapped_mounts) / sizeof(t_idmapped_mounts[0])); i++) {
8886                 struct t_idmapped_mounts *t = &t_idmapped_mounts[i];
8887                 pid_t pid;
8888
8889                 test_setup();
8890
8891                 pid = fork();
8892                 if (pid < 0)
8893                         goto out;
8894
8895                 if (pid == 0) {
8896                         ret = t->test();
8897                         if (ret) {
8898                                 fprintf(stderr, "failure: %s\n", t->description);
8899                                 exit(EXIT_FAILURE);
8900                         }
8901
8902                         exit(EXIT_SUCCESS);
8903                 }
8904
8905                 ret = wait_for_pid(pid);
8906                 test_cleanup();
8907
8908                 if (ret)
8909                         goto out;
8910         }
8911
8912         fret = EXIT_SUCCESS;
8913
8914 out:
8915         exit(fret);
8916 }