Unverified Commit a20853ab authored by Amir Goldstein's avatar Amir Goldstein Committed by Christian Brauner
Browse files

fs: open_by_handle_at() support for decoding "explicit connectable" file handles



Teach open_by_handle_at(2) about the type format of "explicit connectable"
file handles that were created using the AT_HANDLE_CONNECTABLE flag to
name_to_handle_at(2).

When decoding an "explicit connectable" file handles, name_to_handle_at(2)
should fail if it cannot open a "connected" fd with known path, which is
accessible (to capable user) from mount fd path.

Note that this does not check if the path is accessible to the calling
user, just that it is accessible wrt the mount namesapce, so if there
is no "connected" alias, or if parts of the path are hidden in the
mount namespace, open_by_handle_at(2) will return -ESTALE.

Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20241011090023.655623-4-amir73il@gmail.com


Fixes: 570df4e9 ("ceph: snapshot nfs re-export")
Acked-by:
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent c374196b
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -246,6 +246,12 @@ static int vfs_dentry_acceptable(void *context, struct dentry *dentry)

	if (!(ctx->flags & HANDLE_CHECK_SUBTREE) || d == root)
		retval = 1;
	/*
	 * exportfs_decode_fh_raw() does not call acceptable() callback with
	 * a disconnected directory dentry, so we should have reached either
	 * mount fd directory or sb root.
	 */
	if (ctx->fh_flags & EXPORT_FH_DIR_ONLY)
		WARN_ON_ONCE(d != root && d != root->d_sb->s_root);
	dput(d);
	return retval;
@@ -350,6 +356,7 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
		retval = -EINVAL;
		goto out_path;
	}

	handle = kmalloc(struct_size(handle, f_handle, f_handle.handle_bytes),
			 GFP_KERNEL);
	if (!handle) {
@@ -365,6 +372,17 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
		goto out_handle;
	}

	/*
	 * If handle was encoded with AT_HANDLE_CONNECTABLE, verify that we
	 * are decoding an fd with connected path, which is accessible from
	 * the mount fd path.
	 */
	if (f_handle.handle_type & FILEID_IS_CONNECTABLE) {
		ctx.fh_flags |= EXPORT_FH_CONNECTABLE;
		ctx.flags |= HANDLE_CHECK_SUBTREE;
	}
	if (f_handle.handle_type & FILEID_IS_DIR)
		ctx.fh_flags |= EXPORT_FH_DIR_ONLY;
	/* Filesystem code should not be exposed to user flags */
	handle->handle_type &= ~FILEID_USER_FLAGS_MASK;
	retval = do_handle_to_path(handle, path, &ctx);
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ struct fid {
/* Flags supported in encoded handle_type that is exported to user */
#define FILEID_IS_CONNECTABLE	0x10000
#define FILEID_IS_DIR		0x20000
#define FILEID_VALID_USER_FLAGS	(0)
#define FILEID_VALID_USER_FLAGS	(FILEID_IS_CONNECTABLE | FILEID_IS_DIR)

/**
 * struct export_operations - for nfsd to communicate with file systems