diff options
author | Christian Brauner <brauner@kernel.org> | 2025-01-28 11:33:41 +0100 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2025-02-12 12:12:28 +0100 |
commit | c4a16820d90199409c9bf01c4f794e1e9e8d8fd8 (patch) | |
tree | b3de182aaedb70d4278e12becfc23a829ffc9a82 /fs/namespace.c | |
parent | 474f7825d5335798742b92f067e1d22365013107 (diff) |
fs: add open_tree_attr()
Add open_tree_attr() which allow to atomically create a detached mount
tree and set mount options on it. If OPEN_TREE_CLONE is used this will
allow the creation of a detached mount with a new set of mount options
without it ever being exposed to userspace without that set of mount
options applied.
Link: https://lore.kernel.org/r/20250128-work-mnt_idmap-update-v2-v1-3-c25feb0d2eb3@kernel.org
Reviewed-by: "Seth Forshee (DigitalOcean)" <sforshee@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index d2ef1d69839b..ac4ad746c770 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4995,6 +4995,45 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, return err; } +SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename, + unsigned, flags, struct mount_attr __user *, uattr, + size_t, usize) +{ + struct file __free(fput) *file = NULL; + int fd; + + if (!uattr && usize) + return -EINVAL; + + file = vfs_open_tree(dfd, filename, flags); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (uattr) { + int ret; + struct mount_kattr kattr = { + .recurse = !!(flags & AT_RECURSIVE), + }; + + ret = copy_mount_setattr(uattr, usize, &kattr); + if (ret) + return ret; + + ret = do_mount_setattr(&file->f_path, &kattr); + if (ret) + return ret; + + finish_mount_kattr(&kattr); + } + + fd = get_unused_fd_flags(flags & O_CLOEXEC); + if (fd < 0) + return fd; + + fd_install(fd, no_free_ptr(file)); + return fd; +} + int show_path(struct seq_file *m, struct dentry *root) { if (root->d_sb->s_op->show_path) |