VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100   1) // SPDX-License-Identifier: GPL-2.0
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   2) #include <linux/syscalls.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   3) #include <linux/slab.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   4) #include <linux/fs.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   5) #include <linux/file.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   6) #include <linux/mount.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   7) #include <linux/namei.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   8) #include <linux/exportfs.h>
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530   9) #include <linux/fs_struct.h>
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  10) #include <linux/fsnotify.h>
ed5afeaf42220 (Jeff Mahoney       2011-04-14 15:22:16 -0700  11) #include <linux/personality.h>
7c0f6ba682b9c (Linus Torvalds     2016-12-24 11:46:01 -0800  12) #include <linux/uaccess.h>
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400  13) #include <linux/compat.h>
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  14) #include "internal.h"
15169fe784a98 (Al Viro            2011-11-25 00:50:41 -0500  15) #include "mount.h"
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  16) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  17) static long do_sys_name_to_handle(struct path *path,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  18) 				  struct file_handle __user *ufh,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  19) 				  int __user *mnt_id)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  20) {
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  21) 	long retval;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  22) 	struct file_handle f_handle;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  23) 	int handle_dwords, handle_bytes;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  24) 	struct file_handle *handle = NULL;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  25) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  26) 	/*
48fc7f7e787dd (Adam Buchbinder    2012-09-19 21:48:00 -0400  27) 	 * We need to make sure whether the file system
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  28) 	 * support decoding of the file handle
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  29) 	 */
d8c9584ea2a92 (Al Viro            2011-12-07 18:16:57 -0500  30) 	if (!path->dentry->d_sb->s_export_op ||
d8c9584ea2a92 (Al Viro            2011-12-07 18:16:57 -0500  31) 	    !path->dentry->d_sb->s_export_op->fh_to_dentry)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  32) 		return -EOPNOTSUPP;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  33) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  34) 	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  35) 		return -EFAULT;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  36) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  37) 	if (f_handle.handle_bytes > MAX_HANDLE_SZ)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  38) 		return -EINVAL;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  39) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  40) 	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  41) 			 GFP_KERNEL);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  42) 	if (!handle)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  43) 		return -ENOMEM;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  44) 
48fc7f7e787dd (Adam Buchbinder    2012-09-19 21:48:00 -0400  45) 	/* convert handle size to multiple of sizeof(u32) */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  46) 	handle_dwords = f_handle.handle_bytes >> 2;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  47) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  48) 	/* we ask for a non connected handle */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  49) 	retval = exportfs_encode_fh(path->dentry,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  50) 				    (struct fid *)handle->f_handle,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  51) 				    &handle_dwords,  0);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  52) 	handle->handle_type = retval;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  53) 	/* convert handle size to bytes */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  54) 	handle_bytes = handle_dwords * sizeof(u32);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  55) 	handle->handle_bytes = handle_bytes;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  56) 	if ((handle->handle_bytes > f_handle.handle_bytes) ||
216b6cbdcbd86 (Namjae Jeon        2012-08-29 10:10:10 -0400  57) 	    (retval == FILEID_INVALID) || (retval == -ENOSPC)) {
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  58) 		/* As per old exportfs_encode_fh documentation
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  59) 		 * we could return ENOSPC to indicate overflow
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  60) 		 * But file system returned 255 always. So handle
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  61) 		 * both the values
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  62) 		 */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  63) 		/*
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  64) 		 * set the handle size to zero so we copy only
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  65) 		 * non variable part of the file_handle
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  66) 		 */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  67) 		handle_bytes = 0;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  68) 		retval = -EOVERFLOW;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  69) 	} else
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  70) 		retval = 0;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  71) 	/* copy the mount id */
6391af6f5829e (David Windsor      2017-06-10 22:50:31 -0400  72) 	if (put_user(real_mount(path->mnt)->mnt_id, mnt_id) ||
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  73) 	    copy_to_user(ufh, handle,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  74) 			 sizeof(struct file_handle) + handle_bytes))
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  75) 		retval = -EFAULT;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  76) 	kfree(handle);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  77) 	return retval;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  78) }
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  79) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  80) /**
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  81)  * sys_name_to_handle_at: convert name to handle
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  82)  * @dfd: directory relative to which name is interpreted if not absolute
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  83)  * @name: name that should be converted to handle.
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  84)  * @handle: resulting file handle
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  85)  * @mnt_id: mount id of the file system containing the file
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  86)  * @flag: flag value to indicate whether to follow symlink or not
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  87)  *
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  88)  * @handle->handle_size indicate the space available to store the
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  89)  * variable part of the file handle in bytes. If there is not
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  90)  * enough space, the field is updated to return the minimum
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  91)  * value required.
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  92)  */
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  93) SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  94) 		struct file_handle __user *, handle, int __user *, mnt_id,
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  95) 		int, flag)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  96) {
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  97) 	struct path path;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  98) 	int lookup_flags;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530  99) 	int err;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 100) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 101) 	if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 102) 		return -EINVAL;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 103) 
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 104) 	lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 105) 	if (flag & AT_EMPTY_PATH)
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 106) 		lookup_flags |= LOOKUP_EMPTY;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 107) 	err = user_path_at(dfd, name, lookup_flags, &path);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 108) 	if (!err) {
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 109) 		err = do_sys_name_to_handle(&path, handle, mnt_id);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 110) 		path_put(&path);
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 111) 	}
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 112) 	return err;
990d6c2d7aee9 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 113) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 114) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 115) static struct vfsmount *get_vfsmount_from_fd(int fd)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 116) {
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 117) 	struct vfsmount *mnt;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 118) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 119) 	if (fd == AT_FDCWD) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 120) 		struct fs_struct *fs = current->fs;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 121) 		spin_lock(&fs->lock);
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 122) 		mnt = mntget(fs->pwd.mnt);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 123) 		spin_unlock(&fs->lock);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 124) 	} else {
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 125) 		struct fd f = fdget(fd);
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 126) 		if (!f.file)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 127) 			return ERR_PTR(-EBADF);
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 128) 		mnt = mntget(f.file->f_path.mnt);
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 129) 		fdput(f);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 130) 	}
2903ff019b346 (Al Viro            2012-08-28 12:52:22 -0400 131) 	return mnt;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 132) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 133) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 134) static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 135) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 136) 	return 1;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 137) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 138) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 139) static int do_handle_to_path(int mountdirfd, struct file_handle *handle,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 140) 			     struct path *path)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 141) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 142) 	int retval = 0;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 143) 	int handle_dwords;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 144) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 145) 	path->mnt = get_vfsmount_from_fd(mountdirfd);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 146) 	if (IS_ERR(path->mnt)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 147) 		retval = PTR_ERR(path->mnt);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 148) 		goto out_err;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 149) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 150) 	/* change the handle size to multiple of sizeof(u32) */
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 151) 	handle_dwords = handle->handle_bytes >> 2;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 152) 	path->dentry = exportfs_decode_fh(path->mnt,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 153) 					  (struct fid *)handle->f_handle,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 154) 					  handle_dwords, handle->handle_type,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 155) 					  vfs_dentry_acceptable, NULL);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 156) 	if (IS_ERR(path->dentry)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 157) 		retval = PTR_ERR(path->dentry);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 158) 		goto out_mnt;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 159) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 160) 	return 0;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 161) out_mnt:
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 162) 	mntput(path->mnt);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 163) out_err:
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 164) 	return retval;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 165) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 166) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 167) static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 168) 		   struct path *path)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 169) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 170) 	int retval = 0;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 171) 	struct file_handle f_handle;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 172) 	struct file_handle *handle = NULL;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 173) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 174) 	/*
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 175) 	 * With handle we don't look at the execute bit on the
3d742d4b6ebb3 (Randy Dunlap       2021-02-24 12:00:48 -0800 176) 	 * directory. Ideally we would like CAP_DAC_SEARCH.
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 177) 	 * But we don't have that
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 178) 	 */
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 179) 	if (!capable(CAP_DAC_READ_SEARCH)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 180) 		retval = -EPERM;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 181) 		goto out_err;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 182) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 183) 	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 184) 		retval = -EFAULT;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 185) 		goto out_err;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 186) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 187) 	if ((f_handle.handle_bytes > MAX_HANDLE_SZ) ||
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 188) 	    (f_handle.handle_bytes == 0)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 189) 		retval = -EINVAL;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 190) 		goto out_err;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 191) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 192) 	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 193) 			 GFP_KERNEL);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 194) 	if (!handle) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 195) 		retval = -ENOMEM;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 196) 		goto out_err;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 197) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 198) 	/* copy the full handle */
161f873b89136 (Sasha Levin        2015-01-28 15:30:43 -0500 199) 	*handle = f_handle;
161f873b89136 (Sasha Levin        2015-01-28 15:30:43 -0500 200) 	if (copy_from_user(&handle->f_handle,
161f873b89136 (Sasha Levin        2015-01-28 15:30:43 -0500 201) 			   &ufh->f_handle,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 202) 			   f_handle.handle_bytes)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 203) 		retval = -EFAULT;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 204) 		goto out_handle;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 205) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 206) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 207) 	retval = do_handle_to_path(mountdirfd, handle, path);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 208) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 209) out_handle:
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 210) 	kfree(handle);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 211) out_err:
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 212) 	return retval;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 213) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 214) 
73ecf5cf141a0 (Al Viro            2017-10-14 13:18:33 -0400 215) static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
73ecf5cf141a0 (Al Viro            2017-10-14 13:18:33 -0400 216) 			   int open_flag)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 217) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 218) 	long retval = 0;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 219) 	struct path path;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 220) 	struct file *file;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 221) 	int fd;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 222) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 223) 	retval = handle_to_path(mountdirfd, ufh, &path);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 224) 	if (retval)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 225) 		return retval;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 226) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 227) 	fd = get_unused_fd_flags(open_flag);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 228) 	if (fd < 0) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 229) 		path_put(&path);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 230) 		return fd;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 231) 	}
378c6520e7d29 (Jann Horn          2016-03-22 14:25:36 -0700 232) 	file = file_open_root(path.dentry, path.mnt, "", open_flag, 0);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 233) 	if (IS_ERR(file)) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 234) 		put_unused_fd(fd);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 235) 		retval =  PTR_ERR(file);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 236) 	} else {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 237) 		retval = fd;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 238) 		fsnotify_open(file);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 239) 		fd_install(fd, file);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 240) 	}
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 241) 	path_put(&path);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 242) 	return retval;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 243) }
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 244) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 245) /**
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 246)  * sys_open_by_handle_at: Open the file handle
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 247)  * @mountdirfd: directory file descriptor
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 248)  * @handle: file handle to be opened
a92c7ba982e39 (Valdis Kletnieks   2019-08-07 19:22:34 -0400 249)  * @flags: open flags.
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 250)  *
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 251)  * @mountdirfd indicate the directory file descriptor
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 252)  * of the mount point. file handle is decoded relative
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 253)  * to the vfsmount pointed by the @mountdirfd. @flags
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 254)  * value is same as the open(2) flags.
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 255)  */
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 256) SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 257) 		struct file_handle __user *, handle,
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 258) 		int, flags)
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 259) {
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 260) 	long ret;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 261) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 262) 	if (force_o_largefile())
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 263) 		flags |= O_LARGEFILE;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 264) 
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 265) 	ret = do_handle_open(mountdirfd, handle, flags);
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 266) 	return ret;
becfd1f375447 (Aneesh Kumar K.V   2011-01-29 18:43:26 +0530 267) }
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 268) 
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 269) #ifdef CONFIG_COMPAT
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 270) /*
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 271)  * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 272)  * doesn't set the O_LARGEFILE flag.
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 273)  */
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 274) COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 275) 			     struct file_handle __user *, handle, int, flags)
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 276) {
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 277) 	return do_handle_open(mountdirfd, handle, flags);
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 278) }
2b8910264a7fe (Al Viro            2017-04-08 18:16:56 -0400 279) #endif