Unverified Commit 901766df authored by Christian Brauner's avatar Christian Brauner
Browse files

fs: add vfs_open_tree() helper

Split out vfs_open_tree() from open_tree() so we can use it in later
patches.

Link: https://lore.kernel.org/r/20250128-work-mnt_idmap-update-v2-v1-1-c25feb0d2eb3@kernel.org


Reviewed-by: default avatar"Seth Forshee (DigitalOcean)" <sforshee@kernel.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 8f6116b5
Loading
Loading
Loading
Loading
+26 −23
Original line number Diff line number Diff line
@@ -3002,24 +3002,22 @@ static struct file *open_detached_copy(struct path *path, bool recursive)
	return file;
}

SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, flags)
static struct file *vfs_open_tree(int dfd, const char __user *filename, unsigned int flags)
{
	struct file *file;
	struct path path;
	int ret;
	struct path path __free(path_put) = {};
	int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
	bool detached = flags & OPEN_TREE_CLONE;
	int error;
	int fd;

	BUILD_BUG_ON(OPEN_TREE_CLOEXEC != O_CLOEXEC);

	if (flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_RECURSIVE |
		      AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLONE |
		      OPEN_TREE_CLOEXEC))
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	if ((flags & (AT_RECURSIVE | OPEN_TREE_CLONE)) == AT_RECURSIVE)
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	if (flags & AT_NO_AUTOMOUNT)
		lookup_flags &= ~LOOKUP_AUTOMOUNT;
@@ -3029,27 +3027,32 @@ SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, fl
		lookup_flags |= LOOKUP_EMPTY;

	if (detached && !may_mount())
		return -EPERM;
		return ERR_PTR(-EPERM);

	fd = get_unused_fd_flags(flags & O_CLOEXEC);
	if (fd < 0)
		return fd;
	ret = user_path_at(dfd, filename, lookup_flags, &path);
	if (unlikely(ret))
		return ERR_PTR(ret);

	error = user_path_at(dfd, filename, lookup_flags, &path);
	if (unlikely(error)) {
		file = ERR_PTR(error);
	} else {
	if (detached)
			file = open_detached_copy(&path, flags & AT_RECURSIVE);
		else
			file = dentry_open(&path, O_PATH, current_cred());
		path_put(&path);
		return open_detached_copy(&path, flags & AT_RECURSIVE);

	return dentry_open(&path, O_PATH, current_cred());
}
	if (IS_ERR(file)) {
		put_unused_fd(fd);

SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, flags)
{
	int fd;
	struct file *file __free(fput) = NULL;

	file = vfs_open_tree(dfd, filename, flags);
	if (IS_ERR(file))
		return PTR_ERR(file);
	}
	fd_install(fd, file);

	fd = get_unused_fd_flags(flags & O_CLOEXEC);
	if (fd < 0)
		return fd;

	fd_install(fd, no_free_ptr(file));
	return fd;
}