open_tree
open path or create detached mount object and attach to fd
- Provided by: manpages-dev (Version: 6.17-1)
- Source: manpages
- Report a bug
open path or create detached mount object and attach to fd
Standard C library (libc, -lc)
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include <fcntl.h> /* Definition of AT_* constants */ #include <sys/mount.h>
int open_tree(int dirfd, const char *path, unsigned int flags);
#include <sys/syscall.h> /* Definition of SYS_* constants */
int syscall(SYS_open_tree_attr,
int dirfd, const char *path, unsigned int flags,
struct mount_attr *_Nullable attr, size_t size);
Note: glibc provides no wrapper for open_tree_attr(), necessitating the use of syscall(2).
The open_tree() system call is part of the suite of file-descriptor-based mount facilities in Linux.
In either case, the resultant file descriptor acts the same as one produced by open(2) with O_PATH, meaning it can also be used as a dirfd argument to "*at()" system calls. However, unlike open(2) called with O_PATH, automounts will by default be triggered by open_tree() unless AT_NO_AUTOMOUNT is included in flags.
As with "*at()" system calls, open_tree() uses the dirfd argument in conjunction with the path argument to determine the path to operate on, as follows:
See openat(2) for an explanation of why the dirfd argument is useful.
flags can be used to control aspects of the path lookup and properties of the returned file descriptor. A value for flags is constructed by bitwise ORing zero or more of the following constants:
The open_tree_attr() system call operates in exactly the same way as open_tree(), except for the differences described here.
After performing the same operation as with open_tree(), open_tree_attr() will apply the mount attribute changes described in attr to the file descriptor before it is returned. (See mount_attr(2type) for a description of the mount_attr structure. As described in mount_setattr(2), size must be set to sizeof(struct mount_attr) in order to support future extensions.) If attr is NULL, or has attr.attr_clr, attr.attr_set, and attr.propagation all set to zero, then open_tree_attr() has identical behavior to open_tree().
The application of attr to the resultant file descriptor has identical semantics to mount_setattr(2), except for the following extensions and general caveats:
Note that if flags does not contain OPEN_TREE_CLONE, open_tree_attr() will attempt to modify the mount attributes of the mount object attached at the path described by dirfd and path. As with mount_setattr(2), if said path is not a mount point, open_tree_attr() will return an error.
On success, a new file descriptor is returned. On error, -1 is returned, and errno is set to indicate the error.
Linux.
Linux 5.2. glibc 2.36.
Linux 6.15.
The bind-mount mount objects created by open_tree() with OPEN_TREE_CLONE are not associated with the mount namespace of the calling process. Instead, each mount object is placed in a newly allocated "anonymous" mount namespace associated with the calling process.
One of the side-effects of this is that (unlike bind-mounts created with mount(2)), mount propagation (as described in mount_namespaces(7)) will not be applied to bind-mounts created by open_tree() until the bind-mount is attached with move_mount(2), at which point the mount object will be associated with the mount namespace where it was attached and mount propagation will resume. Note that any mount propagation events that occurred before the mount object was attached will not be propagated to the mount object, even after it is attached.
The following examples show how open_tree() can be used in place of more traditional mount(2) calls with MS_BIND.
int srcfd = open_tree(AT_FDCWD, "/var", OPEN_TREE_CLONE); move_mount(srcfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH);
First, a detached bind-mount mount object of /var is created and associated with the file descriptor srcfd. Then, the mount object is attached to /mnt using move_mount(2) with MOVE_MOUNT_F_EMPTY_PATH to request that the detached mount object associated with the file descriptor srcfd be moved (and thus attached) to /mnt.
The above procedure is functionally equivalent to the following mount operation using mount(2):
mount("/var", "/mnt", NULL, MS_BIND, NULL);
OPEN_TREE_CLONE can be combined with AT_RECURSIVE to create recursive detached bind-mount mount objects, which in turn can be attached to mount points to create recursive bind-mounts.
int srcfd = open_tree(AT_FDCWD, "/var",
OPEN_TREE_CLONE | AT_RECURSIVE);
move_mount(srcfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH);
The above procedure is functionally equivalent to the following mount operation using mount(2):
mount("/var", "/mnt", NULL, MS_BIND | MS_REC, NULL);
One of the primary benefits of using open_tree() and move_mount(2) over the traditional mount(2) is that operating with dirfd-style file descriptors is far easier and more intuitive.
int srcfd = open_tree(100, "", AT_EMPTY_PATH | OPEN_TREE_CLONE); move_mount(srcfd, "", 200, "foo", MOVE_MOUNT_F_EMPTY_PATH);
The above procedure is roughly equivalent to the following mount operation using mount(2):
mount("/proc/self/fd/100",
"/proc/self/fd/200/foo",
NULL, MS_BIND, NULL);
In addition, you can use the file descriptor returned by open_tree() as the dirfd argument to any "*at()" system calls:
int dirfd, fd; dirfd = open_tree(AT_FDCWD, "/etc", OPEN_TREE_CLONE); fd = openat(dirfd, "passwd", O_RDONLY); fchmodat(dirfd, "shadow", 0000, 0); close(dirfd); close(fd); /* The bind-mount is now destroyed */
The following is an example of how open_tree_attr() can be used to take an existing id-mapped mount and construct a new bind-mount mount object with a different MOUNT_ATTR_IDMAP attribute. The resultant detached mount object can be used like any other mount object returned by open_tree().
int nsfd1, nsfd2;
int mntfd1, mntfd2, mntfd3;
struct mount_attr attr;
mntfd1 = open_tree(AT_FDCWD, "/foo", OPEN_TREE_CLONE);
/* Configure the id-mapping of mntfd1 */
nsfd1 = open("/proc/1234/ns/user", O_RDONLY);
memset(&attr, 0, sizeof(attr));
attr.attr_set = MOUNT_ATTR_IDMAP;
attr.userns_fd = nsfd1;
mount_setattr(mntfd1, "", AT_EMPTY_PATH, &attr, sizeof(attr));
/* Create a new copy with a different id-mapping */
nsfd2 = open("/proc/5678/ns/user", O_RDONLY);
memset(&attr, 0, sizeof(attr));
attr.attr_clr = MOUNT_ATTR_IDMAP;
attr.attr_set = MOUNT_ATTR_IDMAP;
attr.userns_fd = nsfd2;
mntfd2 = open_tree_attr(mntfd1, "", OPEN_TREE_CLONE,
&attr, sizeof(attr));
/* Create a new copy with the id-mapping cleared */
memset(&attr, 0, sizeof(attr));
attr.attr_clr = MOUNT_ATTR_IDMAP;
mntfd3 = open_tree_attr(mntfd1, "", OPEN_TREE_CLONE,
&attr, sizeof(attr));
open_tree_attr() can also be used with attached mount objects; the above example is only intended to be illustrative.
fsconfig(2), fsmount(2), fsopen(2), fspick(2), mount(2), mount_setattr(2), move_mount(2), mount_namespaces(7)