mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
fhandle: expose u64 mount id to name_to_handle_at(2)
Now that we provide a unique 64-bit mount ID interface in statx(2), we can now provide a race-free way for name_to_handle_at(2) to provide a file handle and corresponding mount without needing to worry about racing with /proc/mountinfo parsing or having to open a file just to do statx(2). While this is not necessary if you are using AT_EMPTY_PATH and don't care about an extra statx(2) call, users that pass full paths into name_to_handle_at(2) need to know which mount the file handle comes from (to make sure they don't try to open_by_handle_at a file handle from a different filesystem) and switching to AT_EMPTY_PATH would require allocating a file for every name_to_handle_at(2) call, turning err = name_to_handle_at(-EBADF, "/foo/bar/baz", &handle, &mntid, AT_HANDLE_MNT_ID_UNIQUE); into int fd = openat(-EBADF, "/foo/bar/baz", O_PATH | O_CLOEXEC); err1 = name_to_handle_at(fd, "", &handle, &unused_mntid, AT_EMPTY_PATH); err2 = statx(fd, "", AT_EMPTY_PATH, STATX_MNT_ID_UNIQUE, &statxbuf); mntid = statxbuf.stx_mnt_id; close(fd); Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Link: https://lore.kernel.org/r/20240828-exportfs-u64-mount-id-v3-2-10c2c4c16708@cyphar.com Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
b4fef22c2f
commit
4356d575ef
29
fs/fhandle.c
29
fs/fhandle.c
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
static long do_sys_name_to_handle(const struct path *path,
|
static long do_sys_name_to_handle(const struct path *path,
|
||||||
struct file_handle __user *ufh,
|
struct file_handle __user *ufh,
|
||||||
int __user *mnt_id, int fh_flags)
|
void __user *mnt_id, bool unique_mntid,
|
||||||
|
int fh_flags)
|
||||||
{
|
{
|
||||||
long retval;
|
long retval;
|
||||||
struct file_handle f_handle;
|
struct file_handle f_handle;
|
||||||
@ -69,9 +70,19 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||||||
} else
|
} else
|
||||||
retval = 0;
|
retval = 0;
|
||||||
/* copy the mount id */
|
/* copy the mount id */
|
||||||
if (put_user(real_mount(path->mnt)->mnt_id, mnt_id) ||
|
if (unique_mntid) {
|
||||||
copy_to_user(ufh, handle,
|
if (put_user(real_mount(path->mnt)->mnt_id_unique,
|
||||||
struct_size(handle, f_handle, handle_bytes)))
|
(u64 __user *) mnt_id))
|
||||||
|
retval = -EFAULT;
|
||||||
|
} else {
|
||||||
|
if (put_user(real_mount(path->mnt)->mnt_id,
|
||||||
|
(int __user *) mnt_id))
|
||||||
|
retval = -EFAULT;
|
||||||
|
}
|
||||||
|
/* copy the handle */
|
||||||
|
if (retval != -EFAULT &&
|
||||||
|
copy_to_user(ufh, handle,
|
||||||
|
struct_size(handle, f_handle, handle_bytes)))
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
kfree(handle);
|
kfree(handle);
|
||||||
return retval;
|
return retval;
|
||||||
@ -83,6 +94,7 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||||||
* @name: name that should be converted to handle.
|
* @name: name that should be converted to handle.
|
||||||
* @handle: resulting file handle
|
* @handle: resulting file handle
|
||||||
* @mnt_id: mount id of the file system containing the file
|
* @mnt_id: mount id of the file system containing the file
|
||||||
|
* (u64 if AT_HANDLE_MNT_ID_UNIQUE, otherwise int)
|
||||||
* @flag: flag value to indicate whether to follow symlink or not
|
* @flag: flag value to indicate whether to follow symlink or not
|
||||||
* and whether a decodable file handle is required.
|
* and whether a decodable file handle is required.
|
||||||
*
|
*
|
||||||
@ -92,7 +104,7 @@ static long do_sys_name_to_handle(const struct path *path,
|
|||||||
* value required.
|
* value required.
|
||||||
*/
|
*/
|
||||||
SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
||||||
struct file_handle __user *, handle, int __user *, mnt_id,
|
struct file_handle __user *, handle, void __user *, mnt_id,
|
||||||
int, flag)
|
int, flag)
|
||||||
{
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
@ -100,7 +112,8 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
|||||||
int fh_flags;
|
int fh_flags;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID))
|
if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID |
|
||||||
|
AT_HANDLE_MNT_ID_UNIQUE))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
|
lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
|
||||||
@ -109,7 +122,9 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
|||||||
lookup_flags |= LOOKUP_EMPTY;
|
lookup_flags |= LOOKUP_EMPTY;
|
||||||
err = user_path_at(dfd, name, lookup_flags, &path);
|
err = user_path_at(dfd, name, lookup_flags, &path);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
err = do_sys_name_to_handle(&path, handle, mnt_id, fh_flags);
|
err = do_sys_name_to_handle(&path, handle, mnt_id,
|
||||||
|
flag & AT_HANDLE_MNT_ID_UNIQUE,
|
||||||
|
fh_flags);
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
@ -870,7 +870,7 @@ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
|
|||||||
#endif
|
#endif
|
||||||
asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
|
asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
|
||||||
struct file_handle __user *handle,
|
struct file_handle __user *handle,
|
||||||
int __user *mnt_id, int flag);
|
void __user *mnt_id, int flag);
|
||||||
asmlinkage long sys_open_by_handle_at(int mountdirfd,
|
asmlinkage long sys_open_by_handle_at(int mountdirfd,
|
||||||
struct file_handle __user *handle,
|
struct file_handle __user *handle,
|
||||||
int flags);
|
int flags);
|
||||||
|
@ -152,6 +152,7 @@
|
|||||||
#define AT_HANDLE_FID 0x200 /* File handle is needed to compare
|
#define AT_HANDLE_FID 0x200 /* File handle is needed to compare
|
||||||
object identity and may not be
|
object identity and may not be
|
||||||
usable with open_by_handle_at(2). */
|
usable with open_by_handle_at(2). */
|
||||||
|
#define AT_HANDLE_MNT_ID_UNIQUE 0x001 /* Return the u64 unique mount ID. */
|
||||||
|
|
||||||
#if defined(__KERNEL__)
|
#if defined(__KERNEL__)
|
||||||
#define AT_GETATTR_NOSEC 0x80000000
|
#define AT_GETATTR_NOSEC 0x80000000
|
||||||
|
Loading…
Reference in New Issue
Block a user