1mount_setattr(2) System Calls Manual mount_setattr(2)
2
3
4
6 mount_setattr - change properties of a mount or mount tree
7
9 Standard C library (libc, -lc)
10
12 #include <linux/fcntl.h> /* Definition of AT_* constants */
13 #include <linux/mount.h> /* Definition of MOUNT_ATTR_* constants */
14 #include <sys/syscall.h> /* Definition of SYS_* constants */
15 #include <unistd.h>
16
17 int syscall(SYS_mount_setattr, int dirfd, const char *pathname,
18 unsigned int flags, struct mount_attr *attr, size_t size);
19
20 Note: glibc provides no wrapper for mount_setattr(), necessitating the
21 use of syscall(2).
22
24 The mount_setattr() system call changes the mount properties of a mount
25 or an entire mount tree. If pathname is a relative pathname, then it
26 is interpreted relative to the directory referred to by the file de‐
27 scriptor dirfd. If dirfd is the special value AT_FDCWD, then pathname
28 is interpreted relative to the current working directory of the calling
29 process. If pathname is the empty string and AT_EMPTY_PATH is speci‐
30 fied in flags, then the mount properties of the mount identified by
31 dirfd are changed. (See openat(2) for an explanation of why the dirfd
32 argument is useful.)
33
34 The mount_setattr() system call uses an extensible structure (struct
35 mount_attr) to allow for future extensions. Any non-flag extensions to
36 mount_setattr() will be implemented as new fields appended to the this
37 structure, with a zero value in a new field resulting in the kernel be‐
38 having as though that extension field was not present. Therefore, the
39 caller must zero-fill this structure on initialization. See the "Ex‐
40 tensibility" subsection under NOTES for more details.
41
42 The size argument should usually be specified as sizeof(struct
43 mount_attr). However, if the caller is using a kernel that supports an
44 extended struct mount_attr, but the caller does not intend to make use
45 of these features, it is possible to pass the size of an earlier ver‐
46 sion of the structure together with the extended structure. This al‐
47 lows the kernel to not copy later parts of the structure that aren't
48 used anyway. With each extension that changes the size of struct
49 mount_attr, the kernel will expose a definition of the form
50 MOUNT_ATTR_SIZE_VERnumber. For example, the macro for the size of the
51 initial version of struct mount_attr is MOUNT_ATTR_SIZE_VER0.
52
53 The flags argument can be used to alter the pathname resolution behav‐
54 ior. The supported values are:
55
56 AT_EMPTY_PATH
57 If pathname is the empty string, change the mount properties on
58 dirfd itself.
59
60 AT_RECURSIVE
61 Change the mount properties of the entire mount tree.
62
63 AT_SYMLINK_NOFOLLOW
64 Don't follow trailing symbolic links.
65
66 AT_NO_AUTOMOUNT
67 Don't trigger automounts.
68
69 The attr argument of mount_setattr() is a structure of the following
70 form:
71
72 struct mount_attr {
73 __u64 attr_set; /* Mount properties to set */
74 __u64 attr_clr; /* Mount properties to clear */
75 __u64 propagation; /* Mount propagation type */
76 __u64 userns_fd; /* User namespace file descriptor */
77 };
78
79 The attr_set and attr_clr members are used to specify the mount proper‐
80 ties that are supposed to be set or cleared for a mount or mount tree.
81 Flags set in attr_set enable a property on a mount or mount tree, and
82 flags set in attr_clr remove a property from a mount or mount tree.
83
84 When changing mount properties, the kernel will first clear the flags
85 specified in the attr_clr field, and then set the flags specified in
86 the attr_set field. For example, these settings:
87
88 struct mount_attr attr = {
89 .attr_clr = MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NODEV,
90 .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID,
91 };
92
93 are equivalent to the following steps:
94
95 unsigned int current_mnt_flags = mnt->mnt_flags;
96
97 /*
98 * Clear all flags set in .attr_clr,
99 * clearing MOUNT_ATTR_NOEXEC and MOUNT_ATTR_NODEV.
100 */
101 current_mnt_flags &= ~attr->attr_clr;
102
103 /*
104 * Now set all flags set in .attr_set,
105 * applying MOUNT_ATTR_RDONLY and MOUNT_ATTR_NOSUID.
106 */
107 current_mnt_flags |= attr->attr_set;
108
109 mnt->mnt_flags = current_mnt_flags;
110
111 As a result of this change, the mount or mount tree (a) is read-only;
112 (b) blocks the execution of set-user-ID and set-group-ID programs; (c)
113 allows execution of programs; and (d) allows access to devices.
114
115 Multiple changes with the same set of flags requested in attr_clr and
116 attr_set are guaranteed to be idempotent after the changes have been
117 applied.
118
119 The following mount attributes can be specified in the attr_set or
120 attr_clr fields:
121
122 MOUNT_ATTR_RDONLY
123 If set in attr_set, makes the mount read-only. If set in
124 attr_clr, removes the read-only setting if set on the mount.
125
126 MOUNT_ATTR_NOSUID
127 If set in attr_set, causes the mount not to honor the set-user-
128 ID and set-group-ID mode bits and file capabilities when execut‐
129 ing programs. If set in attr_clr, clears the set-user-ID, set-
130 group-ID, and file capability restriction if set on this mount.
131
132 MOUNT_ATTR_NODEV
133 If set in attr_set, prevents access to devices on this mount.
134 If set in attr_clr, removes the restriction that prevented ac‐
135 cessing devices on this mount.
136
137 MOUNT_ATTR_NOEXEC
138 If set in attr_set, prevents executing programs on this mount.
139 If set in attr_clr, removes the restriction that prevented exe‐
140 cuting programs on this mount.
141
142 MOUNT_ATTR_NOSYMFOLLOW
143 If set in attr_set, prevents following symbolic links on this
144 mount. If set in attr_clr, removes the restriction that pre‐
145 vented following symbolic links on this mount.
146
147 MOUNT_ATTR_NODIRATIME
148 If set in attr_set, prevents updating access time for directo‐
149 ries on this mount. If set in attr_clr, removes the restriction
150 that prevented updating access time for directories. Note that
151 MOUNT_ATTR_NODIRATIME can be combined with other access-time
152 settings and is implied by the noatime setting. All other ac‐
153 cess-time settings are mutually exclusive.
154
155 MOUNT_ATTR__ATIME - changing access-time settings
156 The access-time values listed below are an enumeration that in‐
157 cludes the value zero, expressed in the bits defined by the mask
158 MOUNT_ATTR__ATIME. Even though these bits are an enumeration
159 (in contrast to the other mount flags such as
160 MOUNT_ATTR_NOEXEC), they are nonetheless passed in attr_set and
161 attr_clr for consistency with fsmount(2), which introduced this
162 behavior.
163
164 Note that, since the access-time values are an enumeration
165 rather than bit values, a caller wanting to transition to a dif‐
166 ferent access-time setting cannot simply specify the access-time
167 setting in attr_set, but must also include MOUNT_ATTR__ATIME in
168 the attr_clr field. The kernel will verify that
169 MOUNT_ATTR__ATIME isn't partially set in attr_clr (i.e., either
170 all bits in the MOUNT_ATTR__ATIME bit field are either set or
171 clear), and that attr_set doesn't have any access-time bits set
172 if MOUNT_ATTR__ATIME isn't set in attr_clr.
173
174 MOUNT_ATTR_RELATIME
175 When a file is accessed via this mount, update the file's
176 last access time (atime) only if the current value of
177 atime is less than or equal to the file's last modifica‐
178 tion time (mtime) or last status change time (ctime).
179
180 To enable this access-time setting on a mount or mount
181 tree, MOUNT_ATTR_RELATIME must be set in attr_set and
182 MOUNT_ATTR__ATIME must be set in the attr_clr field.
183
184 MOUNT_ATTR_NOATIME
185 Do not update access times for (all types of) files on
186 this mount.
187
188 To enable this access-time setting on a mount or mount
189 tree, MOUNT_ATTR_NOATIME must be set in attr_set and
190 MOUNT_ATTR__ATIME must be set in the attr_clr field.
191
192 MOUNT_ATTR_STRICTATIME
193 Always update the last access time (atime) when files are
194 accessed on this mount.
195
196 To enable this access-time setting on a mount or mount
197 tree, MOUNT_ATTR_STRICTATIME must be set in attr_set and
198 MOUNT_ATTR__ATIME must be set in the attr_clr field.
199
200 MOUNT_ATTR_IDMAP
201 If set in attr_set, creates an ID-mapped mount. The ID mapping
202 is taken from the user namespace specified in userns_fd and at‐
203 tached to the mount.
204
205 Since it is not supported to change the ID mapping of a mount
206 after it has been ID mapped, it is invalid to specify
207 MOUNT_ATTR_IDMAP in attr_clr.
208
209 For further details, see the subsection "ID-mapped mounts" under
210 NOTES.
211
212 The propagation field is used to specify the propagation type of the
213 mount or mount tree. This field either has the value zero, meaning
214 leave the propagation type unchanged, or it has one of the following
215 values:
216
217 MS_PRIVATE
218 Turn all mounts into private mounts.
219
220 MS_SHARED
221 Turn all mounts into shared mounts.
222
223 MS_SLAVE
224 Turn all mounts into dependent mounts.
225
226 MS_UNBINDABLE
227 Turn all mounts into unbindable mounts.
228
229 For further details on the above propagation types, see mount_name‐
230 spaces(7).
231
233 On success, mount_setattr() returns zero. On error, -1 is returned and
234 errno is set to indicate the cause of the error.
235
237 EBADF pathname is relative but dirfd is neither AT_FDCWD nor a valid
238 file descriptor.
239
240 EBADF userns_fd is not a valid file descriptor.
241
242 EBUSY The caller tried to change the mount to MOUNT_ATTR_RDONLY, but
243 the mount still holds files open for writing.
244
245 EBUSY The caller tried to create an ID-mapped mount raising
246 MOUNT_ATTR_IDMAP and specifying userns_fd but the mount still
247 holds files open for writing.
248
249 EINVAL The pathname specified via the dirfd and pathname arguments to
250 mount_setattr() isn't a mount point.
251
252 EINVAL An unsupported value was set in flags.
253
254 EINVAL An unsupported value was specified in the attr_set field of
255 mount_attr.
256
257 EINVAL An unsupported value was specified in the attr_clr field of
258 mount_attr.
259
260 EINVAL An unsupported value was specified in the propagation field of
261 mount_attr.
262
263 EINVAL More than one of MS_SHARED, MS_SLAVE, MS_PRIVATE, or MS_UNBIND‐
264 ABLE was set in the propagation field of mount_attr.
265
266 EINVAL An access-time setting was specified in the attr_set field with‐
267 out MOUNT_ATTR__ATIME being set in the attr_clr field.
268
269 EINVAL MOUNT_ATTR_IDMAP was specified in attr_clr.
270
271 EINVAL A file descriptor value was specified in userns_fd which exceeds
272 INT_MAX.
273
274 EINVAL A valid file descriptor value was specified in userns_fd, but
275 the file descriptor did not refer to a user namespace.
276
277 EINVAL The underlying filesystem does not support ID-mapped mounts.
278
279 EINVAL The mount that is to be ID mapped is not a detached mount; that
280 is, the mount has not previously been visible in a mount name‐
281 space.
282
283 EINVAL A partial access-time setting was specified in attr_clr instead
284 of MOUNT_ATTR__ATIME being set.
285
286 EINVAL The mount is located outside the caller's mount namespace.
287
288 EINVAL The underlying filesystem has been mounted in a mount namespace
289 that is owned by a noninitial user namespace
290
291 ENOENT A pathname was empty or had a nonexistent component.
292
293 ENOMEM When changing mount propagation to MS_SHARED, a new peer group
294 ID needs to be allocated for all mounts without a peer group ID
295 set. This allocation failed because there was not enough memory
296 to allocate the relevant internal structures.
297
298 ENOSPC When changing mount propagation to MS_SHARED, a new peer group
299 ID needs to be allocated for all mounts without a peer group ID
300 set. This allocation failed because the kernel has run out of
301 IDs.
302
303 EPERM One of the mounts had at least one of MOUNT_ATTR_NOATIME,
304 MOUNT_ATTR_NODEV, MOUNT_ATTR_NODIRATIME, MOUNT_ATTR_NOEXEC,
305 MOUNT_ATTR_NOSUID, or MOUNT_ATTR_RDONLY set and the flag is
306 locked. Mount attributes become locked on a mount if:
307
308 • A new mount or mount tree is created causing mount propaga‐
309 tion across user namespaces (i.e., propagation to a mount
310 namespace owned by a different user namespace). The kernel
311 will lock the aforementioned flags to prevent these sensitive
312 properties from being altered.
313
314 • A new mount and user namespace pair is created. This happens
315 for example when specifying CLONE_NEWUSER | CLONE_NEWNS in
316 unshare(2), clone(2), or clone3(2). The aforementioned flags
317 become locked in the new mount namespace to prevent sensitive
318 mount properties from being altered. Since the newly created
319 mount namespace will be owned by the newly created user name‐
320 space, a calling process that is privileged in the new user
321 namespace would—in the absence of such locking—be able to al‐
322 ter sensitive mount properties (e.g., to remount a mount that
323 was marked read-only as read-write in the new mount name‐
324 space).
325
326 EPERM A valid file descriptor value was specified in userns_fd, but
327 the file descriptor refers to the initial user namespace.
328
329 EPERM An attempt was made to add an ID mapping to a mount that is al‐
330 ready ID mapped.
331
332 EPERM The caller does not have CAP_SYS_ADMIN in the initial user name‐
333 space.
334
336 Linux.
337
339 Linux 5.12.
340
342 ID-mapped mounts
343 Creating an ID-mapped mount makes it possible to change the ownership
344 of all files located under a mount. Thus, ID-mapped mounts make it
345 possible to change ownership in a temporary and localized way. It is a
346 localized change because the ownership changes are visible only via a
347 specific mount. All other users and locations where the filesystem is
348 exposed are unaffected. It is a temporary change because the ownership
349 changes are tied to the lifetime of the mount.
350
351 Whenever callers interact with the filesystem through an ID-mapped
352 mount, the ID mapping of the mount will be applied to user and group
353 IDs associated with filesystem objects. This encompasses the user and
354 group IDs associated with inodes and also the following xattr(7) keys:
355
356 • security.capability, whenever filesystem capabilities are stored or
357 returned in the VFS_CAP_REVISION_3 format, which stores a root user
358 ID alongside the capabilities (see capabilities(7)).
359
360 • system.posix_acl_access and system.posix_acl_default, whenever user
361 IDs or group IDs are stored in ACL_USER or ACL_GROUP entries.
362
363 The following conditions must be met in order to create an ID-mapped
364 mount:
365
366 • The caller must have the CAP_SYS_ADMIN capability in the user name‐
367 space the filesystem was mounted in.
368
369 • The underlying filesystem must support ID-mapped mounts. Currently,
370 the following filesystems support ID-mapped mounts:
371
372 • xfs(5) (since Linux 5.12)
373 • ext4(5) (since Linux 5.12)
374 • FAT (since Linux 5.12)
375 • btrfs(5) (since Linux 5.15)
376 • ntfs3 (since Linux 5.15)
377 • f2fs (since Linux 5.18)
378 • erofs (since Linux 5.19)
379 • overlayfs (ID-mapped lower and upper layers supported since Linux
380 5.19)
381
382 • The mount must not already be ID-mapped. This also implies that the
383 ID mapping of a mount cannot be altered.
384
385 • The mount must not have any writers.
386
387 • The mount must be a detached mount; that is, it must have been cre‐
388 ated by calling open_tree(2) with the OPEN_TREE_CLONE flag and it
389 must not already have been visible in a mount namespace. (To put
390 things another way: the mount must not have been attached to the
391 filesystem hierarchy with a system call such as move_mount(2).)
392
393 ID mappings can be created for user IDs, group IDs, and project IDs.
394 An ID mapping is essentially a mapping of a range of user or group IDs
395 into another or the same range of user or group IDs. ID mappings are
396 written to map files as three numbers separated by white space. The
397 first two numbers specify the starting user or group ID in each of the
398 two user namespaces. The third number specifies the range of the ID
399 mapping. For example, a mapping for user IDs such as "1000 1001 1"
400 would indicate that user ID 1000 in the caller's user namespace is
401 mapped to user ID 1001 in its ancestor user namespace. Since the map
402 range is 1, only user ID 1000 is mapped.
403
404 It is possible to specify up to 340 ID mappings for each ID mapping
405 type. If any user IDs or group IDs are not mapped, all files owned by
406 that unmapped user or group ID will appear as being owned by the over‐
407 flow user ID or overflow group ID respectively.
408
409 Further details on setting up ID mappings can be found in user_name‐
410 spaces(7).
411
412 In the common case, the user namespace passed in userns_fd (together
413 with MOUNT_ATTR_IDMAP in attr_set) to create an ID-mapped mount will be
414 the user namespace of a container. In other scenarios it will be a
415 dedicated user namespace associated with a user's login session as is
416 the case for portable home directories in systemd-homed.service(8)).
417 It is also perfectly fine to create a dedicated user namespace for the
418 sake of ID mapping a mount.
419
420 ID-mapped mounts can be useful in the following and a variety of other
421 scenarios:
422
423 • Sharing files or filesystems between multiple users or multiple ma‐
424 chines, especially in complex scenarios. For example, ID-mapped
425 mounts are used to implement portable home directories in systemd-
426 homed.service(8), where they allow users to move their home direc‐
427 tory to an external storage device and use it on multiple computers
428 where they are assigned different user IDs and group IDs. This ef‐
429 fectively makes it possible to assign random user IDs and group IDs
430 at login time.
431
432 • Sharing files or filesystems from the host with unprivileged con‐
433 tainers. This allows a user to avoid having to change ownership
434 permanently through chown(2).
435
436 • ID mapping a container's root filesystem. Users don't need to
437 change ownership permanently through chown(2). Especially for large
438 root filesystems, using chown(2) can be prohibitively expensive.
439
440 • Sharing files or filesystems between containers with non-overlapping
441 ID mappings.
442
443 • Implementing discretionary access (DAC) permission checking for
444 filesystems lacking a concept of ownership.
445
446 • Efficiently changing ownership on a per-mount basis. In contrast to
447 chown(2), changing ownership of large sets of files is instantaneous
448 with ID-mapped mounts. This is especially useful when ownership of
449 an entire root filesystem of a virtual machine or container is to be
450 changed as mentioned above. With ID-mapped mounts, a single
451 mount_setattr() system call will be sufficient to change the owner‐
452 ship of all files.
453
454 • Taking the current ownership into account. ID mappings specify pre‐
455 cisely what a user or group ID is supposed to be mapped to. This
456 contrasts with the chown(2) system call which cannot by itself take
457 the current ownership of the files it changes into account. It sim‐
458 ply changes the ownership to the specified user ID and group ID.
459
460 • Locally and temporarily restricted ownership changes. ID-mapped
461 mounts make it possible to change ownership locally, restricting the
462 ownership changes to specific mounts, and temporarily as the owner‐
463 ship changes only apply as long as the mount exists. By contrast,
464 changing ownership via the chown(2) system call changes the owner‐
465 ship globally and permanently.
466
467 Extensibility
468 In order to allow for future extensibility, mount_setattr() requires
469 the user-space application to specify the size of the mount_attr struc‐
470 ture that it is passing. By providing this information, it is possible
471 for mount_setattr() to provide both forwards- and backwards-compatibil‐
472 ity, with size acting as an implicit version number. (Because new ex‐
473 tension fields will always be appended, the structure size will always
474 increase.) This extensibility design is very similar to other system
475 calls such as perf_setattr(2), perf_event_open(2), clone3(2) and ope‐
476 nat2(2).
477
478 Let usize be the size of the structure as specified by the user-space
479 application, and let ksize be the size of the structure which the ker‐
480 nel supports, then there are three cases to consider:
481
482 • If ksize equals usize, then there is no version mismatch and attr
483 can be used verbatim.
484
485 • If ksize is larger than usize, then there are some extension fields
486 that the kernel supports which the user-space application is unaware
487 of. Because a zero value in any added extension field signifies a
488 no-op, the kernel treats all of the extension fields not provided by
489 the user-space application as having zero values. This provides
490 backwards-compatibility.
491
492 • If ksize is smaller than usize, then there are some extension fields
493 which the user-space application is aware of but which the kernel
494 does not support. Because any extension field must have its zero
495 values signify a no-op, the kernel can safely ignore the unsupported
496 extension fields if they are all zero. If any unsupported extension
497 fields are non-zero, then -1 is returned and errno is set to E2BIG.
498 This provides forwards-compatibility.
499
500 Because the definition of struct mount_attr may change in the future
501 (with new fields being added when system headers are updated), user-
502 space applications should zero-fill struct mount_attr to ensure that
503 recompiling the program with new headers will not result in spurious
504 errors at run time. The simplest way is to use a designated initial‐
505 izer:
506
507 struct mount_attr attr = {
508 .attr_set = MOUNT_ATTR_RDONLY,
509 .attr_clr = MOUNT_ATTR_NODEV
510 };
511
512 Alternatively, the structure can be zero-filled using memset(3) or sim‐
513 ilar functions:
514
515 struct mount_attr attr;
516 memset(&attr, 0, sizeof(attr));
517 attr.attr_set = MOUNT_ATTR_RDONLY;
518 attr.attr_clr = MOUNT_ATTR_NODEV;
519
520 A user-space application that wishes to determine which extensions the
521 running kernel supports can do so by conducting a binary search on size
522 with a structure which has every byte nonzero (to find the largest
523 value which doesn't produce an error of E2BIG).
524
526 /*
527 * This program allows the caller to create a new detached mount
528 * and set various properties on it.
529 */
530 #define _GNU_SOURCE
531 #include <err.h>
532 #include <fcntl.h>
533 #include <getopt.h>
534 #include <linux/mount.h>
535 #include <linux/types.h>
536 #include <stdbool.h>
537 #include <stdio.h>
538 #include <stdlib.h>
539 #include <string.h>
540 #include <sys/syscall.h>
541 #include <unistd.h>
542
543 static inline int
544 mount_setattr(int dirfd, const char *pathname, unsigned int flags,
545 struct mount_attr *attr, size_t size)
546 {
547 return syscall(SYS_mount_setattr, dirfd, pathname, flags,
548 attr, size);
549 }
550
551 static inline int
552 open_tree(int dirfd, const char *filename, unsigned int flags)
553 {
554 return syscall(SYS_open_tree, dirfd, filename, flags);
555 }
556
557 static inline int
558 move_mount(int from_dirfd, const char *from_pathname,
559 int to_dirfd, const char *to_pathname, unsigned int flags)
560 {
561 return syscall(SYS_move_mount, from_dirfd, from_pathname,
562 to_dirfd, to_pathname, flags);
563 }
564
565 static const struct option longopts[] = {
566 {"map-mount", required_argument, NULL, 'a'},
567 {"recursive", no_argument, NULL, 'b'},
568 {"read-only", no_argument, NULL, 'c'},
569 {"block-setid", no_argument, NULL, 'd'},
570 {"block-devices", no_argument, NULL, 'e'},
571 {"block-exec", no_argument, NULL, 'f'},
572 {"no-access-time", no_argument, NULL, 'g'},
573 { NULL, 0, NULL, 0 },
574 };
575
576 int
577 main(int argc, char *argv[])
578 {
579 int fd_userns = -1;
580 int fd_tree;
581 int index = 0;
582 int ret;
583 bool recursive = false;
584 const char *source;
585 const char *target;
586 struct mount_attr *attr = &(struct mount_attr){};
587
588 while ((ret = getopt_long_only(argc, argv, "",
589 longopts, &index)) != -1) {
590 switch (ret) {
591 case 'a':
592 fd_userns = open(optarg, O_RDONLY | O_CLOEXEC);
593 if (fd_userns == -1)
594 err(EXIT_FAILURE, "open(%s)", optarg);
595 break;
596 case 'b':
597 recursive = true;
598 break;
599 case 'c':
600 attr->attr_set |= MOUNT_ATTR_RDONLY;
601 break;
602 case 'd':
603 attr->attr_set |= MOUNT_ATTR_NOSUID;
604 break;
605 case 'e':
606 attr->attr_set |= MOUNT_ATTR_NODEV;
607 break;
608 case 'f':
609 attr->attr_set |= MOUNT_ATTR_NOEXEC;
610 break;
611 case 'g':
612 attr->attr_set |= MOUNT_ATTR_NOATIME;
613 attr->attr_clr |= MOUNT_ATTR__ATIME;
614 break;
615 default:
616 errx(EXIT_FAILURE, "Invalid argument specified");
617 }
618 }
619
620 if ((argc - optind) < 2)
621 errx(EXIT_FAILURE, "Missing source or target mount point");
622
623 source = argv[optind];
624 target = argv[optind + 1];
625
626 /* In the following, -1 as the 'dirfd' argument ensures that
627 open_tree() fails if 'source' is not an absolute pathname. */
628
629 fd_tree = open_tree(-1, source,
630 OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC |
631 AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0));
632 if (fd_tree == -1)
633 err(EXIT_FAILURE, "open(%s)", source);
634
635 if (fd_userns >= 0) {
636 attr->attr_set |= MOUNT_ATTR_IDMAP;
637 attr->userns_fd = fd_userns;
638 }
639
640 ret = mount_setattr(fd_tree, "",
641 AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0),
642 attr, sizeof(struct mount_attr));
643 if (ret == -1)
644 err(EXIT_FAILURE, "mount_setattr");
645
646 close(fd_userns);
647
648 /* In the following, -1 as the 'to_dirfd' argument ensures that
649 open_tree() fails if 'target' is not an absolute pathname. */
650
651 ret = move_mount(fd_tree, "", -1, target,
652 MOVE_MOUNT_F_EMPTY_PATH);
653 if (ret == -1)
654 err(EXIT_FAILURE, "move_mount() to %s", target);
655
656 close(fd_tree);
657
658 exit(EXIT_SUCCESS);
659 }
660
662 newgidmap(1), newuidmap(1), clone(2), mount(2), unshare(2), proc(5),
663 capabilities(7), mount_namespaces(7), user_namespaces(7), xattr(7)
664
665
666
667Linux man-pages 6.05 2023-05-03 mount_setattr(2)