mount_setattr.2: Changes after review feedback from Christian Brauner
[man-pages.git] / man2 / mount_setattr.2
blob875834637656fcb06801a28f4061c705d5d810c8
1 .\" Copyright (c) 2021 by Christian Brauner <christian.brauner@ubuntu.com>
2 .\"
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.
7 .\"
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.
12 .\"
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
19 .\" professionally.
20 .\"
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
23 .\" %%%LICENSE_END
24 .\"
25 .TH MOUNT_SETATTR 2 2021-03-22 "Linux" "Linux Programmer's Manual"
26 .SH NAME
27 mount_setattr \- change properties of a mount or mount tree
28 .SH SYNOPSIS
29 .nf
31 .PP
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>
36 .PP
37 .BI "int syscall(SYS_mount_setattr, int " dirfd ", const char *" path ,
38 .BI "            unsigned int " flags ", struct mount_attr *" attr \
39 ", size_t " size );
40 .fi
41 .PP
42 .IR Note :
43 glibc provides no wrapper for
44 .BR mount_setattr (),
45 necessitating the use of
46 .BR syscall (2).
47 .SH DESCRIPTION
48 The
49 .BR mount_setattr ()
50 system call changes the mount properties of a mount or an entire mount tree.
52 .I path
53 is a relative pathname,
54 then it is interpreted relative to
55 the directory referred to by the file descriptor
56 .IR dirfd .
58 .I dirfd
59 is the special value
60 .BR AT_FDCWD ,
61 then
62 .I path
63 is interpreted relative to
64 the current working directory of the calling process.
66 .I path
67 is the empty string and
68 .B AT_EMPTY_PATH
69 is specified in
70 .IR flags ,
71 then the mount properties of the mount identified by
72 .I dirfd
73 are changed.
74 .PP
75 The
76 .BR mount_setattr ()
77 system call uses an extensible structure
78 .RI ( "struct mount_attr" )
79 to allow for future extensions.
80 Any non-flag extensions to
81 .BR mount_setattr ()
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.
85 Therefore,
86 the caller
87 .I must
88 zero-fill this structure on initialization.
89 See the "Extensibility" subsection under
90 .B NOTES
91 for more details.
92 .PP
93 The
94 .I size
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
110 .I struct mount_attr
112 .BR MOUNT_ATTR_SIZE_VER0 .
115 .I flags
116 argument can be used to alter the path resolution behavior.
117 The supported values are:
119 .B AT_EMPTY_PATH
121 .I path
122 is the empty string,
123 change the mount properties on
124 .I dirfd
125 itself.
127 .B AT_RECURSIVE
128 Change the mount properties of the entire mount tree.
130 .B AT_SYMLINK_NOFOLLOW
131 Don't follow trailing symbolic links.
133 .B AT_NO_AUTOMOUNT
134 Don't trigger automounts.
137 .I attr
138 argument of
139 .BR mount_setattr ()
140 is a structure of the following form:
142 .in +4n
144 struct mount_attr {
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 */
154 .I attr_set
156 .I attr_clr
157 members are used to specify the mount properties that
158 are supposed to be set or cleared for a mount or mount tree.
159 Flags set in
160 .I attr_set
161 enable a property on a mount or mount tree,
162 and flags set in
163 .I attr_clr
164 remove a property from a mount or mount tree.
166 When changing mount properties,
167 the kernel will first clear the flags specified
168 in the
169 .I attr_clr
170 field,
171 and then set the flags specified in the
172 .I attr_set
173 field.
174 For example, these settings:
176 .in +4n
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:
187 .in +4n
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.
194  */
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.
200  */
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
213 .I attr_clr
215 .I attr_set
216 are guaranteed to be idempotent after the changes have been applied.
218 The following mount attributes can be specified in the
219 .I attr_set
221 .I attr_clr
222 fields:
224 .B MOUNT_ATTR_RDONLY
225 If set in
226 .IR attr_set ,
227 makes the mount read-only.
228 If set in
229 .IR attr_clr ,
230 removes the read-only setting if set on the mount.
232 .B MOUNT_ATTR_NOSUID
233 If set in
234 .IR attr_set ,
235 causes the mount not to honor the set-user-ID and set-group-ID mode bits and
236 file capabilities when executing programs.
237 If set in
238 .IR attr_clr ,
239 clears the set-user-ID, set-group-ID,
240 and file capability restriction if set on this mount.
242 .B MOUNT_ATTR_NODEV
243 If set in
244 .IR attr_set ,
245 prevents access to devices on this mount.
246 If set in
247 .IR attr_clr ,
248 removes the restriction that prevented accessing devices on this mount.
250 .B MOUNT_ATTR_NOEXEC
251 If set in
252 .IR attr_set ,
253 prevents executing programs on this mount.
254 If set in
255 .IR attr_clr ,
256 removes the restriction that prevented executing programs on this mount.
258 .B MOUNT_ATTR_NOSYMFOLLOW
259 If set in
260 .IR attr_set ,
261 prevents following symbolic links on this mount.
262 If set in
263 .IR attr_clr ,
264 removes the restriction that prevented following symbolic links on this mount.
266 .B MOUNT_ATTR_NODIRATIME
267 If set in
268 .IR attr_set ,
269 prevents updating access time for directories on this mount.
270 If set in
271 .IR attr_clr ,
272 removes the restriction that prevented updating access time for directories.
273 Note that
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
287 .I attr_set
289 .I attr_clr
290 for consistency with
291 .BR fsmount (2),
292 which introduced this behavior.
294 Note that,
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
298 .IR attr_set ,
299 but must also include
300 .B MOUNT_ATTR__ATIME
301 in the
302 .I attr_clr
303 field.
304 The kernel will verify that
305 .B MOUNT_ATTR__ATIME
306 isn't partially set in
307 .IR attr_clr
308 (i.e., either all bits in the
309 .B MOUNT_ATTR__ATIME
310 bit field are either set or clear), and that
311 .I attr_set
312 doesn't have any access-time bits set if
313 .B MOUNT_ATTR__ATIME
314 isn't set in
315 .IR attr_clr .
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
326 must be set in
327 .I attr_set
329 .B MOUNT_ATTR__ATIME
330 must be set in the
331 .I attr_clr
332 field.
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
339 must be set in
340 .I attr_set
342 .B MOUNT_ATTR__ATIME
343 must be set in the
344 .I attr_clr
345 field.
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
353 must be set in
354 .I attr_set
356 .B MOUNT_ATTR__ATIME
357 must be set in the
358 .I attr_clr
359 field.
362 .B MOUNT_ATTR_IDMAP
363 If set in
364 .IR attr_set ,
365 creates an ID-mapped mount.
366 The ID mapping is taken from the user namespace specified in
367 .I userns_fd
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
373 .B MOUNT_ATTR_IDMAP
375 .IR attr_clr .
377 For further details, see the subsection "ID-mapped mounts" under NOTES.
380 .I propagation
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:
386 .B MS_PRIVATE
387 Turn all mounts into private mounts.
389 .B MS_SHARED
390 Turn all mounts into shared mounts.
392 .B MS_SLAVE
393 Turn all mounts into dependent mounts.
395 .B MS_UNBINDABLE
396 Turn all mounts into unbindable mounts.
398 For further details on the above propagation types, see
399 .BR mount_namespaces (7).
400 .SH RETURN VALUE
401 On success,
402 .BR mount_setattr ()
403 returns zero.
404 On error,
405 \-1 is returned and
406 .I errno
407 is set to indicate the cause of the error.
408 .SH ERRORS
410 .B EBADF
411 .I dirfd
412 is not a valid file descriptor.
414 .B EBADF
415 .I userns_fd
416 is not a valid file descriptor.
418 .B EBUSY
419 The caller tried to change the mount to
420 .BR MOUNT_ATTR_RDONLY ,
421 but the mount still holds files open for writing.
423 .B EINVAL
424 The path specified via the
425 .I dirfd
427 .I path
428 arguments to
429 .BR mount_setattr ()
430 isn't a mount point.
432 .B EINVAL
433 An unsupported value was set in
434 .I flags.
436 .B EINVAL
437 An unsupported value was specified in the
438 .I attr_set
439 field of
440 .IR mount_attr .
442 .B EINVAL
443 An unsupported value was specified in the
444 .I attr_clr
445 field of
446 .IR mount_attr .
448 .B EINVAL
449 An unsupported value was specified in the
450 .I propagation
451 field of
452 .IR mount_attr .
454 .B EINVAL
455 More than one of
456 .BR MS_SHARED ,
457 .BR MS_SLAVE ,
458 .BR MS_PRIVATE ,
460 .B MS_UNBINDABLE
461 was set in the
462 .I propagation
463 field of
464 .IR mount_attr .
466 .B EINVAL
467 An access-time setting was specified in the
468 .I attr_set
469 field without
470 .B MOUNT_ATTR__ATIME
471 being set in the
472 .I attr_clr
473 field.
475 .B EINVAL
476 .B MOUNT_ATTR_IDMAP
477 was specified in
478 .IR attr_clr .
480 .B EINVAL
481 A file descriptor value was specified in
482 .I userns_fd
483 which exceeds
484 .BR INT_MAX .
486 .B EINVAL
487 A valid file descriptor value was specified in
488 .IR userns_fd ,
489 but the file descriptor did not refer to a user namespace.
491 .B EINVAL
492 The underlying filesystem does not support ID-mapped mounts.
494 .B EINVAL
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.
498 .B EINVAL
499 A partial access-time setting was specified in
500 .I attr_clr
501 instead of
502 .B MOUNT_ATTR__ATIME
503 being set.
505 .B EINVAL
506 The mount is located outside the caller's mount namespace.
508 .B EINVAL
509 The underlying filesystem is mounted in a 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 Allocation of this peer group ID has failed.
521 .B ENOSPC
522 When changing mount propagation to
523 .BR MS_SHARED ,
524 a new peer group ID needs to be allocated for all mounts without a peer group
525 ID set.
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.
530 .B EPERM
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 ,
538 .B MOUNT_ATTR_RDONLY
539 set and the flag is locked.
540 Mount attributes become locked on a mount if:
542 .IP \(bu 3
543 A new mount or mount tree is created causing mount propagation across user
544 namespaces.
545 The kernel will lock the aforementioned flags to protect these sensitive
546 properties from being altered.
547 .IP \(bu
548 A new mount and user namespace pair is created.
549 This happens for example when specifying
550 .B CLONE_NEWUSER | CLONE_NEWNS
552 .BR unshare (2),
553 .BR clone (2),
555 .BR clone3 (2).
556 The aforementioned flags become locked to protect user namespaces from altering
557 sensitive mount properties.
560 .B EPERM
561 A valid file descriptor value was specified in
562 .IR userns_fd ,
563 but the file descriptor refers to the initial user namespace.
565 .B EPERM
566 An attempt was made to add an ID mapping to a mount that is already ID mapped.
568 .B EPERM
569 The caller does not have
570 .B CAP_SYS_ADMIN
571 in the initial user namespace.
572 .SH VERSIONS
573 .BR mount_setattr ()
574 first appeared in Linux 5.12.
575 .\" commit 7d6beb71da3cc033649d641e1e608713b8220290
576 .\" commit 2a1867219c7b27f928e2545782b86daaf9ad50bd
577 .\" commit 9caccd41541a6f7d6279928d9f971f6642c361af
578 .SH CONFORMING TO
579 .BR mount_setattr ()
580 is Linux-specific.
581 .SH NOTES
582 .SS ID-mapped mounts
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
598 .BR xattr (7)
599 keys:
600 .IP \(bu 3
601 .IR security.capability ,
602 whenever filesystem capabilities
603 are stored or returned in the
604 .B VFS_CAP_REVISION_3
605 format,
606 which stores a root user ID alongside the capabilities
607 (see
608 .BR capabilities (7)).
609 .IP \(bu
610 .I system.posix_acl_access
612 .IR system.posix_acl_default ,
613 whenever user IDs or group IDs are stored in
614 .B ACL_USER
616 .B ACL_GROUP
617 entries.
619 The following conditions must be met in order to create an ID-mapped mount:
620 .IP \(bu 3
621 The caller must have the
622 .B CAP_SYS_ADMIN
623 capability in the initial user namespace.
624 .IP \(bu
625 The filesystem must be mounted in a mount namespace
626 that is owned by the initial user namespace.
627 .IP \(bu
628 The underlying filesystem must support ID-mapped mounts.
629 Currently, the
630 .BR xfs (5),
631 .BR ext4 (5),
633 .B FAT
634 filesystems support ID-mapped mounts
635 with more filesystems being actively worked on.
636 .IP \(bu
637 The mount must not already be ID-mapped.
638 This also implies that the ID mapping of a mount cannot be altered.
639 .IP \(bu
640 The mount must be a detached mount;
641 that is,
642 it must have been created by calling
643 .BR open_tree (2)
644 with the
645 .B OPEN_TREE_CLONE
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.
656 For example,
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)
670 man page.
672 In the common case, the user namespace passed in
673 .I userns_fd
674 together with
675 .B MOUNT_ATTR_IDMAP
677 .I attr_set
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:
687 .IP \(bu 3
688 Sharing files or filesystems
689 between multiple users or multiple machines,
690 especially in complex scenarios.
691 For example,
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.
700 .IP \(bu
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
704 .BR chown (2).
705 .IP \(bu
706 ID mapping a container's root filesystem.
707 Users don't need to change ownership permanently through
708 .BR chown (2).
709 Especially for large root filesystems, using
710 .BR chown (2)
711 can be prohibitively expensive.
712 .IP \(bu
713 Sharing files or filesystems
714 between containers with non-overlapping ID mappings.
715 .IP \(bu
716 Implementing discretionary access (DAC) permission checking
717 for filesystems lacking a concept of ownership.
718 .IP \(bu
719 Efficiently changing ownership on a per-mount basis.
720 In contrast to
721 .BR chown (2),
722 changing ownership of large sets of files is instantaneous with
723 ID-mapped mounts.
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,
728 a single
729 .BR mount_setattr ()
730 system call will be sufficient to change the ownership of all files.
731 .IP \(bu
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
736 .BR chown (2)
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.
740 .IP \(bu
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.
745 By contrast,
746 changing ownership via the
747 .BR chown (2)
748 system call changes the ownership globally and permanently.
750 .SS Extensibility
751 In order to allow for future extensibility,
752 .BR mount_setattr ()
753 requires the user-space application to specify the size of the
754 .I mount_attr
755 structure that it is passing.
756 By providing this information, it is possible for
757 .BR mount_setattr ()
758 to provide both forwards- and backwards-compatibility, with
759 .I size
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),
766 .BR clone3 (2)
768 .BR openat2 (2).
771 .I usize
772 be the size of the structure as specified by the user-space application,
773 and let
774 .I ksize
775 be the size of the structure which the kernel supports,
776 then there are three cases to consider:
777 .IP \(bu 3
779 .I ksize
780 equals
781 .IR usize ,
782 then there is no version mismatch and
783 .I attr
784 can be used verbatim.
785 .IP \(bu
787 .I ksize
788 is larger than
789 .IR usize ,
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.
797 .IP \(bu
799 .I ksize
800 is smaller than
801 .IR usize ,
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
809 .I errno
810 is set to
811 .BR E2BIG .
812 This provides forwards-compatibility.
814 Because the definition of
815 .I struct mount_attr
816 may change in the future
817 (with new fields being added when system headers are updated),
818 user-space applications should zero-fill
819 .I struct mount_attr
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:
824 .in +4n
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
834 .BR memset (3)
835 or similar functions:
837 .in +4n
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
848 .I size
849 with a structure which has every byte nonzero
850 (to find the largest value which doesn't produce an error of
851 .BR E2BIG ).
852 .SH EXAMPLES
855  * This program allows the caller to create a new detached mount
856  * and set various properties on it.
857  */
858 #define _GNU_SOURCE
859 #include <errno.h>
860 #include <fcntl.h>
861 #include <getopt.h>
862 #include <linux/mount.h>
863 #include <linux/types.h>
864 #include <stdbool.h>
865 #include <stdio.h>
866 #include <stdlib.h>
867 #include <string.h>
868 #include <sys/syscall.h>
869 #include <unistd.h>
871 static inline int
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);
878 static inline int
879 open_tree(int dirfd, const char *filename, unsigned int flags)
881     return syscall(SYS_open_tree, dirfd, filename, flags);
884 static inline int
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
904 {                                           \e
905     fprintf(stderr, format, ##__VA_ARGS__); \e
906     exit(EXIT_FAILURE);                     \e
907 } while (0)
910 main(int argc, char *argv[])
912     struct mount_attr *attr = &(struct mount_attr){};
913     int fd_userns = \-1;
914     bool recursive = false;
915     int index = 0;
916     int ret;
918     while ((ret = getopt_long_only(argc, argv, "",
919                                    longopts, &index)) != \-1) {
920         switch (ret) {
921         case 'a':
922             fd_userns = open(optarg, O_RDONLY | O_CLOEXEC);
923             if (fd_userns == \-1)
924                 exit_log("%m \- Failed top open %s\en", optarg);
925             break;
926         case 'b':
927             recursive = true;
928             break;
929         case 'c':
930             attr\->attr_set |= MOUNT_ATTR_RDONLY;
931             break;
932         case 'd':
933             attr\->attr_set |= MOUNT_ATTR_NOSUID;
934             break;
935         case 'e':
936             attr\->attr_set |= MOUNT_ATTR_NODEV;
937             break;
938         case 'f':
939             attr\->attr_set |= MOUNT_ATTR_NOEXEC;
940             break;
941         case 'g':
942             attr\->attr_set |= MOUNT_ATTR_NOATIME;
943             attr\->attr_clr |= MOUNT_ATTR__ATIME;
944             break;
945         default:
946             exit_log("Invalid argument specified");
947         }
948     }
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));
959     if (fd_tree == \-1)
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;
965     }
967     ret = mount_setattr(fd_tree, "",
968                         AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0),
969                         attr, sizeof(struct mount_attr));
970     if (ret == \-1)
971         exit_log("%m \- Failed to change mount attributes\en");
973     close(fd_userns);
975     ret = move_mount(fd_tree, "", \-EBADF, target,
976                      MOVE_MOUNT_F_EMPTY_PATH);
977     if (ret == \-1)
978         exit_log("%m \- Failed to attach mount to %s\en", target);
980     close(fd_tree);
982     exit(EXIT_SUCCESS);
985 .SH SEE ALSO
986 .BR newuidmap (1),
987 .BR newgidmap (1),
988 .BR clone (2),
989 .BR mount (2),
990 .BR unshare (2),
991 .BR proc (5),
992 .BR mount_namespaces (7),
993 .BR capabilities (7),
994 .BR user_namespaces (7),
995 .BR xattr (7)