1 .\" Copyright (c) 2021 by Christian Brauner <christian.brauner@ubuntu.com>
3 .\" %%%LICENSE_START(VERBATIM)
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date. The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein. The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
25 .TH MOUNT_SETATTR 2 2021-03-22 "Linux" "Linux Programmer's Manual"
27 mount_setattr \- change properties of a mount or mount tree
32 .BR "#include <linux/fcntl.h>" " /* Definition of " AT_* " constants */"
33 .BR "#include <linux/mount.h>" " /* Definition of " MOUNT_ATTR_* " constants */"
34 .BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */"
35 .B #include <unistd.h>
37 .BI "int syscall(SYS_mount_setattr, int " dirfd ", const char *" path ,
38 .BI " unsigned int " flags ", struct mount_attr *" attr \
43 glibc provides no wrapper for
45 necessitating the use of
50 system call changes the mount properties of a mount or an entire mount tree.
53 is a relative pathname,
54 then it is interpreted relative to
55 the directory referred to by the file descriptor
63 is interpreted relative to
64 the current working directory of the calling process.
67 is the empty string and
71 then the mount properties of the mount identified by
77 system call uses an extensible structure
78 .RI ( "struct mount_attr" )
79 to allow for future extensions.
80 Any non-flag extensions to
82 will be implemented as new fields appended to the this structure,
83 with a zero value in a new field resulting in the kernel behaving
84 as though that extension field was not present.
88 zero-fill this structure on initialization.
89 See the "Extensibility" subsection under
95 argument should usually be specified as
96 .IR "sizeof(struct mount_attr)" .
97 However, if the caller is using a kernel that supports an extended
98 .IR "struct mount_attr" ,
99 but the caller does not intend to make use of these features,
100 they can pass the size of an earlier
101 version of the structure together with the extended structure.
102 This allows the kernel to not copy later parts of the struct
103 that aren't used anyway.
104 With each extension that changes the size of
105 .IR "struct mount_attr" ,
106 the kernel will expose a definition of the form
107 .BI MOUNT_ATTR_SIZE_VER number\c
109 For example, the macro for the size of the initial version of
112 .BR MOUNT_ATTR_SIZE_VER0 .
116 argument can be used to alter the path resolution behavior.
117 The supported values are:
123 change the mount properties on
128 Change the mount properties of the entire mount tree.
130 .B AT_SYMLINK_NOFOLLOW
131 Don't follow trailing symbolic links.
134 Don't trigger automounts.
140 is a structure of the following form:
145 __u64 attr_set; /* Mount properties to set */
146 __u64 attr_clr; /* Mount properties to clear */
147 __u64 propagation; /* Mount propagation type */
148 __u64 userns_fd; /* User namespace file descriptor */
157 members are used to specify the mount properties that
158 are supposed to be set or cleared for a mount or mount tree.
161 enable a property on a mount or mount tree,
164 remove a property from a mount or mount tree.
166 When changing mount properties,
167 the kernel will first clear the flags specified
171 and then set the flags specified in the
174 For example, these settings:
178 struct mount_attr attr = {
179 .attr_clr = MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV,
180 .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID,
185 are equivalent to the following steps:
189 unsigned int current_mnt_flags = mnt->mnt_flags;
192 * Clear all flags set in .attr_clr,
193 * clearing MOUNT_ATTR_NOEXEC and MOUNT_ATTR_NODEV.
195 current_mnt_flags &= ~attr->attr_clr;
198 * Now set all flags set in .attr_set,
199 * applying MOUNT_ATTR_RDONLY and MOUNT_ATTR_NOSUID.
201 current_mnt_flags |= attr->attr_set;
203 mnt->mnt_flags = current_mnt_flags;
207 As a result of this change, the mount or mount tree (a) is read-only;
208 (b) blocks the execution of set-user-ID and set-group-ID programs;
209 (c) allows execution of programs; and (d) allows access to devices.
211 Multiple changes with the same set of flags requested
216 are guaranteed to be idempotent after the changes have been applied.
218 The following mount attributes can be specified in the
227 makes the mount read-only.
230 removes the read-only setting if set on the mount.
235 causes the mount not to honor the set-user-ID and set-group-ID mode bits and
236 file capabilities when executing programs.
239 clears the set-user-ID, set-group-ID,
240 and file capability restriction if set on this mount.
245 prevents access to devices on this mount.
248 removes the restriction that prevented accessing devices on this mount.
253 prevents executing programs on this mount.
256 removes the restriction that prevented executing programs on this mount.
258 .B MOUNT_ATTR_NOSYMFOLLOW
261 prevents following symbolic links on this mount.
264 removes the restriction that prevented following symbolic links on this mount.
266 .B MOUNT_ATTR_NODIRATIME
269 prevents updating access time for directories on this mount.
272 removes the restriction that prevented updating access time for directories.
274 .B MOUNT_ATTR_NODIRATIME
275 can be combined with other access-time settings
276 and is implied by the noatime setting.
277 All other access-time settings are mutually exclusive.
279 .BR MOUNT_ATTR__ATIME " - changing access-time settings"
280 The access-time values listed below are an enumeration that
281 includes the value zero, expressed in the bits defined by the mask
282 .BR MOUNT_ATTR__ATIME .
283 Even though these bits are an enumeration
284 (in contrast to the other mount flags such as
285 .BR MOUNT_ATTR_NOEXEC ),
286 they are nonetheless passed in
292 which introduced this behavior.
295 since the access-time values are an enumeration rather than bit values,
296 a caller wanting to transition to a different access-time setting
297 cannot simply specify the access-time setting in
299 but must also include
304 The kernel will verify that
306 isn't partially set in
308 (i.e., either all bits in the
310 bit field are either set or clear), and that
312 doesn't have any access-time bits set if
318 .B MOUNT_ATTR_RELATIME
319 When a file is accessed via this mount,
320 update the file's last access time (atime)
321 only if the current value of atime is less than or equal to
322 the file's last modification time (mtime) or last status change time (ctime).
324 To enable this access-time setting on a mount or mount tree,
325 .B MOUNT_ATTR_RELATIME
334 .B MOUNT_ATTR_NOATIME
335 Do not update access times for (all types of) files on this mount.
337 To enable this access-time setting on a mount or mount tree,
338 .B MOUNT_ATTR_NOATIME
347 .B MOUNT_ATTR_STRICTATIME
348 Always update the last access time (atime)
349 when files are accessed on this mount.
351 To enable this access-time setting on a mount or mount tree,
352 .B MOUNT_ATTR_STRICTATIME
365 creates an ID-mapped mount.
366 The ID mapping is taken from the user namespace specified in
368 and attached to the mount.
370 Since it is not supported to
371 change the ID mapping of a mount after it has been ID mapped,
372 it is invalid to specify
377 For further details, see the subsection "ID-mapped mounts" under NOTES.
381 field is used to specify the propagation type of the mount or mount tree.
382 This field either has the value zero,
383 meaning leave the propagation type unchanged, or it has one of
384 the following values:
387 Turn all mounts into private mounts.
390 Turn all mounts into shared mounts.
393 Turn all mounts into dependent mounts.
396 Turn all mounts into unbindable mounts.
398 For further details on the above propagation types, see
399 .BR mount_namespaces (7).
407 is set to indicate the cause of the error.
412 is not a valid file descriptor.
416 is not a valid file descriptor.
419 The caller tried to change the mount to
420 .BR MOUNT_ATTR_RDONLY ,
421 but the mount still holds files open for writing.
424 The path specified via the
433 An unsupported value was set in
437 An unsupported value was specified in the
443 An unsupported value was specified in the
449 An unsupported value was specified in the
467 An access-time setting was specified in the
481 A file descriptor value was specified in
487 A valid file descriptor value was specified in
489 but the file descriptor did not refer to a user namespace.
492 The underlying filesystem does not support ID-mapped mounts.
495 The mount that is to be ID mapped is not a detached mount;
496 that is, the mount is already visible in the filesystem.
499 A partial access-time setting was specified in
506 The mount is located outside the caller's mount namespace.
509 The underlying filesystem is mounted in a user namespace.
512 A pathname was empty or had a nonexistent component.
515 When changing mount propagation to
517 a new peer group ID needs to be allocated for all mounts without a peer group
519 Allocation of this peer group ID has failed.
522 When changing mount propagation to
524 a new peer group ID needs to be allocated for all mounts without a peer group
526 Allocation of this peer group ID can fail.
527 Note that technically further error codes are possible that are specific to the
528 ID allocation implementation used.
531 One of the mounts had at least one of
532 .BR MOUNT_ATTR_NOATIME ,
533 .BR MOUNT_ATTR_NODEV ,
534 .BR MOUNT_ATTR_NODIRATIME ,
535 .BR MOUNT_ATTR_NOEXEC ,
536 .BR MOUNT_ATTR_NOSUID ,
539 set and the flag is locked.
540 Mount attributes become locked on a mount if:
543 A new mount or mount tree is created causing mount propagation across user
545 The kernel will lock the aforementioned flags to protect these sensitive
546 properties from being altered.
548 A new mount and user namespace pair is created.
549 This happens for example when specifying
550 .B CLONE_NEWUSER | CLONE_NEWNS
556 The aforementioned flags become locked to protect user namespaces from altering
557 sensitive mount properties.
561 A valid file descriptor value was specified in
563 but the file descriptor refers to the initial user namespace.
566 An attempt was made to add an ID mapping to a mount that is already ID mapped.
569 The caller does not have
571 in the initial user namespace.
574 first appeared in Linux 5.12.
575 .\" commit 7d6beb71da3cc033649d641e1e608713b8220290
576 .\" commit 2a1867219c7b27f928e2545782b86daaf9ad50bd
577 .\" commit 9caccd41541a6f7d6279928d9f971f6642c361af
583 Creating an ID-mapped mount makes it possible to
584 change the ownership of all files located under a mount.
585 Thus, ID-mapped mounts make it possible to
586 change ownership in a temporary and localized way.
587 It is a localized change because the ownership changes are
588 visible only via a specific mount.
589 All other users and locations where the filesystem is exposed are unaffected.
590 And it is a temporary change because
591 ownership changes are tied to the lifetime of the mount.
593 Whenever callers interact with the filesystem through an ID-mapped mount,
594 the ID mapping of the mount will be applied to
595 user and group IDs associated with filesystem objects.
596 This encompasses the user and group IDs associated with inodes
597 and also the following
601 .IR security.capability ,
602 whenever filesystem capabilities
603 are stored or returned in the
604 .B VFS_CAP_REVISION_3
606 which stores a root user ID alongside the capabilities
608 .BR capabilities (7)).
610 .I system.posix_acl_access
612 .IR system.posix_acl_default ,
613 whenever user IDs or group IDs are stored in
619 The following conditions must be met in order to create an ID-mapped mount:
621 The caller must have the
623 capability in the initial user namespace.
625 The filesystem must be mounted in a mount namespace
626 that is owned by the initial user namespace.
628 The underlying filesystem must support ID-mapped mounts.
634 filesystems support ID-mapped mounts
635 with more filesystems being actively worked on.
637 The mount must not already be ID-mapped.
638 This also implies that the ID mapping of a mount cannot be altered.
640 The mount must be a detached mount;
642 it must have been created by calling
646 flag and it must not already have been visible in the filesystem.
648 ID mappings can be created for user IDs, group IDs, and project IDs.
649 An ID mapping is essentially a mapping of a range of user or group IDs into
650 another or the same range of user or group IDs.
651 ID mappings are written to map files as three numbers
652 separated by white space.
653 The first two numbers specify the starting user or group ID
654 in each of the two user namespaces.
655 The third number specifies the range of the ID mapping.
657 a mapping for user IDs such as "1000\ 1001\ 1" would indicate that
658 user ID 1000 in the caller's user namespace is mapped to
659 user ID 1001 in its ancestor user namespace.
660 Since the map range is 1,
661 only user ID 1000 is mapped.
663 It is possible to specify up to 340 ID mappings for each ID mapping type.
664 If any user IDs or group IDs are not mapped,
665 all files owned by that unmapped user or group ID will appear as
666 being owned by the overflow user ID or overflow group ID respectively.
668 Further details and instructions for setting up ID mappings can be found in the
669 .BR user_namespaces (7)
672 In the common case, the user namespace passed in
678 to create an ID-mapped mount will be the user namespace of a container.
679 In other scenarios it will be a dedicated user namespace associated with
680 a user's login session as is the case for portable home directories in
681 .BR systemd-homed.service (8)).
682 It is also perfectly fine to create a dedicated user namespace
683 for the sake of ID mapping a mount.
685 ID-mapped mounts can be useful in the following
686 and a variety of other scenarios:
688 Sharing files or filesystems
689 between multiple users or multiple machines,
690 especially in complex scenarios.
692 ID-mapped mounts are used to implement portable home directories in
693 .BR systemd-homed.service (8),
694 where they allow users to move their home directory
695 to an external storage device
696 and use it on multiple computers
697 where they are assigned different user IDs and group IDs.
698 This effectively makes it possible to
699 assign random user IDs and group IDs at login time.
701 Sharing files or filesystems
702 from the host with unprivileged containers.
703 This allows a user to avoid having to change ownership permanently through
706 ID mapping a container's root filesystem.
707 Users don't need to change ownership permanently through
709 Especially for large root filesystems, using
711 can be prohibitively expensive.
713 Sharing files or filesystems
714 between containers with non-overlapping ID mappings.
716 Implementing discretionary access (DAC) permission checking
717 for filesystems lacking a concept of ownership.
719 Efficiently changing ownership on a per-mount basis.
722 changing ownership of large sets of files is instantaneous with
724 This is especially useful when ownership of
725 an entire root filesystem of a virtual machine or container
726 is to be changed as mentioned above.
727 With ID-mapped mounts,
730 system call will be sufficient to change the ownership of all files.
732 Taking the current ownership into account.
733 ID mappings specify precisely
734 what a user or group ID is supposed to be mapped to.
735 This contrasts with the
737 system call which cannot by itself
738 take the current ownership of the files it changes into account.
739 It simply changes the ownership to the specified user ID and group ID.
741 Locally and temporarily restricted ownership changes.
742 ID-mapped mounts make it possible to change ownership locally,
743 restricting the ownership changes to specific mounts,
744 and temporarily as the ownership changes only apply as long as the mount exists.
746 changing ownership via the
748 system call changes the ownership globally and permanently.
751 In order to allow for future extensibility,
753 requires the user-space application to specify the size of the
755 structure that it is passing.
756 By providing this information, it is possible for
758 to provide both forwards- and backwards-compatibility, with
760 acting as an implicit version number.
761 (Because new extension fields will always
762 be appended, the structure size will always increase.)
763 This extensibility design is very similar to other system calls such as
764 .BR perf_setattr (2),
765 .BR perf_event_open (2),
772 be the size of the structure as specified by the user-space application,
775 be the size of the structure which the kernel supports,
776 then there are three cases to consider:
782 then there is no version mismatch and
784 can be used verbatim.
790 then there are some extension fields that the kernel supports
791 which the user-space application is unaware of.
792 Because a zero value in any added extension field signifies a no-op,
793 the kernel treats all of the extension fields
794 not provided by the user-space application
795 as having zero values.
796 This provides backwards-compatibility.
802 then there are some extension fields which the user-space application is aware
803 of but which the kernel does not support.
804 Because any extension field must have its zero values signify a no-op,
805 the kernel can safely ignore the unsupported extension fields
806 if they are all zero.
807 If any unsupported extension fields are non-zero,
808 then \-1 is returned and
812 This provides forwards-compatibility.
814 Because the definition of
816 may change in the future
817 (with new fields being added when system headers are updated),
818 user-space applications should zero-fill
820 to ensure that recompiling the program with new headers will not result in
821 spurious errors at runtime.
822 The simplest way is to use a designated initializer:
826 struct mount_attr attr = {
827 .attr_set = MOUNT_ATTR_RDONLY,
828 .attr_clr = MOUNT_ATTR_NODEV
833 Alternatively, the structure can be zero-filled using
835 or similar functions:
839 struct mount_attr attr;
840 memset(&attr, 0, sizeof(attr));
841 attr.attr_set = MOUNT_ATTR_RDONLY;
842 attr.attr_clr = MOUNT_ATTR_NODEV;
846 A user-space application that wishes to determine which extensions the running
847 kernel supports can do so by conducting a binary search on
849 with a structure which has every byte nonzero
850 (to find the largest value which doesn't produce an error of
855 * This program allows the caller to create a new detached mount
856 * and set various properties on it.
862 #include <linux/mount.h>
863 #include <linux/types.h>
868 #include <sys/syscall.h>
872 mount_setattr(int dirfd, const char *path, unsigned int flags,
873 struct mount_attr *attr, size_t size)
875 return syscall(SYS_mount_setattr, dirfd, path, flags, attr, size);
879 open_tree(int dirfd, const char *filename, unsigned int flags)
881 return syscall(SYS_open_tree, dirfd, filename, flags);
885 move_mount(int from_dirfd, const char *from_pathname,
886 int to_dirfd, const char *to_pathname, unsigned int flags)
888 return syscall(SYS_move_mount, from_dirfd, from_pathname,
889 to_dirfd, to_pathname, flags);
892 static const struct option longopts[] = {
893 {"map\-mount", required_argument, NULL, 'a'},
894 {"recursive", no_argument, NULL, 'b'},
895 {"read\-only", no_argument, NULL, 'c'},
896 {"block\-setid", no_argument, NULL, 'd'},
897 {"block\-devices", no_argument, NULL, 'e'},
898 {"block\-exec", no_argument, NULL, 'f'},
899 {"no\-access\-time", no_argument, NULL, 'g'},
900 { NULL, 0, NULL, 0 },
903 #define exit_log(format, ...) do \e
905 fprintf(stderr, format, ##__VA_ARGS__); \e
906 exit(EXIT_FAILURE); \e
910 main(int argc, char *argv[])
912 struct mount_attr *attr = &(struct mount_attr){};
914 bool recursive = false;
918 while ((ret = getopt_long_only(argc, argv, "",
919 longopts, &index)) != \-1) {
922 fd_userns = open(optarg, O_RDONLY | O_CLOEXEC);
923 if (fd_userns == \-1)
924 exit_log("%m \- Failed top open %s\en", optarg);
930 attr\->attr_set |= MOUNT_ATTR_RDONLY;
933 attr\->attr_set |= MOUNT_ATTR_NOSUID;
936 attr\->attr_set |= MOUNT_ATTR_NODEV;
939 attr\->attr_set |= MOUNT_ATTR_NOEXEC;
942 attr\->attr_set |= MOUNT_ATTR_NOATIME;
943 attr\->attr_clr |= MOUNT_ATTR__ATIME;
946 exit_log("Invalid argument specified");
950 if ((argc \- optind) < 2)
951 exit_log("Missing source or target mount point\en");
953 const char *source = argv[optind];
954 const char *target = argv[optind + 1];
956 int fd_tree = open_tree(\-EBADF, source,
957 OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC |
958 AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0));
960 exit_log("%m \- Failed to open %s\en", source);
962 if (fd_userns >= 0) {
963 attr\->attr_set |= MOUNT_ATTR_IDMAP;
964 attr\->userns_fd = fd_userns;
967 ret = mount_setattr(fd_tree, "",
968 AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0),
969 attr, sizeof(struct mount_attr));
971 exit_log("%m \- Failed to change mount attributes\en");
975 ret = move_mount(fd_tree, "", \-EBADF, target,
976 MOVE_MOUNT_F_EMPTY_PATH);
978 exit_log("%m \- Failed to attach mount to %s\en", target);
992 .BR mount_namespaces (7),
993 .BR capabilities (7),
994 .BR user_namespaces (7),