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 Signed-off-by: Thomas Bertschinger Reviewed-by: Amir Goldstein --- 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 7cc17e03e632..2dc669aeb520 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