Many pages: Document fixed-width types with ISO C naming
[man-pages.git] / man2 / mount_setattr.2
blobc106c0feebd0517713a340add9d8cadd886d26b6
1 .\" Copyright (c) 2021 by Christian Brauner <christian.brauner@ubuntu.com>
2 .\"
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
4 .\"
5 .TH MOUNT_SETATTR 2 2021-08-27 "Linux man-pages (unreleased)"
6 .SH NAME
7 mount_setattr \- change properties of a mount or mount tree
8 .SH LIBRARY
9 Standard C library
10 .RI ( libc ", " \-lc )
11 .SH SYNOPSIS
12 .nf
14 .PP
15 .BR "#include <linux/fcntl.h>" " /* Definition of " AT_* " constants */"
16 .BR "#include <linux/mount.h>" " /* Definition of " MOUNT_ATTR_* " constants */"
17 .BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */"
18 .B #include <unistd.h>
19 .PP
20 .BI "int syscall(SYS_mount_setattr, int " dirfd ", const char *" pathname ,
21 .BI "            unsigned int " flags ", struct mount_attr *" attr \
22 ", size_t " size );
23 .fi
24 .PP
25 .IR Note :
26 glibc provides no wrapper for
27 .BR mount_setattr (),
28 necessitating the use of
29 .BR syscall (2).
30 .SH DESCRIPTION
31 The
32 .BR mount_setattr ()
33 system call changes the mount properties of a mount or an entire mount tree.
35 .I pathname
36 is a relative pathname,
37 then it is interpreted relative to
38 the directory referred to by the file descriptor
39 .IR dirfd .
41 .I dirfd
42 is the special value
43 .BR AT_FDCWD ,
44 then
45 .I pathname
46 is interpreted relative to
47 the current working directory of the calling process.
49 .I pathname
50 is the empty string and
51 .B AT_EMPTY_PATH
52 is specified in
53 .IR flags ,
54 then the mount properties of the mount identified by
55 .I dirfd
56 are changed.
57 (See
58 .BR openat (2)
59 for an explanation of why the
60 .I dirfd
61 argument is useful.)
62 .PP
63 The
64 .BR mount_setattr ()
65 system call uses an extensible structure
66 .RI ( "struct mount_attr" )
67 to allow for future extensions.
68 Any non-flag extensions to
69 .BR mount_setattr ()
70 will be implemented as new fields appended to the this structure,
71 with a zero value in a new field resulting in the kernel behaving
72 as though that extension field was not present.
73 Therefore,
74 the caller
75 .I must
76 zero-fill this structure on initialization.
77 See the "Extensibility" subsection under
78 .B NOTES
79 for more details.
80 .PP
81 The
82 .I size
83 argument should usually be specified as
84 .IR "sizeof(struct mount_attr)" .
85 However, if the caller is using a kernel that supports an extended
86 .IR "struct mount_attr" ,
87 but the caller does not intend to make use of these features,
88 it is possible to pass the size of an earlier
89 version of the structure together with the extended structure.
90 This allows the kernel to not copy later parts of the structure
91 that aren't used anyway.
92 With each extension that changes the size of
93 .IR "struct mount_attr" ,
94 the kernel will expose a definition of the form
95 .BI MOUNT_ATTR_SIZE_VER number\c
96 \&.
97 For example, the macro for the size of the initial version of
98 .I struct mount_attr
100 .BR MOUNT_ATTR_SIZE_VER0 .
103 .I flags
104 argument can be used to alter the pathname resolution behavior.
105 The supported values are:
107 .B AT_EMPTY_PATH
109 .I pathname
110 is the empty string,
111 change the mount properties on
112 .I dirfd
113 itself.
115 .B AT_RECURSIVE
116 Change the mount properties of the entire mount tree.
118 .B AT_SYMLINK_NOFOLLOW
119 Don't follow trailing symbolic links.
121 .B AT_NO_AUTOMOUNT
122 Don't trigger automounts.
125 .I attr
126 argument of
127 .BR mount_setattr ()
128 is a structure of the following form:
130 .in +4n
132 struct mount_attr {
133     uint64_t  attr_set;     /* Mount properties to set */
134     uint64_t  attr_clr;     /* Mount properties to clear */
135     uint64_t  propagation;  /* Mount propagation type */
136     uint64_t  userns_fd;    /* User namespace file descriptor */
142 .I attr_set
144 .I attr_clr
145 members are used to specify the mount properties that
146 are supposed to be set or cleared for a mount or mount tree.
147 Flags set in
148 .I attr_set
149 enable a property on a mount or mount tree,
150 and flags set in
151 .I attr_clr
152 remove a property from a mount or mount tree.
154 When changing mount properties,
155 the kernel will first clear the flags specified
156 in the
157 .I attr_clr
158 field,
159 and then set the flags specified in the
160 .I attr_set
161 field.
162 For example, these settings:
164 .in +4n
166 struct mount_attr attr = {
167     .attr_clr = MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV,
168     .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID,
173 are equivalent to the following steps:
175 .in +4n
177 unsigned int current_mnt_flags = mnt->mnt_flags;
180  * Clear all flags set in .attr_clr,
181  * clearing MOUNT_ATTR_NOEXEC and MOUNT_ATTR_NODEV.
182  */
183 current_mnt_flags &= ~attr->attr_clr;
186  * Now set all flags set in .attr_set,
187  * applying MOUNT_ATTR_RDONLY and MOUNT_ATTR_NOSUID.
188  */
189 current_mnt_flags |= attr->attr_set;
191 mnt->mnt_flags = current_mnt_flags;
195 As a result of this change, the mount or mount tree (a) is read-only;
196 (b) blocks the execution of set-user-ID and set-group-ID programs;
197 (c) allows execution of programs; and (d) allows access to devices.
199 Multiple changes with the same set of flags requested
201 .I attr_clr
203 .I attr_set
204 are guaranteed to be idempotent after the changes have been applied.
206 The following mount attributes can be specified in the
207 .I attr_set
209 .I attr_clr
210 fields:
212 .B MOUNT_ATTR_RDONLY
213 If set in
214 .IR attr_set ,
215 makes the mount read-only.
216 If set in
217 .IR attr_clr ,
218 removes the read-only setting if set on the mount.
220 .B MOUNT_ATTR_NOSUID
221 If set in
222 .IR attr_set ,
223 causes the mount not to honor the set-user-ID and set-group-ID mode bits and
224 file capabilities when executing programs.
225 If set in
226 .IR attr_clr ,
227 clears the set-user-ID, set-group-ID,
228 and file capability restriction if set on this mount.
230 .B MOUNT_ATTR_NODEV
231 If set in
232 .IR attr_set ,
233 prevents access to devices on this mount.
234 If set in
235 .IR attr_clr ,
236 removes the restriction that prevented accessing devices on this mount.
238 .B MOUNT_ATTR_NOEXEC
239 If set in
240 .IR attr_set ,
241 prevents executing programs on this mount.
242 If set in
243 .IR attr_clr ,
244 removes the restriction that prevented executing programs on this mount.
246 .B MOUNT_ATTR_NOSYMFOLLOW
247 If set in
248 .IR attr_set ,
249 prevents following symbolic links on this mount.
250 If set in
251 .IR attr_clr ,
252 removes the restriction that prevented following symbolic links on this mount.
254 .B MOUNT_ATTR_NODIRATIME
255 If set in
256 .IR attr_set ,
257 prevents updating access time for directories on this mount.
258 If set in
259 .IR attr_clr ,
260 removes the restriction that prevented updating access time for directories.
261 Note that
262 .B MOUNT_ATTR_NODIRATIME
263 can be combined with other access-time settings
264 and is implied by the noatime setting.
265 All other access-time settings are mutually exclusive.
267 .BR MOUNT_ATTR__ATIME " - changing access-time settings"
268 The access-time values listed below are an enumeration that
269 includes the value zero, expressed in the bits defined by the mask
270 .BR MOUNT_ATTR__ATIME .
271 Even though these bits are an enumeration
272 (in contrast to the other mount flags such as
273 .BR MOUNT_ATTR_NOEXEC ),
274 they are nonetheless passed in
275 .I attr_set
277 .I attr_clr
278 for consistency with
279 .BR fsmount (2),
280 which introduced this behavior.
282 Note that,
283 since the access-time values are an enumeration rather than bit values,
284 a caller wanting to transition to a different access-time setting
285 cannot simply specify the access-time setting in
286 .IR attr_set ,
287 but must also include
288 .B MOUNT_ATTR__ATIME
289 in the
290 .I attr_clr
291 field.
292 The kernel will verify that
293 .B MOUNT_ATTR__ATIME
294 isn't partially set in
295 .I attr_clr
296 (i.e., either all bits in the
297 .B MOUNT_ATTR__ATIME
298 bit field are either set or clear), and that
299 .I attr_set
300 doesn't have any access-time bits set if
301 .B MOUNT_ATTR__ATIME
302 isn't set in
303 .IR attr_clr .
306 .B MOUNT_ATTR_RELATIME
307 When a file is accessed via this mount,
308 update the file's last access time (atime)
309 only if the current value of atime is less than or equal to
310 the file's last modification time (mtime) or last status change time (ctime).
312 To enable this access-time setting on a mount or mount tree,
313 .B MOUNT_ATTR_RELATIME
314 must be set in
315 .I attr_set
317 .B MOUNT_ATTR__ATIME
318 must be set in the
319 .I attr_clr
320 field.
322 .B MOUNT_ATTR_NOATIME
323 Do not update access times for (all types of) files on this mount.
325 To enable this access-time setting on a mount or mount tree,
326 .B MOUNT_ATTR_NOATIME
327 must be set in
328 .I attr_set
330 .B MOUNT_ATTR__ATIME
331 must be set in the
332 .I attr_clr
333 field.
335 .B MOUNT_ATTR_STRICTATIME
336 Always update the last access time (atime)
337 when files are accessed on this mount.
339 To enable this access-time setting on a mount or mount tree,
340 .B MOUNT_ATTR_STRICTATIME
341 must be set in
342 .I attr_set
344 .B MOUNT_ATTR__ATIME
345 must be set in the
346 .I attr_clr
347 field.
350 .B MOUNT_ATTR_IDMAP
351 If set in
352 .IR attr_set ,
353 creates an ID-mapped mount.
354 The ID mapping is taken from the user namespace specified in
355 .I userns_fd
356 and attached to the mount.
358 Since it is not supported to
359 change the ID mapping of a mount after it has been ID mapped,
360 it is invalid to specify
361 .B MOUNT_ATTR_IDMAP
363 .IR attr_clr .
365 For further details, see the subsection "ID-mapped mounts" under NOTES.
368 .I propagation
369 field is used to specify the propagation type of the mount or mount tree.
370 This field either has the value zero,
371 meaning leave the propagation type unchanged, or it has one of
372 the following values:
374 .B MS_PRIVATE
375 Turn all mounts into private mounts.
377 .B MS_SHARED
378 Turn all mounts into shared mounts.
380 .B MS_SLAVE
381 Turn all mounts into dependent mounts.
383 .B MS_UNBINDABLE
384 Turn all mounts into unbindable mounts.
386 For further details on the above propagation types, see
387 .BR mount_namespaces (7).
388 .SH RETURN VALUE
389 On success,
390 .BR mount_setattr ()
391 returns zero.
392 On error,
393 \-1 is returned and
394 .I errno
395 is set to indicate the cause of the error.
396 .SH ERRORS
398 .B EBADF
399 .I pathname
400 is relative but
401 .I dirfd
402 is neither
403 .B AT_FDCWD
404 nor a valid file descriptor.
406 .B EBADF
407 .I userns_fd
408 is not a valid file descriptor.
410 .B EBUSY
411 The caller tried to change the mount to
412 .BR MOUNT_ATTR_RDONLY ,
413 but the mount still holds files open for writing.
415 .B EBUSY
416 The caller tried to create an ID-mapped mount raising
417 .B MOUNT_ATTR_IDMAP
418 and specifying
419 .I userns_fd
420 but the mount still holds files open for writing.
422 .B EINVAL
423 The pathname specified via the
424 .I dirfd
426 .I pathname
427 arguments to
428 .BR mount_setattr ()
429 isn't a mount point.
431 .B EINVAL
432 An unsupported value was set in
433 .IR flags .
435 .B EINVAL
436 An unsupported value was specified in the
437 .I attr_set
438 field of
439 .IR mount_attr .
441 .B EINVAL
442 An unsupported value was specified in the
443 .I attr_clr
444 field of
445 .IR mount_attr .
447 .B EINVAL
448 An unsupported value was specified in the
449 .I propagation
450 field of
451 .IR mount_attr .
453 .B EINVAL
454 More than one of
455 .BR MS_SHARED ,
456 .BR MS_SLAVE ,
457 .BR MS_PRIVATE ,
459 .B MS_UNBINDABLE
460 was set in the
461 .I propagation
462 field of
463 .IR mount_attr .
465 .B EINVAL
466 An access-time setting was specified in the
467 .I attr_set
468 field without
469 .B MOUNT_ATTR__ATIME
470 being set in the
471 .I attr_clr
472 field.
474 .B EINVAL
475 .B MOUNT_ATTR_IDMAP
476 was specified in
477 .IR attr_clr .
479 .B EINVAL
480 A file descriptor value was specified in
481 .I userns_fd
482 which exceeds
483 .BR INT_MAX .
485 .B EINVAL
486 A valid file descriptor value was specified in
487 .IR userns_fd ,
488 but the file descriptor did not refer to a user namespace.
490 .B EINVAL
491 The underlying filesystem does not support ID-mapped mounts.
493 .B EINVAL
494 The mount that is to be ID mapped is not a detached mount;
495 that is, the mount has not previously been visible in a mount namespace.
497 .B EINVAL
498 A partial access-time setting was specified in
499 .I attr_clr
500 instead of
501 .B MOUNT_ATTR__ATIME
502 being set.
504 .B EINVAL
505 The mount is located outside the caller's mount namespace.
507 .B EINVAL
508 The underlying filesystem has been mounted in a mount namespace that is
509 owned by a noninitial user namespace
511 .B ENOENT
512 A pathname was empty or had a nonexistent component.
514 .B ENOMEM
515 When changing mount propagation to
516 .BR MS_SHARED ,
517 a new peer group ID needs to be allocated for all mounts without a peer group
518 ID set.
519 This allocation failed because there was not
520 enough memory to allocate the relevant internal structures.
522 .B ENOSPC
523 When changing mount propagation to
524 .BR MS_SHARED ,
525 a new peer group ID needs to be allocated for all mounts without a peer group
526 ID set.
527 This allocation failed because
528 the kernel has run out of IDs.
529 .\" Christian Brauner: i.e. someone has somehow managed to
530 .\" allocate so many peer groups and managed to keep the kernel running
531 .\" (???) that the ida has ran out of ids
532 .\" Note that technically further error codes are possible that are
533 .\" specific to the ID allocation implementation used.
535 .B EPERM
536 One of the mounts had at least one of
537 .BR MOUNT_ATTR_NOATIME ,
538 .BR MOUNT_ATTR_NODEV ,
539 .BR MOUNT_ATTR_NODIRATIME ,
540 .BR MOUNT_ATTR_NOEXEC ,
541 .BR MOUNT_ATTR_NOSUID ,
543 .B MOUNT_ATTR_RDONLY
544 set and the flag is locked.
545 Mount attributes become locked on a mount if:
547 .IP \(bu 3
548 A new mount or mount tree is created causing mount propagation across user
549 namespaces
550 (i.e., propagation to a mount namespace owned by a different user namespace).
551 The kernel will lock the aforementioned flags to prevent these sensitive
552 properties from being altered.
553 .IP \(bu
554 A new mount and user namespace pair is created.
555 This happens for example when specifying
556 .B CLONE_NEWUSER | CLONE_NEWNS
558 .BR unshare (2),
559 .BR clone (2),
561 .BR clone3 (2).
562 The aforementioned flags become locked in the new mount namespace
563 to prevent sensitive mount properties from being altered.
564 Since the newly created mount namespace will be owned by the
565 newly created user namespace,
566 a calling process that is privileged in the new
567 user namespace would\(emin the absence of such locking\(embe
568 able to alter sensitive mount properties (e.g., to remount a mount
569 that was marked read-only as read-write in the new mount namespace).
572 .B EPERM
573 A valid file descriptor value was specified in
574 .IR userns_fd ,
575 but the file descriptor refers to the initial user namespace.
577 .B EPERM
578 An attempt was made to add an ID mapping to a mount that is already ID mapped.
580 .B EPERM
581 The caller does not have
582 .B CAP_SYS_ADMIN
583 in the initial user namespace.
584 .SH VERSIONS
585 .BR mount_setattr ()
586 first appeared in Linux 5.12.
587 .\" commit 7d6beb71da3cc033649d641e1e608713b8220290
588 .\" commit 2a1867219c7b27f928e2545782b86daaf9ad50bd
589 .\" commit 9caccd41541a6f7d6279928d9f971f6642c361af
590 .SH STANDARDS
591 .BR mount_setattr ()
592 is Linux-specific.
593 .SH NOTES
594 .SS ID-mapped mounts
595 Creating an ID-mapped mount makes it possible to
596 change the ownership of all files located under a mount.
597 Thus, ID-mapped mounts make it possible to
598 change ownership in a temporary and localized way.
599 It is a localized change because the ownership changes are
600 visible only via a specific mount.
601 All other users and locations where the filesystem is exposed are unaffected.
602 It is a temporary change because
603 the ownership changes are tied to the lifetime of the mount.
605 Whenever callers interact with the filesystem through an ID-mapped mount,
606 the ID mapping of the mount will be applied to
607 user and group IDs associated with filesystem objects.
608 This encompasses the user and group IDs associated with inodes
609 and also the following
610 .BR xattr (7)
611 keys:
612 .IP \(bu 3
613 .IR security.capability ,
614 whenever filesystem capabilities
615 are stored or returned in the
616 .B VFS_CAP_REVISION_3
617 format,
618 which stores a root user ID alongside the capabilities
619 (see
620 .BR capabilities (7)).
621 .IP \(bu
622 .I system.posix_acl_access
624 .IR system.posix_acl_default ,
625 whenever user IDs or group IDs are stored in
626 .B ACL_USER
628 .B ACL_GROUP
629 entries.
631 The following conditions must be met in order to create an ID-mapped mount:
632 .IP \(bu 3
633 The caller must have the
634 .B CAP_SYS_ADMIN
635 capability in the user namespace the filesystem was mounted in.
636 .\" commit bd303368b776eead1c29e6cdda82bde7128b82a7
637 .\" Christian Brauner
638 .\"     Note, currently no filesystems mountable in non-initial user namespaces
639 .\"     support ID-mapped mounts.
640 .IP \(bu
641 The underlying filesystem must support ID-mapped mounts.
642 Currently, the following filesystems support ID-mapped mounts:
643 .\" fs_flags = FS_ALLOW_IDMAP in kernel sources
645 .RS 3
646 .PD 0
647 .IP \(bu 3
648 .BR xfs (5)
649 (since Linux 5.12)
650 .IP \(bu
651 .BR ext4 (5)
652 (since Linux 5.12)
653 .IP \(bu
654 .B FAT
655 (since Linux 5.12)
656 .IP \(bu
657 .BR btrfs (5)
658 (since Linux 5.15)
659 .\" commit 5b9b26f5d0b88b74001dcfe4ab8a8f2f4e744112
660 .IP \(bu
661 .B ntfs3
662 (since Linux 5.15)
663 .\" commit 82cae269cfa953032fbb8980a7d554d60fb00b17
664 .IP \(bu
665 .B f2fs
666 (since Linux 5.18)
667 .\" commit 984fc4e76d63345499f01c0c198a4b44860cf027
668 .IP \(bu
669 .B erofs
670 (since Linux 5.19)
671 .\" commit 6c459b78d4793afbba6d864c466cc5cd2932459d
672 .IP \(bu
673 .B overlayfs
674 (ID-mapped lower and upper layers supported since Linux 5.19)
677 .IP \(bu 3
678 The mount must not already be ID-mapped.
679 This also implies that the ID mapping of a mount cannot be altered.
680 .IP \(bu
681 The mount must be a detached mount;
682 that is,
683 it must have been created by calling
684 .IP \(bu
685 The mount must not have any writers.
686 .\" commit 1bbcd277a53e08d619ffeec56c5c9287f2bf42f
687 .BR open_tree (2)
688 with the
689 .B OPEN_TREE_CLONE
690 flag and it must not already have been visible in a mount namespace.
691 (To put things another way:
692 the mount must not have been attached to the filesystem hierarchy
693 with a system call such as
694 .BR move_mount (2).)
696 ID mappings can be created for user IDs, group IDs, and project IDs.
697 An ID mapping is essentially a mapping of a range of user or group IDs into
698 another or the same range of user or group IDs.
699 ID mappings are written to map files as three numbers
700 separated by white space.
701 The first two numbers specify the starting user or group ID
702 in each of the two user namespaces.
703 The third number specifies the range of the ID mapping.
704 For example,
705 a mapping for user IDs such as "1000\ 1001\ 1" would indicate that
706 user ID 1000 in the caller's user namespace is mapped to
707 user ID 1001 in its ancestor user namespace.
708 Since the map range is 1,
709 only user ID 1000 is mapped.
711 It is possible to specify up to 340 ID mappings for each ID mapping type.
712 If any user IDs or group IDs are not mapped,
713 all files owned by that unmapped user or group ID will appear as
714 being owned by the overflow user ID or overflow group ID respectively.
716 Further details on setting up ID mappings can be found in
717 .BR user_namespaces (7).
719 In the common case, the user namespace passed in
720 .I userns_fd
721 (together with
722 .B MOUNT_ATTR_IDMAP
724 .IR attr_set )
725 to create an ID-mapped mount will be the user namespace of a container.
726 In other scenarios it will be a dedicated user namespace associated with
727 a user's login session as is the case for portable home directories in
728 .BR systemd-homed.service (8)).
729 It is also perfectly fine to create a dedicated user namespace
730 for the sake of ID mapping a mount.
732 ID-mapped mounts can be useful in the following
733 and a variety of other scenarios:
734 .IP \(bu 3
735 Sharing files or filesystems
736 between multiple users or multiple machines,
737 especially in complex scenarios.
738 For example,
739 ID-mapped mounts are used to implement portable home directories in
740 .BR systemd-homed.service (8),
741 where they allow users to move their home directory
742 to an external storage device
743 and use it on multiple computers
744 where they are assigned different user IDs and group IDs.
745 This effectively makes it possible to
746 assign random user IDs and group IDs at login time.
747 .IP \(bu
748 Sharing files or filesystems
749 from the host with unprivileged containers.
750 This allows a user to avoid having to change ownership permanently through
751 .BR chown (2).
752 .IP \(bu
753 ID mapping a container's root filesystem.
754 Users don't need to change ownership permanently through
755 .BR chown (2).
756 Especially for large root filesystems, using
757 .BR chown (2)
758 can be prohibitively expensive.
759 .IP \(bu
760 Sharing files or filesystems
761 between containers with non-overlapping ID mappings.
762 .IP \(bu
763 Implementing discretionary access (DAC) permission checking
764 for filesystems lacking a concept of ownership.
765 .IP \(bu
766 Efficiently changing ownership on a per-mount basis.
767 In contrast to
768 .BR chown (2),
769 changing ownership of large sets of files is instantaneous with
770 ID-mapped mounts.
771 This is especially useful when ownership of
772 an entire root filesystem of a virtual machine or container
773 is to be changed as mentioned above.
774 With ID-mapped mounts,
775 a single
776 .BR mount_setattr ()
777 system call will be sufficient to change the ownership of all files.
778 .IP \(bu
779 Taking the current ownership into account.
780 ID mappings specify precisely
781 what a user or group ID is supposed to be mapped to.
782 This contrasts with the
783 .BR chown (2)
784 system call which cannot by itself
785 take the current ownership of the files it changes into account.
786 It simply changes the ownership to the specified user ID and group ID.
787 .IP \(bu
788 Locally and temporarily restricted ownership changes.
789 ID-mapped mounts make it possible to change ownership locally,
790 restricting the ownership changes to specific mounts,
791 and temporarily as the ownership changes only apply as long as the mount exists.
792 By contrast,
793 changing ownership via the
794 .BR chown (2)
795 system call changes the ownership globally and permanently.
797 .SS Extensibility
798 In order to allow for future extensibility,
799 .BR mount_setattr ()
800 requires the user-space application to specify the size of the
801 .I mount_attr
802 structure that it is passing.
803 By providing this information, it is possible for
804 .BR mount_setattr ()
805 to provide both forwards- and backwards-compatibility, with
806 .I size
807 acting as an implicit version number.
808 (Because new extension fields will always
809 be appended, the structure size will always increase.)
810 This extensibility design is very similar to other system calls such as
811 .BR perf_setattr (2),
812 .BR perf_event_open (2),
813 .BR clone3 (2)
815 .BR openat2 (2).
818 .I usize
819 be the size of the structure as specified by the user-space application,
820 and let
821 .I ksize
822 be the size of the structure which the kernel supports,
823 then there are three cases to consider:
824 .IP \(bu 3
826 .I ksize
827 equals
828 .IR usize ,
829 then there is no version mismatch and
830 .I attr
831 can be used verbatim.
832 .IP \(bu
834 .I ksize
835 is larger than
836 .IR usize ,
837 then there are some extension fields that the kernel supports
838 which the user-space application is unaware of.
839 Because a zero value in any added extension field signifies a no-op,
840 the kernel treats all of the extension fields
841 not provided by the user-space application
842 as having zero values.
843 This provides backwards-compatibility.
844 .IP \(bu
846 .I ksize
847 is smaller than
848 .IR usize ,
849 then there are some extension fields which the user-space application is aware
850 of but which the kernel does not support.
851 Because any extension field must have its zero values signify a no-op,
852 the kernel can safely ignore the unsupported extension fields
853 if they are all zero.
854 If any unsupported extension fields are non-zero,
855 then \-1 is returned and
856 .I errno
857 is set to
858 .BR E2BIG .
859 This provides forwards-compatibility.
861 Because the definition of
862 .I struct mount_attr
863 may change in the future
864 (with new fields being added when system headers are updated),
865 user-space applications should zero-fill
866 .I struct mount_attr
867 to ensure that recompiling the program with new headers will not result in
868 spurious errors at runtime.
869 The simplest way is to use a designated initializer:
871 .in +4n
873 struct mount_attr attr = {
874     .attr_set = MOUNT_ATTR_RDONLY,
875     .attr_clr = MOUNT_ATTR_NODEV
880 Alternatively, the structure can be zero-filled using
881 .BR memset (3)
882 or similar functions:
884 .in +4n
886 struct mount_attr attr;
887 memset(&attr, 0, sizeof(attr));
888 attr.attr_set = MOUNT_ATTR_RDONLY;
889 attr.attr_clr = MOUNT_ATTR_NODEV;
893 A user-space application that wishes to determine which extensions the running
894 kernel supports can do so by conducting a binary search on
895 .I size
896 with a structure which has every byte nonzero
897 (to find the largest value which doesn't produce an error of
898 .BR E2BIG ).
899 .SH EXAMPLES
900 .\" SRC BEGIN (mount_setattr.c)
903  * This program allows the caller to create a new detached mount
904  * and set various properties on it.
905  */
906 #define _GNU_SOURCE
907 #include <errno.h>
908 #include <fcntl.h>
909 #include <getopt.h>
910 #include <linux/mount.h>
911 #include <linux/types.h>
912 #include <stdbool.h>
913 #include <stdio.h>
914 #include <stdlib.h>
915 #include <string.h>
916 #include <sys/syscall.h>
917 #include <unistd.h>
919 static inline int
920 mount_setattr(int dirfd, const char *pathname, unsigned int flags,
921               struct mount_attr *attr, size_t size)
923     return syscall(SYS_mount_setattr, dirfd, pathname, flags,
924                    attr, size);
927 static inline int
928 open_tree(int dirfd, const char *filename, unsigned int flags)
930     return syscall(SYS_open_tree, dirfd, filename, flags);
933 static inline int
934 move_mount(int from_dirfd, const char *from_pathname,
935            int to_dirfd, const char *to_pathname, unsigned int flags)
937     return syscall(SYS_move_mount, from_dirfd, from_pathname,
938                    to_dirfd, to_pathname, flags);
941 static const struct option longopts[] = {
942     {"map\-mount",       required_argument,  NULL,  \(aqa\(aq},
943     {"recursive",       no_argument,        NULL,  \(aqb\(aq},
944     {"read\-only",       no_argument,        NULL,  \(aqc\(aq},
945     {"block\-setid",     no_argument,        NULL,  \(aqd\(aq},
946     {"block\-devices",   no_argument,        NULL,  \(aqe\(aq},
947     {"block\-exec",      no_argument,        NULL,  \(aqf\(aq},
948     {"no\-access\-time",  no_argument,        NULL,  \(aqg\(aq},
949     { NULL,             0,                  NULL,   0 },
952 #define exit_log(format, ...)  do           \e
953 {                                           \e
954     fprintf(stderr, format, ##__VA_ARGS__); \e
955     exit(EXIT_FAILURE);                     \e
956 } while (0)
959 main(int argc, char *argv[])
961     struct mount_attr *attr = &(struct mount_attr){};
962     int fd_userns = \-1;
963     bool recursive = false;
964     int index = 0;
965     int ret;
967     while ((ret = getopt_long_only(argc, argv, "",
968                                    longopts, &index)) != \-1) {
969         switch (ret) {
970         case \(aqa\(aq:
971             fd_userns = open(optarg, O_RDONLY | O_CLOEXEC);
972             if (fd_userns == \-1)
973                 exit_log("%m \- Failed top open %s\en", optarg);
974             break;
975         case \(aqb\(aq:
976             recursive = true;
977             break;
978         case \(aqc\(aq:
979             attr\->attr_set |= MOUNT_ATTR_RDONLY;
980             break;
981         case \(aqd\(aq:
982             attr\->attr_set |= MOUNT_ATTR_NOSUID;
983             break;
984         case \(aqe\(aq:
985             attr\->attr_set |= MOUNT_ATTR_NODEV;
986             break;
987         case \(aqf\(aq:
988             attr\->attr_set |= MOUNT_ATTR_NOEXEC;
989             break;
990         case \(aqg\(aq:
991             attr\->attr_set |= MOUNT_ATTR_NOATIME;
992             attr\->attr_clr |= MOUNT_ATTR__ATIME;
993             break;
994         default:
995             exit_log("Invalid argument specified");
996         }
997     }
999     if ((argc \- optind) < 2)
1000         exit_log("Missing source or target mount point\en");
1002     const char *source = argv[optind];
1003     const char *target = argv[optind + 1];
1005     /* In the following, \-1 as the \(aqdirfd\(aq argument ensures that
1006        open_tree() fails if \(aqsource\(aq is not an absolute pathname. */
1007 .\" Christian Brauner
1008 .\"     When writing programs I like to never use relative paths with AT_FDCWD
1009 .\"     because. Because making assumptions about the current working directory
1010 .\"     of the calling process is just too easy to get wrong; especially when
1011 .\"     pivot_root() or chroot() are in play.
1012 .\"     My absolut preference (joke intended) is to open a well-known starting
1013 .\"     point with an absolute path to get a dirfd and then scope all future
1014 .\"     operations beneath that dirfd. This already works with old-style
1015 .\"     openat() and _very_ cautious programming but openat2() and its
1016 .\"     resolve-flag space have made this **chef's kiss**.
1017 .\"     If I can't operate based on a well-known dirfd I use absolute paths
1018 .\"     with a -EBADF dirfd passed to *at() functions.
1020     int fd_tree = open_tree(\-1, source,
1021                        OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC |
1022                        AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0));
1023     if (fd_tree == \-1)
1024         exit_log("%m \- Failed to open %s\en", source);
1026     if (fd_userns >= 0) {
1027         attr\->attr_set  |= MOUNT_ATTR_IDMAP;
1028         attr\->userns_fd = fd_userns;
1029     }
1031     ret = mount_setattr(fd_tree, "",
1032                         AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0),
1033                         attr, sizeof(struct mount_attr));
1034     if (ret == \-1)
1035         exit_log("%m \- Failed to change mount attributes\en");
1037     close(fd_userns);
1039     /* In the following, \-1 as the \(aqto_dirfd\(aq argument ensures that
1040        open_tree() fails if \(aqtarget\(aq is not an absolute pathname. */
1042     ret = move_mount(fd_tree, "", \-1, target,
1043                      MOVE_MOUNT_F_EMPTY_PATH);
1044     if (ret == \-1)
1045         exit_log("%m \- Failed to attach mount to %s\en", target);
1047     close(fd_tree);
1049     exit(EXIT_SUCCESS);
1052 .\" SRC END
1053 .SH SEE ALSO
1054 .BR newgidmap (1),
1055 .BR newuidmap (1),
1056 .BR clone (2),
1057 .BR mount (2),
1058 .BR unshare (2),
1059 .BR proc (5),
1060 .BR capabilities (7),
1061 .BR mount_namespaces (7),
1062 .BR user_namespaces (7),
1063 .BR xattr (7)