mount_setattr.2: New manual page documenting the mount_setattr() system call
[man-pages.git] / man2 / mount_setattr.2
blob16881d90df713640e7fac2b20d41ce0d8983c86a
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 mount 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 struct mount_attr and 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 " dfd ", const char *" path \
38 ", unsigned int " flags \
39 ", struct mount_attr *" attr ", 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 (2)
50 system call changes the mount properties of a mount or entire mount tree.
52 .I path
53 is a relative pathname,
54 then it is interpreted relative to the directory referred to by the file
55 descriptor
56 .IR dfd .
58 .I dfd
59 is the special value
60 .B AT_FDCWD
61 then
62 .I path
63 is taken to be relative to the current working directory of the calling process.
65 .I path
66 is the empty string and
67 .BR AT_EMPTY_PATH
68 is specified in
69 .I flags
70 then the mount properties of the mount identified by
71 .I dfd
72 are changed.
73 .PP
74 The
75 .BR mount_setattr (2)
76 system call uses an extensible structure
77 .IR ( "struct mount_attr" )
78 to allow for future extensions.
79 Any non-flag extensions to
80 .BR mount_setattr (2)
81 will be implemented as new fields appended to the above structure,
82 with a zero value in a new field resulting in the kernel behaving
83 as though that extension field was not present.
84 Therefore,
85 the caller
86 .I must
87 zero-fill this structure on initialization.
88 Please see the "Extensibility" section under
89 .B NOTES
90 for more details.
91 .PP
92 The
93 .I size
94 argument should usually be specified as
95 .IR "sizeof(struct mount_attr)" .
96 However,
97 if the caller does not intend to make use of features that got
98 introduced after the initial version of
99 .I struct mount_attr
100 they are free to pass the size of the initial struct together with the larger
101 struct.
102 This allows the kernel to not copy later parts of the struct that aren't used
103 anyway.
104 With each extension that changes the size of
105 .I struct mount_attr
106 the kernel will expose a define of the form
107 .BR MOUNT_ATTR_SIZE_VER<number> .
108 For example the macro for the size of the initial version of
109 .I struct mount_attr
111 .BR MOUNT_ATTR_SIZE_VER0 .
114 .I flags
115 argument can be used to alter the path resolution behavior.
116 The supported values are:
118 .B AT_EMPTY_PATH
120 .I path
121 is the empty string change the mount properties on
122 .I dfd
123 itself.
125 .B AT_RECURSIVE
126 Change the mount properties of the entire mount tree.
128 .B AT_SYMLINK_NOFOLLOW
129 Don't follow trailing symlinks.
131 .B AT_NO_AUTOMOUNT
132 Don't trigger automounts.
135 .I attr
136 argument of
137 .BR mount_setattr (2)
138 is a structure of the following form:
140 .in +4n
142 struct mount_attr {
143     __u64 attr_set;    /* Mount properties to set. */
144     __u64 attr_clr;    /* Mount properties to clear. */
145     __u64 propagation; /* Mount propagation type. */
146     __u64 userns_fd;   /* User namespace file descriptor. */
152 .I attr_set
154 .I attr_clr
155 members are used to specify the mount properties that are supposed to be set or
156 cleared for a mount or mount tree.
157 Flags set in
158 .I attr_set
159 enable a property on a mount or mount tree and flags set in
160 .I attr_clr
161 remove a property from a mount or mount tree.
163 When changing mount properties the kernel will first clear the flags specified
164 in the
165 .I attr_clr
166 field and then set the flags specified in the
167 .I attr_set
168 field:
170 .in +4n
172 struct mount_attr attr = {
173     .attr_clr = MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV,
174     .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID,
176 unsigned int current_mnt_flags = mnt->mnt_flags;
179  * Clear all flags set in .attr_clr,
180  * clearing MOUNT_ATTR_NOEXEC and MOUNT_ATTR_NODEV.
181  */
182 current_mnt_flags &= ~attr->attr_clr;
185  * Now set all flags set in .attr_set,
186  * applying MOUNT_ATTR_RDONLY and MOUNT_ATTR_NOSUID.
187  */
188 current_mnt_flags |= attr->attr_set;
190 mnt->mnt_flags = current_mnt_flags;
194 The effect of this change will be a mount or mount tree that is read-only,
195 blocks the execution of set-user-ID and set-group-ID binaries but does allow to
196 execute programs and access to devices nodes.
197 Multiple changes with the same set of flags requested
199 .I attr_clr
201 .I attr_set
202 are guaranteed to be idempotent after the changes have been applied.
204 The following mount attributes can be specified in the
205 .I attr_set
207 .I attr_clr
208 fields:
210 .B MOUNT_ATTR_RDONLY
211 If set in
212 .I attr_set
213 makes the mount read-only and if set in
214 .I attr_clr
215 removes the read-only setting if set on the mount.
217 .B MOUNT_ATTR_NOSUID
218 If set in
219 .I attr_set
220 makes the mount not honor set-user-ID and set-group-ID binaries,
221 and file capabilities when executing programs.
222 If set in
223 .I attr_clr
224 clears the set-user-ID, set-group-ID,
225 and file capability restriction if set on this mount.
227 .B MOUNT_ATTR_NODEV
228 If set in
229 .I attr_set
230 prevents access to devices on this mount and if set in
231 .I attr_clr
232 removes the device access restriction if set on this mount.
234 .BR MOUNT_ATTR_NOEXEC
235 If set in
236 .I attr_set
237 prevents executing programs on this mount and if set in
238 .I attr_clr
239 removes the restriction to execute programs on this mount.
241 .BR MOUNT_ATTR_NOSYMFOLLOW
242 If set in
243 .I attr_set
244 prevents following symlinks on this mount and if set in
245 .I attr_clr
246 removes the restriction to not follow symlinks on this mount.
248 .B MOUNT_ATTR_NODIRATIME
249 If set in
250 .I attr_set
251 prevents updating access time for directories on this mount and if set in
252 .I attr_clr
253 removes access time restriction for directories.
254 Note that
255 .BR MOUNT_ATTR_NODIRATIME
256 can be combined with other access time settings and is implied
257 by the noatime setting.
258 All other access time settings are mutually exclusive.
260 .BR MOUNT_ATTR__ATIME " - Changing access time settings
261 In the new mount api the access time values are an enum starting from 0.
262 Even though they are an enum in contrast to the other mount flags such as
263 .BR MOUNT_ATTR_NOEXEC
264 they are nonetheless passed in
265 .I attr_set
267 .I attr_clr
268 for consistency with
269 .BR fsmount (2)
270 which introduced this behavior.
272 Note,
273 since access times are an enum,
274 not a bitmap,
275 users wanting to transition to a different access time setting cannot simply
276 specify the access time in
277 .I attr_set
278 but must also set
279 .B MOUNT_ATTR__ATIME
280 in the
281 .I attr_clr
282 field.
283 The kernel will verify that
284 .BR MOUNT_ATTR__ATIME
285 isn't partially set in
286 .I attr_clr
287 and that
288 .I attr_set
289 doesn't have any access time bits set if
290 .BR MOUNT_ATTR__ATIME
291 isn't set in
292 .IR attr_clr .
295 .B MOUNT_ATTR_RELATIME
296 When a file is accessed via this mount,
297 update the file's last access time
298 (atime)
299 only if the current value of atime is less than or equal to the file's
300 last modification time (mtime) or last status change time (ctime).
302 To enable this access time setting on a mount or mount tree
303 .BR MOUNT_ATTR_RELATIME
304 must be set in
305 .I attr_set
307 .BR MOUNT_ATTR__ATIME
308 must be set in the
309 .I attr_clr
310 field.
312 .BR MOUNT_ATTR_NOATIME
313 Do not update access times for (all types of) files on this mount.
315 To enable this access time setting on a mount or mount tree
316 .BR MOUNT_ATTR_NOATIME
317 must be set in
318 .I attr_set
320 .BR MOUNT_ATTR__ATIME
321 must be set in the
322 .I attr_clr
323 field.
325 .BR MOUNT_ATTR_STRICTATIME
326 Always update the last access time (atime) when files are accessed on this
327 mount.
329 To enable this access time setting on a mount or mount tree
330 .BR MOUNT_ATTR_STRICTATIME
331 must be set in
332 .I attr_set
334 .BR MOUNT_ATTR__ATIME
335 must be set in the
336 .I attr_clr
337 field.
340 .BR MOUNT_ATTR_IDMAP
341 If set in
342 .I attr_set
343 creates an idmapped mount.
344 Since it is not supported to change the idmapping of a mount after it has been
345 idmapped,
346 it is invalid to specify
347 .B MOUNT_ATTR_IDMAP
349 .IR attr_clr .
350 The idmapping is taken from the user namespace specified in
351 .I userns_fd
352 and attached to the mount.
353 More details can be found in subsequent paragraphs.
355 Creating an idmapped mount allows to change the ownership of all files located
356 under a mount.
357 Thus, idmapped mounts make it possible to change ownership in a temporary and
358 localized way.
359 It is a localized change because ownership changes are restricted to a specific
360 mount.
361 All other users and locations where the filesystem is exposed are unaffected.
362 And it is a temporary change because ownership changes are tied to the lifetime
363 of the mount.
365 Whenever callers interact with the filesystem through an idmapped mount the
366 idmapping of the mount will be applied to user and group IDs associated with
367 filesystem objects.
368 This encompasses the user and group IDs associated with inodes and also
369 the following
370 .BR xattr (7)
371 keys:
374 .IP \(bu 2
375 .IR security.capability
376 whenever filesystem
377 .BR capabilities (7)
378 are stored or returned in the
379 .I VFS_CAP_REVISION_3
380 format which stores a rootid alongside the capabilities.
381 .IP \(bu 2
382 .I system.posix_acl_access
384 .I system.posix_acl_default
385 whenever user IDs or group IDs are stored in
386 .BR ACL_USER
388 .BR ACL_GROUP
389 entries.
393 The following conditions must be met in order to create an idmapped mount:
396 .IP \(bu 2
397 The caller must have
398 .I CAP_SYS_ADMIN
399 in the initial user namespace.
400 .IP \(bu 2
401 The filesystem must be mounted in the initial user namespace.
402 .IP \(bu
403 The underlying filesystem must support idmapped mounts.
404 Currently
405 .BR xfs (5),
406 .BR ext4 (5)
408 .BR fat
409 filesystems support idmapped mounts with more filesystems being actively worked
411 .IP \(bu
412 The mount must not already be idmapped.
413 This also implies that the idmapping of a mount cannot be altered.
414 .IP \(bu
415 The mount must be a detached/anonymous mount,
416 i.e.,
417 it must have been created by calling
418 .BR open_tree (2)
419 with the
420 .I OPEN_TREE_CLONE
421 flag and it must not already have been visible in the filesystem.
425 Idmappings can be created for user IDs, group IDs, and project IDs.
426 An idmapping is essentially a mapping of a range of user or group IDs into
427 another or the same range of user or group IDs.
428 Idmappings are usually written as three numbers either separated by white space
429 or a full stop.
430 The first two numbers specify the starting user or group ID in each of the two
431 user namespaces.
432 The third number specifies the range of the idmapping.
433 For example, a mapping for user IDs such as 1000:1001:1 would indicate that
434 user ID 1000 in the caller's user namespace is mapped to user ID 1001 in its
435 ancestor user namespace.
436 Since the map range is 1 only user ID 1000 is mapped.
437 It is possible to specify up to 340 idmappings for each idmapping type.
438 If any user IDs or group IDs are not mapped all files owned by that unmapped
439 user or group ID will appear as being owned by the overflow user ID or overflow
440 group ID respectively.
441 Further details and instructions for setting up idmappings can be found in the
442 .BR user_namespaces (7)
443 man page.
445 In the common case the user namespace passed in
446 .I userns_fd
447 together with
448 .BR MOUNT_ATTR_IDMAP
450 .I attr_set
451 to create an idmapped mount will be the user namespace of a container.
452 In other scenarios it will be a dedicated user namespace associated with a
453 user's login session as is the case for portable home directories in
454 .BR systemd-homed.service (8) ).
455 It is also perfectly fine to create a dedicated user namespace for the sake of
456 idmapping a mount.
458 Idmapped mounts can be useful in the following and a variety of other
459 scenarios:
462 .IP \(bu 2
463 sharing files between multiple users or multiple machines especially in
464 complex scenarios.
465 For example,
466 idmapped mounts are used to implement portable home directories in
467 .BR systemd-homed.service (8)
468 where they allow users to move their home directory to an external storage
469 device and use it on multiple computers where they are assigned different user IDs
470 and group IDs.
471 This effectively makes it possible to assign random user IDs and group IDs at login time.
472 .IP \(bu
473 sharing files from the host with unprivileged containers.
474 This allows user to avoid having to change ownership permanently through
475 .BR chown (2) .
476 .IP \(bu
477 idmapping a container's root filesystem.
478 Users don't need to change ownership
479 permanently through
480 .BR chown (2) .
481 Especially for large root filesystems using
482 .BR chown (2)
483 can be prohibitively expensive.
484 .IP \(bu
485 sharing files between containers with non-overlapping
486 idmappings.
487 .IP \(bu
488 implementing discretionary access (DAC) permission checking for fileystems
489 lacking a concept of ownership.
490 .IP \(bu
491 efficiently change ownership on a per-mount basis.
492 In contrast to
493 .BR chown (2)
494 changing ownership of large sets of files is instantenous with idmapped mounts.
495 This is especially useful when ownership of an entire root filesystem of a
496 virtual machine or container is to be changed as we've mentioned above.
497 With idmapped mounts a single
498 .BR mount_setattr (2)
499 system call will be sufficient to change the ownership of all files.
500 .IP \(bu
501 taking the current ownership into account.
502 Idmappings specify precisely what a user or group ID is supposed to be
503 mapped to.
504 This contrasts with the
505 .BR chown (2)
506 system call which cannot by itself take the current ownership of the files it
507 changes into account.
508 It simply changes the ownership to the specified user ID and group ID.
509 .IP \(bu
510 locally and temporarily restricted ownership changes.
511 Idmapped mounts allow to change ownership locally,
512 restricting it to specific mounts,
513 and temporarily as the ownership changes only apply as long as the mount exists.
514 In contrast,
515 changing ownership via the
516 .BR chown (2)
517 system call changes the ownership globally and permanently.
522 .I propagation
523 field is used to specify the propagation type of the mount or mount tree.
524 Mount propagation options are mutually exclusive,
525 i.e.,
526 the propagation values behave like an enum.
527 The supported mount propagation settings are:
529 .B MS_PRIVATE
530 Turn all mounts into private mounts.
531 Mount and unmount events do not propagate into or out of this mount point.
533 .B MS_SHARED
534 Turn all mounts into shared mounts.
535 Mount points share events with members of a peer group.
536 Mount and unmount events immediately under this mount point
537 will propagate to the other mount points that are members of the peer group.
538 Propagation here means that the same mount or unmount will automatically occur
539 under all of the other mount points in the peer group.
540 Conversely,
541 mount and unmount events that take place under peer mount points will propagate
542 to this mount point.
544 .B MS_SLAVE
545 Turn all mounts into dependent mounts.
546 Mount and unmount events propagate into this mount point from a shared peer
547 group.
548 Mount and unmount events under this mount point do not propagate to any peer.
550 .B MS_UNBINDABLE
551 This is like a private mount,
552 and in addition this mount can't be bind mounted.
553 Attempts to bind mount this mount will fail.
554 When a recursive bind mount is performed on a directory subtree,
555 any bind mounts within the subtree are automatically pruned
556 (i.e., not replicated)
557 when replicating that subtree to produce the target subtree.
559 .SH RETURN VALUE
560 On success,
561 .BR mount_setattr (2)
562 returns zero.
563 On error,
564 \-1 is returned and
565 .I errno
566 is set to indicate the cause of the error.
567 .SH ERRORS
569 .B EBADF
570 .I dfd
571 is not a valid file descriptor.
573 .B EBADF
574 .I userns_fd
575 is not a valid file descriptor.
577 .B EBUSY
578 The caller tried to change the mount to
579 .BR MOUNT_ATTR_RDONLY
580 but the mount still has files open for writing.
582 .B EINVAL
583 The path specified via the
584 .I dfd
586 .I path
587 arguments to
588 .BR mount_setattr (2)
589 isn't a mountpoint.
591 .B EINVAL
592 An unsupported value was set in
593 .I flags.
595 .B EINVAL
596 An unsupported value was specified in the
597 .I attr_set
598 field of
599 .IR mount_attr .
601 .B EINVAL
602 An unsupported value was specified in the
603 .I attr_clr
604 field of
605 .IR mount_attr .
607 .B EINVAL
608 An unsupported value was specified in the
609 .I propagation
610 field of
611 .IR mount_attr .
613 .B EINVAL
614 More than one of
615 .BR MS_SHARED,
616 .BR MS_SLAVE,
617 .BR MS_PRIVATE,
619 .BR MS_UNBINDABLE
620 was set in
621 .I propagation
622 field of
623 .IR mount_attr .
625 .B EINVAL
626 An access time setting was specified in the
627 .I attr_set
628 field without
629 .BR MOUNT_ATTR__ATIME
630 being set in the
631 .I attr_clr
632 field.
634 .B EINVAL
635 .BR MOUNT_ATTR_IDMAP
636 was specified in
637 .IR attr_clr .
639 .B EINVAL
640 A file descriptor value was specified in
641 .I userns_fd
642 which exceeds
643 .BR INT_MAX .
645 .B EINVAL
646 A valid file descriptor value was specified in
647 .I userns_fd
648 but the file descriptor wasn't a namespace file descriptor or did not refer to
649 a user namespace.
651 .B EINVAL
652 The underlying filesystem does not support idmapped mounts.
654 .B EINVAL
655 The mount to idmap is not a detached/anonymous mount,
656 i.e.,
657 the mount is already visible in the filesystem.
659 .B EINVAL
660 A partial access time setting was specified in
661 .I attr_clr
662 instead of
663 .BR MOUNT_ATTR__ATIME
664 being set.
666 .B EINVAL
667 The mount is located outside the caller's mount namespace.
669 .B EINVAL
670 The underlying filesystem is mounted in a user namespace.
672 .B ENOENT
673 A pathname was empty or had a nonexistent component.
675 .B ENOMEM
676 When changing mount propagation to
677 .BR MS_SHARED
678 a new peer group id needs to be allocated for all mounts without a peer group
679 id set.
680 Allocation of this peer group id has failed.
682 .B ENOSPC
683 When changing mount propagation to
684 .BR MS_SHARED
685 a new peer group id needs to be allocated for all mounts without a peer group
686 id set.
687 Allocation of this peer group id can fail.
688 Note that technically further error codes are possible that are specific to the
689 id allocation implementation used.
691 .B EPERM
692 One of the mounts had at least one of
693 .BR MOUNT_ATTR_NOATIME,
694 .BR MOUNT_ATTR_NODEV,
695 .BR MOUNT_ATTR_NODIRATIME,
696 .BR MOUNT_ATTR_NOEXEC,
697 .BR MOUNT_ATTR_NOSUID,
699 .BR MOUNT_ATTR_RDONLY
700 set and the flag is locked.
701 Mount attributes become locked on a mount if:
703 .IP \(bu 2
704 a new mount or mount tree is created causing mount propagation across user
705 namespaces.
706 The kernel will lock the aforementioned flags to protect these sensitive
707 properties from being altered.
708 .IP \(bu
709 a new mount and user namespace pair is created.
710 This happens for example when specifying
711 .BR CLONE_NEWUSER | CLONE_NEWNS
713 .BR unshare (2),
714 .BR clone (2),
716 .BR clone3 (2) .
717 The aformentioned flags become locked to protect user namespaces from altering
718 sensitive mount properties.
721 .B EPERM
722 A valid file descriptor value was specified in
723 .I userns_fd
724 but the file descriptor refers to the initial user namespace.
726 .B EPERM
727 An already idmapped mount was supposed to be idmapped.
729 .B EPERM
730 The caller does not have
731 .I CAP_SYS_ADMIN
732 in the initial user namespace.
733 .SH VERSIONS
734 .BR mount_setattr (2)
735 first appeared in Linux 5.12.
736 .\" commit 7d6beb71da3cc033649d641e1e608713b8220290
737 .\" commit 2a1867219c7b27f928e2545782b86daaf9ad50bd
738 .\" commit 9caccd41541a6f7d6279928d9f971f6642c361af
739 .SH CONFORMING TO
740 .BR mount_setattr (2)
741 is Linux specific.
742 .SH NOTES
743 .SS Extensibility
744 In order to allow for future extensibility,
745 .BR mount_setattr (2)
746 along with other system calls such as
747 .BR openat2 (2)
749 .BR clone3 (2)
750 requires the user-space application to specify the size of the
751 .I mount_attr
752 structure that it is passing.
753 By providing this information, it is possible for
754 .BR mount_setattr (2)
755 to provide both forwards- and backwards-compatibility, with
756 .I size
757 acting as an implicit version number.
758 (Because new extension fields will always
759 be appended, the structure size will always increase.)
760 This extensibility design is very similar to other system calls such as
761 .BR perf_setattr (2),
762 .BR perf_event_open (2),
763 .BR clone3 (2)
765 .BR openat2 (2) .
768 .I usize
769 be the size of the structure as specified by the user-space application,
770 and let
771 .I ksize
772 be the size of the structure which the kernel supports,
773 then there are three cases to consider:
775 .IP \(bu 2
777 .IR ksize
778 equals
779 .IR usize ,
780 then there is no version mismatch and
781 .I attr
782 can be used verbatim.
783 .IP \(bu
785 .IR ksize
786 is larger than
787 .IR usize ,
788 then there are some extension fields that the kernel supports which the
789 user-space application is unaware of.
790 Because a zero value in any added extension field signifies a no-op,
791 the kernel treats all of the extension fields not provided by the user-space
792 application as having zero values.
793 This provides backwards-compatibility.
794 .IP \(bu
796 .IR ksize
797 is smaller than
798 .IR usize ,
799 then there are some extension fields which the user-space application is aware
800 of but which the kernel does not support.
801 Because any extension field must have its zero values signify a no-op,
802 the kernel can safely ignore the unsupported extension fields if they are
803 all zero.
804 If any unsupported extension fields are non-zero, then \-1 is returned and
805 .I errno
806 is set to
807 .BR E2BIG .
808 This provides forwards-compatibility.
811 Because the definition of
812 .I struct mount_attr
813 may change in the future
814 (with new fields being added when system headers are updated),
815 user-space applications should zero-fill
816 .I struct mount_attr
817 to ensure that recompiling the program with new headers will not result in
818 spurious errors at runtime.
819 The simplest way is to use a designated initializer:
821 .in +4n
823 struct mount_attr attr = {
824     .attr_set = MOUNT_ATTR_RDONLY,
825     .attr_clr = MOUNT_ATTR_NODEV
830 or explicitly using
831 .BR memset (3)
832 or similar functions:
834 .in +4n
836 struct mount_attr attr;
837 memset(&attr, 0, sizeof(attr));
838 attr.attr_set = MOUNT_ATTR_RDONLY;
839 attr.attr_clr = MOUNT_ATTR_NODEV;
843 A user-space application that wishes to determine which extensions the running
844 kernel supports can do so by conducting a binary search on
845 .IR size
846 with a structure which has every byte nonzero
847 (to find the largest value which doesn't produce an error of
848 .BR E2BIG ) .
849 .SH EXAMPLES
852  * This program allows the caller to create a new detached mount and set
853  * various properties on it.
854  */
855 #define _GNU_SOURCE
856 #include <errno.h>
857 #include <fcntl.h>
858 #include <getopt.h>
859 #include <linux/mount.h>
860 #include <linux/types.h>
861 #include <stdbool.h>
862 #include <stdio.h>
863 #include <stdlib.h>
864 #include <string.h>
865 #include <sys/syscall.h>
866 #include <unistd.h>
868 static inline int mount_setattr(int dfd,
869                                 const char *path,
870                                 unsigned int flags,
871                                 struct mount_attr *attr,
872                                 size_t size)
874     return syscall(SYS_mount_setattr, dfd, path,
875                    flags, attr, size);
878 static inline int open_tree(int dfd, const char *filename,
879                             unsigned int flags)
881     return syscall(SYS_open_tree, dfd, filename, flags);
884 static inline int move_mount(int from_dfd,
885                              const char *from_pathname,
886                              int to_dfd,
887                              const char *to_pathname,
888                              unsigned int flags)
890     return syscall(SYS_move_mount, from_dfd,
891                    from_pathname, to_dfd, to_pathname, flags);
894 static const struct option longopts[] = {
895     {"map-mount",       required_argument,  NULL,  'a'},
896     {"recursive",       no_argument,        NULL,  'b'},
897     {"read-only",       no_argument,        NULL,  'c'},
898     {"block-setid",     no_argument,        NULL,  'd'},
899     {"block-devices",   no_argument,        NULL,  'e'},
900     {"block-exec",      no_argument,        NULL,  'f'},
901     {"no-access-time",  no_argument,        NULL,  'g'},
902     { NULL,             0,                  NULL,   0 },
905 #define exit_log(format, ...)                   \\
906     ({                                          \\
907         fprintf(stderr, format, ##__VA_ARGS__); \\
908         exit(EXIT_FAILURE);                     \\
909     })
911 int main(int argc, char *argv[])
913     int fd_userns = \-EBADF, index = 0;
914     bool recursive = false;
915     struct mount_attr *attr = &(struct mount_attr){};
916     const char *source, *target;
917     int fd_tree, new_argc, ret;
918     char *const *new_argv;
920     while ((ret = getopt_long_only(argc, argv, "",
921                                   longopts, &index)) != \-1) {
922         switch (ret) {
923         case 'a':
924             fd_userns = open(optarg, O_RDONLY | O_CLOEXEC);
925             if (fd_userns == \-1)
926                 exit_log("%m - Failed top open %s\en", optarg);
927             break;
928         case 'b':
929             recursive = true;
930             break;
931         case 'c':
932             attr->attr_set |= MOUNT_ATTR_RDONLY;
933             break;
934         case 'd':
935             attr->attr_set |= MOUNT_ATTR_NOSUID;
936             break;
937         case 'e':
938             attr->attr_set |= MOUNT_ATTR_NODEV;
939             break;
940         case 'f':
941             attr->attr_set |= MOUNT_ATTR_NOEXEC;
942             break;
943         case 'g':
944             attr->attr_set |= MOUNT_ATTR_NOATIME;
945             attr->attr_clr |= MOUNT_ATTR__ATIME;
946             break;
947         default:
948             exit_log("Invalid argument specified");
949         }
950     }
952     new_argv = &argv[optind];
953     new_argc = argc \- optind;
954     if (new_argc < 2)
955         exit_log("Missing source or target mountpoint\en");
956     source = new_argv[0];
957     target = new_argv[1];
959     fd_tree = open_tree(\-EBADF, source,
960                         OPEN_TREE_CLONE |
961                         OPEN_TREE_CLOEXEC |
962                         AT_EMPTY_PATH |
963                         (recursive ? AT_RECURSIVE : 0));
964     if (fd_tree == \-1)
965         exit_log("%m - Failed to open %s\en", source);
967     if (fd_userns >= 0) {
968         attr->attr_set  |= MOUNT_ATTR_IDMAP;
969         attr->userns_fd = fd_userns;
970     }
971     ret = mount_setattr(fd_tree, "",
972                         AT_EMPTY_PATH |
973                         (recursive ? AT_RECURSIVE : 0),
974                         attr, sizeof(struct mount_attr));
975     if (ret == \-1)
976         exit_log("%m - Failed to change mount attributes\en");
977     close(fd_userns);
979     ret = move_mount(fd_tree, "", \-EBADF, target,
980                      MOVE_MOUNT_F_EMPTY_PATH);
981     if (ret == \-1)
982         exit_log("%m - Failed to attach mount to %s\en", target);
983     close(fd_tree);
985     exit(EXIT_SUCCESS);
989 .SH SEE ALSO
990 .BR capabilities (7),
991 .BR clone (2),
992 .BR clone3 (2),
993 .BR ext4 (5),
994 .BR mount (2),
995 .BR mount_namespaces (7),
996 .BR newuidmap (1),
997 .BR newgidmap (1),
998 .BR proc (5),
999 .BR unshare (2),
1000 .BR user_namespaces (7),
1001 .BR xattr (7),
1002 .BR xfs (5)