On Wed, Sep 10, 2025 at 11:47 PM Thomas Bertschinger <tahbertschinger@xxxxxxxxx> wrote: > > The handle_type field of struct file_handle is already being used to > pass "user" flags to open_by_handle_at() in the upper 16 bits. > > Bits 8..15 are still unused, as FS implementations are expected to only > set the lower 8 bits. > > This change prepares the VFS to pass flags to FS implementations of > fh_to_{dentry,parent}() using the previously unused bits 8..15 of > handle_type. > > The user is prevented from setting VFS flags in a file handle--such a > handle will be rejected by open_by_handle_at(2). Only the VFS can set > those flags before passing the handle to the FS. > > Suggested-by: Amir Goldstein <amir73il@xxxxxxxxx> > Signed-off-by: Thomas Bertschinger <tahbertschinger@xxxxxxxxx> Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx> > --- > fs/exportfs/expfs.c | 2 +- > fs/fhandle.c | 2 +- > include/linux/exportfs.h | 29 ++++++++++++++++++++++++++--- > 3 files changed, 28 insertions(+), 5 deletions(-) > > diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c > index d3e55de4a2a2..949ce6ef6c4e 100644 > --- a/fs/exportfs/expfs.c > +++ b/fs/exportfs/expfs.c > @@ -391,7 +391,7 @@ int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, > else > type = nop->encode_fh(inode, fid->raw, max_len, parent); > > - if (type > 0 && FILEID_USER_FLAGS(type)) { > + if (type > 0 && (type & ~FILEID_HANDLE_TYPE_MASK)) { > pr_warn_once("%s: unexpected fh type value 0x%x from fstype %s.\n", > __func__, type, inode->i_sb->s_type->name); > return -EINVAL; > diff --git a/fs/fhandle.c b/fs/fhandle.c > index 01fc209853d8..276c16454eb7 100644 > --- a/fs/fhandle.c > +++ b/fs/fhandle.c > @@ -342,7 +342,7 @@ struct file_handle *get_user_handle(struct file_handle __user *ufh) > (f_handle.handle_bytes == 0)) > return ERR_PTR(-EINVAL); > > - if (f_handle.handle_type < 0 || > + if (f_handle.handle_type < 0 || FILEID_FS_FLAGS(f_handle.handle_type) || > FILEID_USER_FLAGS(f_handle.handle_type) & ~FILEID_VALID_USER_FLAGS) > return ERR_PTR(-EINVAL); > > diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h > index cfb0dd1ea49c..30a9791d88e0 100644 > --- a/include/linux/exportfs.h > +++ b/include/linux/exportfs.h > @@ -173,10 +173,33 @@ struct handle_to_path_ctx { > #define EXPORT_FH_DIR_ONLY 0x4 /* Only decode file handle for a directory */ > > /* > - * Filesystems use only lower 8 bits of file_handle type for fid_type. > - * name_to_handle_at() uses upper 16 bits of type as user flags to be > - * interpreted by open_by_handle_at(). > + * The 32 bits of the handle_type field of struct file_handle are used for a few > + * different purposes: > + * > + * Filesystems use only lower 8 bits of file_handle type for fid_type. > + * > + * VFS uses bits 8..15 of the handle_type to pass flags to the FS > + * implementation of fh_to_{dentry,parent}(). > + * > + * name_to_handle_at() uses upper 16 bits of type as user flags to be > + * interpreted by open_by_handle_at(). > + * > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > + * | user flags | VFS flags | fid_type | > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > + * (MSB) (LSB) > + * > + * Filesystems are expected not to fill in any bits outside of fid_type in > + * their encode_fh() implementation. > */ > +#define FILEID_HANDLE_TYPE_MASK 0xff > +#define FILEID_TYPE(type) ((type) & FILEID_HANDLE_TYPE_MASK) > + > +/* VFS flags: */ > +#define FILEID_FS_FLAGS_MASK 0xff00 > +#define FILEID_FS_FLAGS(flags) ((flags) & FILEID_FS_FLAGS_MASK) > + > +/* User flags: */ > #define FILEID_USER_FLAGS_MASK 0xffff0000 > #define FILEID_USER_FLAGS(type) ((type) & FILEID_USER_FLAGS_MASK) > > -- > 2.51.0 >