exportfs: allow exporting non-decodeable file handles to userspace
Some userspace programs use st_ino as a unique object identifier, even though inode numbers may be recycable. This issue has been addressed for NFS export long ago using the exportfs file handle API and the unique file handle identifiers are also exported to userspace via name_to_handle_at(2). fanotify also uses file handles to identify objects in events, but only for filesystems that support NFS export. Relax the requirement for NFS export support and allow more filesystems to export a unique object identifier via name_to_handle_at(2) with the flag AT_HANDLE_FID. A file handle requested with the AT_HANDLE_FID flag, may or may not be usable as an argument to open_by_handle_at(2). To allow filesystems to opt-in to supporting AT_HANDLE_FID, a struct export_operations is required, but even an empty struct is sufficient for encoding FIDs. Acked-by: Jeff Layton <jlayton@kernel.org> Acked-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Acked-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Message-Id: <20230502124817.3070545-4-amir73il@gmail.com>
This commit is contained in:
parent
304e9c83e8
commit
96b2b072ee
22
fs/fhandle.c
22
fs/fhandle.c
|
@ -16,7 +16,7 @@
|
|||
|
||||
static long do_sys_name_to_handle(const struct path *path,
|
||||
struct file_handle __user *ufh,
|
||||
int __user *mnt_id)
|
||||
int __user *mnt_id, int fh_flags)
|
||||
{
|
||||
long retval;
|
||||
struct file_handle f_handle;
|
||||
|
@ -24,11 +24,14 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||
struct file_handle *handle = NULL;
|
||||
|
||||
/*
|
||||
* We need to make sure whether the file system
|
||||
* support decoding of the file handle
|
||||
* We need to make sure whether the file system support decoding of
|
||||
* the file handle if decodeable file handle was requested.
|
||||
* Otherwise, even empty export_operations are sufficient to opt-in
|
||||
* to encoding FIDs.
|
||||
*/
|
||||
if (!path->dentry->d_sb->s_export_op ||
|
||||
!path->dentry->d_sb->s_export_op->fh_to_dentry)
|
||||
(!(fh_flags & EXPORT_FH_FID) &&
|
||||
!path->dentry->d_sb->s_export_op->fh_to_dentry))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
|
||||
|
@ -45,10 +48,10 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||
/* convert handle size to multiple of sizeof(u32) */
|
||||
handle_dwords = f_handle.handle_bytes >> 2;
|
||||
|
||||
/* we ask for a non connected handle */
|
||||
/* we ask for a non connectable maybe decodeable file handle */
|
||||
retval = exportfs_encode_fh(path->dentry,
|
||||
(struct fid *)handle->f_handle,
|
||||
&handle_dwords, 0);
|
||||
&handle_dwords, fh_flags);
|
||||
handle->handle_type = retval;
|
||||
/* convert handle size to bytes */
|
||||
handle_bytes = handle_dwords * sizeof(u32);
|
||||
|
@ -84,6 +87,7 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||
* @handle: resulting file handle
|
||||
* @mnt_id: mount id of the file system containing the file
|
||||
* @flag: flag value to indicate whether to follow symlink or not
|
||||
* and whether a decodable file handle is required.
|
||||
*
|
||||
* @handle->handle_size indicate the space available to store the
|
||||
* variable part of the file handle in bytes. If there is not
|
||||
|
@ -96,17 +100,19 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
|||
{
|
||||
struct path path;
|
||||
int lookup_flags;
|
||||
int fh_flags;
|
||||
int err;
|
||||
|
||||
if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
|
||||
if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID))
|
||||
return -EINVAL;
|
||||
|
||||
lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
|
||||
fh_flags = (flag & AT_HANDLE_FID) ? EXPORT_FH_FID : 0;
|
||||
if (flag & AT_EMPTY_PATH)
|
||||
lookup_flags |= LOOKUP_EMPTY;
|
||||
err = user_path_at(dfd, name, lookup_flags, &path);
|
||||
if (!err) {
|
||||
err = do_sys_name_to_handle(&path, handle, mnt_id);
|
||||
err = do_sys_name_to_handle(&path, handle, mnt_id, fh_flags);
|
||||
path_put(&path);
|
||||
}
|
||||
return err;
|
||||
|
|
|
@ -112,4 +112,9 @@
|
|||
|
||||
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||
|
||||
/* Flags for name_to_handle_at(2). We reuse AT_ flag space to save bits... */
|
||||
#define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to
|
||||
compare object identity and may not
|
||||
be usable to open_by_handle_at(2) */
|
||||
|
||||
#endif /* _UAPI_LINUX_FCNTL_H */
|
||||
|
|
Loading…
Reference in New Issue