b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/ioctl.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1991, 1992 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) #include <linux/syscalls.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/mm.h>
16f7e0fe2ecc3 (Randy Dunlap 2006-01-11 12:17:46 -0800 10) #include <linux/capability.h>
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 11) #include <linux/compat.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/security.h>
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 15) #include <linux/export.h>
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 16) #include <linux/uaccess.h>
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 17) #include <linux/writeback.h>
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 18) #include <linux/buffer_head.h>
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 19) #include <linux/falloc.h>
f361bf4a66c9b (Ingo Molnar 2017-02-03 23:47:37 +0100 20) #include <linux/sched/signal.h>
10c5db286452b (Christoph Hellwig 2020-05-23 09:30:11 +0200 21) #include <linux/fiemap.h>
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 22) #include <linux/mount.h>
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 23) #include <linux/fscrypt.h>
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 24) #include <linux/fileattr.h>
f361bf4a66c9b (Ingo Molnar 2017-02-03 23:47:37 +0100 25)
66cf191f3eae4 (Al Viro 2016-01-07 09:53:30 -0500 26) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) #include <asm/ioctls.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 30) /* So that the fiemap access checks can't overflow on 32 bit machines. */
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 31) #define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 32)
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 33) /**
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 34) * vfs_ioctl - call filesystem specific ioctl methods
f6a4c8bdb3037 (Christoph Hellwig 2008-02-09 00:10:16 -0800 35) * @filp: open file to invoke ioctl method on
f6a4c8bdb3037 (Christoph Hellwig 2008-02-09 00:10:16 -0800 36) * @cmd: ioctl command to execute
f6a4c8bdb3037 (Christoph Hellwig 2008-02-09 00:10:16 -0800 37) * @arg: command-specific argument for ioctl
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 38) *
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 39) * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 40) * returns -ENOTTY.
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 41) *
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 42) * Returns 0 on success, -errno on error.
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 43) */
66cf191f3eae4 (Al Viro 2016-01-07 09:53:30 -0500 44) long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) int error = -ENOTTY;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 48) if (!filp->f_op->unlocked_ioctl)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50)
b19dd42faf413 (Arnd Bergmann 2010-07-04 00:15:10 +0200 51) error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
b19dd42faf413 (Arnd Bergmann 2010-07-04 00:15:10 +0200 52) if (error == -ENOIOCTLCMD)
07d106d0a33d6 (Linus Torvalds 2012-01-05 15:40:12 -0800 53) error = -ENOTTY;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) }
9df6702ad0e85 (Miklos Szeredi 2018-07-18 15:44:40 +0200 57) EXPORT_SYMBOL(vfs_ioctl);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 59) static int ioctl_fibmap(struct file *filp, int __user *p)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 60) {
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 61) struct inode *inode = file_inode(filp);
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 62) struct super_block *sb = inode->i_sb;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 63) int error, ur_block;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 64) sector_t block;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 65)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 66) if (!capable(CAP_SYS_RAWIO))
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 67) return -EPERM;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 68)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 69) error = get_user(ur_block, p);
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 70) if (error)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 71) return error;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 72)
324282c0252a4 (Carlos Maiolino 2020-01-09 14:30:45 +0100 73) if (ur_block < 0)
324282c0252a4 (Carlos Maiolino 2020-01-09 14:30:45 +0100 74) return -EINVAL;
324282c0252a4 (Carlos Maiolino 2020-01-09 14:30:45 +0100 75)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 76) block = ur_block;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 77) error = bmap(inode, &block);
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 78)
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 79) if (block > INT_MAX) {
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 80) error = -ERANGE;
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 81) pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 82) current->comm, task_pid_nr(current),
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 83) sb->s_id, filp);
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 84) }
b75dfde121299 (Ritesh Harjani 2020-04-30 07:57:46 -0700 85)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 86) if (error)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 87) ur_block = 0;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 88) else
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 89) ur_block = block;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 90)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 91) if (put_user(ur_block, p))
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 92) error = -EFAULT;
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 93)
0d89fdae2afe8 (Carlos Maiolino 2020-01-09 14:30:44 +0100 94) return error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 95) }
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 96)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 97) /**
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 98) * fiemap_fill_next_extent - Fiemap helper function
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 99) * @fieinfo: Fiemap context passed into ->fiemap
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 100) * @logical: Extent logical start offset, in bytes
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 101) * @phys: Extent physical start offset, in bytes
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 102) * @len: Extent length, in bytes
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 103) * @flags: FIEMAP_EXTENT flags that describe this extent
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 104) *
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 105) * Called from file system ->fiemap callback. Will populate extent
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 106) * info as passed in via arguments and copy to user memory. On
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 107) * success, extent count on fieinfo is incremented.
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 108) *
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 109) * Returns 0 on success, -errno on error, 1 if this was the last
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 110) * extent that will fit in user array.
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 111) */
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 112) #define SET_UNKNOWN_FLAGS (FIEMAP_EXTENT_DELALLOC)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 113) #define SET_NO_UNMOUNTED_IO_FLAGS (FIEMAP_EXTENT_DATA_ENCRYPTED)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 114) #define SET_NOT_ALIGNED_FLAGS (FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 115) int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 116) u64 phys, u64 len, u32 flags)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 117) {
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 118) struct fiemap_extent extent;
ecf5632dd189a (Namhyung Kim 2011-01-16 23:28:17 +0900 119) struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 120)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 121) /* only count the extents */
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 122) if (fieinfo->fi_extents_max == 0) {
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 123) fieinfo->fi_extents_mapped++;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 124) return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 125) }
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 126)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 127) if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 128) return 1;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 129)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 130) if (flags & SET_UNKNOWN_FLAGS)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 131) flags |= FIEMAP_EXTENT_UNKNOWN;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 132) if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 133) flags |= FIEMAP_EXTENT_ENCODED;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 134) if (flags & SET_NOT_ALIGNED_FLAGS)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 135) flags |= FIEMAP_EXTENT_NOT_ALIGNED;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 136)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 137) memset(&extent, 0, sizeof(extent));
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 138) extent.fe_logical = logical;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 139) extent.fe_physical = phys;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 140) extent.fe_length = len;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 141) extent.fe_flags = flags;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 142)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 143) dest += fieinfo->fi_extents_mapped;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 144) if (copy_to_user(dest, &extent, sizeof(extent)))
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 145) return -EFAULT;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 146)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 147) fieinfo->fi_extents_mapped++;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 148) if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 149) return 1;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 150) return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 151) }
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 152) EXPORT_SYMBOL(fiemap_fill_next_extent);
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 153)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 154) /**
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 155) * fiemap_prep - check validity of requested flags for fiemap
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 156) * @inode: Inode to operate on
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 157) * @fieinfo: Fiemap context passed into ->fiemap
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 158) * @start: Start of the mapped range
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 159) * @len: Length of the mapped range, can be truncated by this function.
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 160) * @supported_flags: Set of fiemap flags that the file system understands
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 161) *
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 162) * This function must be called from each ->fiemap instance to validate the
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 163) * fiemap request against the file system parameters.
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 164) *
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 165) * Returns 0 on success, or a negative error on failure.
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 166) */
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 167) int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 168) u64 start, u64 *len, u32 supported_flags)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 169) {
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 170) u64 maxbytes = inode->i_sb->s_maxbytes;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 171) u32 incompat_flags;
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 172) int ret = 0;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 173)
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 174) if (*len == 0)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 175) return -EINVAL;
5aa98b706e83d (Jeff Layton 2009-09-18 13:05:50 -0700 176) if (start > maxbytes)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 177) return -EFBIG;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 178)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 179) /*
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 180) * Shrink request scope to what the fs can actually handle.
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 181) */
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 182) if (*len > maxbytes || (maxbytes - *len) < start)
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 183) *len = maxbytes - start;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 184)
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 185) supported_flags |= FIEMAP_FLAG_SYNC;
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 186) supported_flags &= FIEMAP_FLAGS_COMPAT;
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 187) incompat_flags = fieinfo->fi_flags & ~supported_flags;
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 188) if (incompat_flags) {
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 189) fieinfo->fi_flags = incompat_flags;
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 190) return -EBADR;
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 191) }
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 192)
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 193) if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 194) ret = filemap_write_and_wait(inode->i_mapping);
45dd052e67ad1 (Christoph Hellwig 2020-05-23 09:30:14 +0200 195) return ret;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 196) }
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 197) EXPORT_SYMBOL(fiemap_prep);
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 198)
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 199) static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 200) {
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 201) struct fiemap fiemap;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 202) struct fiemap_extent_info fieinfo = { 0, };
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 203) struct inode *inode = file_inode(filp);
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 204) int error;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 205)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 206) if (!inode->i_op->fiemap)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 207) return -EOPNOTSUPP;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 208)
ecf5632dd189a (Namhyung Kim 2011-01-16 23:28:17 +0900 209) if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 210) return -EFAULT;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 211)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 212) if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 213) return -EINVAL;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 214)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 215) fieinfo.fi_flags = fiemap.fm_flags;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 216) fieinfo.fi_extents_max = fiemap.fm_extent_count;
ecf5632dd189a (Namhyung Kim 2011-01-16 23:28:17 +0900 217) fieinfo.fi_extents_start = ufiemap->fm_extents;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 218)
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 219) error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start,
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 220) fiemap.fm_length);
c7d216e8c44cf (Christoph Hellwig 2020-05-23 09:30:15 +0200 221)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 222) fiemap.fm_flags = fieinfo.fi_flags;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 223) fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
ecf5632dd189a (Namhyung Kim 2011-01-16 23:28:17 +0900 224) if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 225) error = -EFAULT;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 226)
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 227) return error;
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 228) }
c4b929b85bdb6 (Mark Fasheh 2008-10-08 19:44:18 -0400 229)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 230) static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 231) u64 off, u64 olen, u64 destoff)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 232) {
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 233) struct fd src_file = fdget(srcfd);
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 234) loff_t cloned;
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 235) int ret;
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 236)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 237) if (!src_file.file)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 238) return -EBADF;
913b86e92e1f6 (Amir Goldstein 2016-09-23 11:38:10 +0300 239) ret = -EXDEV;
913b86e92e1f6 (Amir Goldstein 2016-09-23 11:38:10 +0300 240) if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
913b86e92e1f6 (Amir Goldstein 2016-09-23 11:38:10 +0300 241) goto fdput;
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 242) cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
452ce65951a2f (Darrick J. Wong 2018-10-30 10:41:56 +1100 243) olen, 0);
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 244) if (cloned < 0)
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 245) ret = cloned;
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 246) else if (olen && cloned != olen)
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 247) ret = -EINVAL;
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 248) else
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 249) ret = 0;
913b86e92e1f6 (Amir Goldstein 2016-09-23 11:38:10 +0300 250) fdput:
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 251) fdput(src_file);
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 252) return ret;
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 253) }
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 254)
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 255) static long ioctl_file_clone_range(struct file *file,
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 256) struct file_clone_range __user *argp)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 257) {
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 258) struct file_clone_range args;
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 259)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 260) if (copy_from_user(&args, argp, sizeof(args)))
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 261) return -EFAULT;
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 262) return ioctl_file_clone(file, args.src_fd, args.src_offset,
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 263) args.src_length, args.dest_offset);
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 264) }
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 265)
06270d5d6aefb (Adrian Bunk 2008-10-12 07:15:19 +0300 266) #ifdef CONFIG_BLOCK
06270d5d6aefb (Adrian Bunk 2008-10-12 07:15:19 +0300 267)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 268) static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 269) {
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 270) return (offset >> inode->i_blkbits);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 271) }
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 272)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 273) static inline loff_t blk_to_logical(struct inode *inode, sector_t blk)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 274) {
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 275) return (blk << inode->i_blkbits);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 276) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 277)
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 278) /**
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 279) * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 280) * @inode: the inode to map
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 281) * @fieinfo: the fiemap info struct that will be passed back to userspace
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 282) * @start: where to start mapping in the inode
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 283) * @len: how much space to map
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 284) * @get_block: the fs's get_block function
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 285) *
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 286) * This does FIEMAP for block based inodes. Basically it will just loop
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 287) * through get_block until we hit the number of extents we want to map, or we
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 288) * go past the end of the file and hit a hole.
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 289) *
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 290) * If it is possible to have data blocks beyond a hole past @inode->i_size, then
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 291) * please do not use this function, it will stop at the first unmapped block
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 292) * beyond i_size.
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 293) *
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 294) * If you use this function directly, you need to do your own locking. Use
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 295) * generic_block_fiemap if you want the locking done for you.
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 296) */
44ebcd06bbb3a (Christoph Hellwig 2020-05-23 09:30:10 +0200 297) static int __generic_block_fiemap(struct inode *inode,
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 298) struct fiemap_extent_info *fieinfo, loff_t start,
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 299) loff_t len, get_block_t *get_block)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 300) {
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 301) struct buffer_head map_bh;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 302) sector_t start_blk, last_blk;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 303) loff_t isize = i_size_read(inode);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 304) u64 logical = 0, phys = 0, size = 0;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 305) u32 flags = FIEMAP_EXTENT_MERGED;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 306) bool past_eof = false, whole_file = false;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 307) int ret = 0;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 308)
cddf8a2c4a828 (Christoph Hellwig 2020-05-23 09:30:13 +0200 309) ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_SYNC);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 310) if (ret)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 311) return ret;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 312)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 313) /*
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 314) * Either the i_mutex or other appropriate locking needs to be held
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 315) * since we expect isize to not change at all through the duration of
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 316) * this call.
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 317) */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 318) if (len >= isize) {
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 319) whole_file = true;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 320) len = isize;
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 321) }
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 322)
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 323) /*
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 324) * Some filesystems can't deal with being asked to map less than
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 325) * blocksize, so make sure our len is at least block length.
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 326) */
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 327) if (logical_to_blk(inode, len) == 0)
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 328) len = blk_to_logical(inode, 1);
d54cdc8ca7aab (Josef Bacik 2011-02-01 15:52:47 -0800 329)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 330) start_blk = logical_to_blk(inode, start);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 331) last_blk = logical_to_blk(inode, start + len - 1);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 332)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 333) do {
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 334) /*
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 335) * we set b_size to the total size we want so it will map as
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 336) * many contiguous blocks as possible at once
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 337) */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 338) memset(&map_bh, 0, sizeof(struct buffer_head));
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 339) map_bh.b_size = len;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 340)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 341) ret = get_block(inode, start_blk, &map_bh, 0);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 342) if (ret)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 343) break;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 344)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 345) /* HOLE */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 346) if (!buffer_mapped(&map_bh)) {
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 347) start_blk++;
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 348)
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 349) /*
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 350) * We want to handle the case where there is an
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 351) * allocated block at the front of the file, and then
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 352) * nothing but holes up to the end of the file properly,
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 353) * to make sure that extent at the front gets properly
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 354) * marked with FIEMAP_EXTENT_LAST
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 355) */
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 356) if (!past_eof &&
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 357) blk_to_logical(inode, start_blk) >= isize)
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 358) past_eof = 1;
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 359)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 360) /*
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 361) * First hole after going past the EOF, this is our
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 362) * last extent
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 363) */
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 364) if (past_eof && size) {
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 365) flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 366) ret = fiemap_fill_next_extent(fieinfo, logical,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 367) phys, size,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 368) flags);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 369) } else if (size) {
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 370) ret = fiemap_fill_next_extent(fieinfo, logical,
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 371) phys, size, flags);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 372) size = 0;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 373) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 374)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 375) /* if we have holes up to/past EOF then we're done */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 376) if (start_blk > last_blk || past_eof || ret)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 377) break;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 378) } else {
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 379) /*
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 380) * We have gone over the length of what we wanted to
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 381) * map, and it wasn't the entire file, so add the extent
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 382) * we got last time and exit.
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 383) *
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 384) * This is for the case where say we want to map all the
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 385) * way up to the second to the last block in a file, but
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 386) * the last block is a hole, making the second to last
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 387) * block FIEMAP_EXTENT_LAST. In this case we want to
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 388) * see if there is a hole after the second to last block
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 389) * so we can mark it properly. If we found data after
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 390) * we exceeded the length we were requesting, then we
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 391) * are good to go, just add the extent to the fieinfo
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 392) * and break
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 393) */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 394) if (start_blk > last_blk && !whole_file) {
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 395) ret = fiemap_fill_next_extent(fieinfo, logical,
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 396) phys, size,
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 397) flags);
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 398) break;
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 399) }
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 400)
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 401) /*
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 402) * if size != 0 then we know we already have an extent
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 403) * to add, so add it.
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 404) */
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 405) if (size) {
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 406) ret = fiemap_fill_next_extent(fieinfo, logical,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 407) phys, size,
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 408) flags);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 409) if (ret)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 410) break;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 411) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 412)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 413) logical = blk_to_logical(inode, start_blk);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 414) phys = blk_to_logical(inode, map_bh.b_blocknr);
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 415) size = map_bh.b_size;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 416) flags = FIEMAP_EXTENT_MERGED;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 417)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 418) start_blk += logical_to_blk(inode, size);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 419)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 420) /*
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 421) * If we are past the EOF, then we need to make sure as
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 422) * soon as we find a hole that the last extent we found
df3935ffd6166 (Josef Bacik 2009-05-06 16:02:53 -0700 423) * is marked with FIEMAP_EXTENT_LAST
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 424) */
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 425) if (!past_eof && logical + size >= isize)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 426) past_eof = true;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 427) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 428) cond_resched();
913e027ca17ee (Dmitry Monakhov 2015-02-10 14:09:29 -0800 429) if (fatal_signal_pending(current)) {
913e027ca17ee (Dmitry Monakhov 2015-02-10 14:09:29 -0800 430) ret = -EINTR;
913e027ca17ee (Dmitry Monakhov 2015-02-10 14:09:29 -0800 431) break;
913e027ca17ee (Dmitry Monakhov 2015-02-10 14:09:29 -0800 432) }
913e027ca17ee (Dmitry Monakhov 2015-02-10 14:09:29 -0800 433)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 434) } while (1);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 435)
3a3076f4d6e2f (Josef Bacik 2010-04-23 12:17:17 -0400 436) /* If ret is 1 then we just hit the end of the extent array */
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 437) if (ret == 1)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 438) ret = 0;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 439)
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 440) return ret;
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 441) }
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 442)
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 443) /**
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 444) * generic_block_fiemap - FIEMAP for block based inodes
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 445) * @inode: The inode to map
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 446) * @fieinfo: The mapping information
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 447) * @start: The initial block to map
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 448) * @len: The length of the extect to attempt to map
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 449) * @get_block: The block mapping function for the fs
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 450) *
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 451) * Calls __generic_block_fiemap to map the inode, after taking
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 452) * the inode's mutex lock.
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 453) */
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 454)
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 455) int generic_block_fiemap(struct inode *inode,
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 456) struct fiemap_extent_info *fieinfo, u64 start,
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 457) u64 len, get_block_t *get_block)
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 458) {
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 459) int ret;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 460) inode_lock(inode);
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 461) ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 462) inode_unlock(inode);
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 463) return ret;
e9079cce20178 (Steven Whitehouse 2008-10-14 14:43:29 +0100 464) }
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 465) EXPORT_SYMBOL(generic_block_fiemap);
68c9d702bb72f (Josef Bacik 2008-10-03 17:32:43 -0400 466)
06270d5d6aefb (Adrian Bunk 2008-10-12 07:15:19 +0300 467) #endif /* CONFIG_BLOCK */
06270d5d6aefb (Adrian Bunk 2008-10-12 07:15:19 +0300 468)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 469) /*
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 470) * This provides compatibility with legacy XFS pre-allocation ioctls
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 471) * which predate the fallocate syscall.
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 472) *
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 473) * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 474) * are used here, rest are ignored.
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 475) */
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 476) static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 477) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 478) struct inode *inode = file_inode(filp);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 479) struct space_resv sr;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 480)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 481) if (copy_from_user(&sr, argp, sizeof(sr)))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 482) return -EFAULT;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 483)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 484) switch (sr.l_whence) {
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 485) case SEEK_SET:
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 486) break;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 487) case SEEK_CUR:
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 488) sr.l_start += filp->f_pos;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 489) break;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 490) case SEEK_END:
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 491) sr.l_start += i_size_read(inode);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 492) break;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 493) default:
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 494) return -EINVAL;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 495) }
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 496)
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 497) return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 498) sr.l_len);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 499) }
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 500)
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 501) /* on ia32 l_start is on a 32-bit boundary */
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 502) #if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 503) /* just account for different alignment */
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 504) static int compat_ioctl_preallocate(struct file *file, int mode,
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 505) struct space_resv_32 __user *argp)
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 506) {
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 507) struct inode *inode = file_inode(file);
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 508) struct space_resv_32 sr;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 509)
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 510) if (copy_from_user(&sr, argp, sizeof(sr)))
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 511) return -EFAULT;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 512)
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 513) switch (sr.l_whence) {
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 514) case SEEK_SET:
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 515) break;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 516) case SEEK_CUR:
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 517) sr.l_start += file->f_pos;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 518) break;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 519) case SEEK_END:
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 520) sr.l_start += i_size_read(inode);
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 521) break;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 522) default:
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 523) return -EINVAL;
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 524) }
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 525)
97eeb4d9d7556 (Linus Torvalds 2019-12-02 14:46:22 -0800 526) return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 527) }
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 528) #endif
011da44bc5b65 (Al Viro 2019-04-21 19:24:03 -0400 529)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 530) static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 531) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 532) switch (cmd) {
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 533) case FIBMAP:
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 534) return ioctl_fibmap(filp, p);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 535) case FS_IOC_RESVSP:
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 536) case FS_IOC_RESVSP64:
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 537) return ioctl_preallocate(filp, 0, p);
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 538) case FS_IOC_UNRESVSP:
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 539) case FS_IOC_UNRESVSP64:
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 540) return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 541) case FS_IOC_ZERO_RANGE:
837a6e7f5cdb5 (Christoph Hellwig 2019-10-24 22:26:02 -0700 542) return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 543) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 544)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 545) return -ENOIOCTLCMD;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 546) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 547)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 548) static int ioctl_fionbio(struct file *filp, int __user *argp)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 549) {
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 550) unsigned int flag;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 551) int on, error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 552)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 553) error = get_user(on, argp);
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 554) if (error)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 555) return error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 556) flag = O_NONBLOCK;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 557) #ifdef __sparc__
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 558) /* SunOS compatibility item. */
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 559) if (O_NONBLOCK != O_NDELAY)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 560) flag |= O_NDELAY;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 561) #endif
db1dd4d376134 (Jonathan Corbet 2009-02-06 15:25:24 -0700 562) spin_lock(&filp->f_lock);
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 563) if (on)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 564) filp->f_flags |= flag;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 565) else
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 566) filp->f_flags &= ~flag;
db1dd4d376134 (Jonathan Corbet 2009-02-06 15:25:24 -0700 567) spin_unlock(&filp->f_lock);
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 568) return error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 569) }
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 570)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 571) static int ioctl_fioasync(unsigned int fd, struct file *filp,
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 572) int __user *argp)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 573) {
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 574) unsigned int flag;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 575) int on, error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 576)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 577) error = get_user(on, argp);
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 578) if (error)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 579) return error;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 580) flag = on ? FASYNC : 0;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 581)
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 582) /* Did FASYNC state change ? */
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 583) if ((flag ^ filp->f_flags) & FASYNC) {
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 584) if (filp->f_op->fasync)
76398425bb06b (Jonathan Corbet 2009-02-01 14:26:59 -0700 585) /* fasync() adjusts filp->f_flags */
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 586) error = filp->f_op->fasync(fd, filp, on);
218d11a8b071b (Jonathan Corbet 2008-12-05 16:12:48 -0700 587) else
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 588) error = -ENOTTY;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 589) }
60aa49243d09a (Jonathan Corbet 2009-02-01 14:52:56 -0700 590) return error < 0 ? error : 0;
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 591) }
aa81a7c7120ad (Erez Zadok 2008-02-07 00:13:25 -0800 592)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 593) static int ioctl_fsfreeze(struct file *filp)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 594) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 595) struct super_block *sb = file_inode(filp)->i_sb;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 596)
f3f1a18330ac1 (Seth Forshee 2015-02-15 14:35:35 -0600 597) if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 598) return -EPERM;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 599)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 600) /* If filesystem doesn't support freeze feature, return. */
48b6bca6b7b83 (Benjamin Marzinski 2014-11-13 20:42:03 -0600 601) if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 602) return -EOPNOTSUPP;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 603)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 604) /* Freeze */
48b6bca6b7b83 (Benjamin Marzinski 2014-11-13 20:42:03 -0600 605) if (sb->s_op->freeze_super)
48b6bca6b7b83 (Benjamin Marzinski 2014-11-13 20:42:03 -0600 606) return sb->s_op->freeze_super(sb);
18e9e5104fcd9 (Josef Bacik 2010-03-23 10:34:56 -0400 607) return freeze_super(sb);
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 608) }
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 609)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 610) static int ioctl_fsthaw(struct file *filp)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 611) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 612) struct super_block *sb = file_inode(filp)->i_sb;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 613)
f3f1a18330ac1 (Seth Forshee 2015-02-15 14:35:35 -0600 614) if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 615) return -EPERM;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 616)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 617) /* Thaw */
48b6bca6b7b83 (Benjamin Marzinski 2014-11-13 20:42:03 -0600 618) if (sb->s_op->thaw_super)
48b6bca6b7b83 (Benjamin Marzinski 2014-11-13 20:42:03 -0600 619) return sb->s_op->thaw_super(sb);
18e9e5104fcd9 (Josef Bacik 2010-03-23 10:34:56 -0400 620) return thaw_super(sb);
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 621) }
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 622)
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 623) static int ioctl_file_dedupe_range(struct file *file,
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 624) struct file_dedupe_range __user *argp)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 625) {
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 626) struct file_dedupe_range *same = NULL;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 627) int ret;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 628) unsigned long size;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 629) u16 count;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 630)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 631) if (get_user(count, &argp->dest_count)) {
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 632) ret = -EFAULT;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 633) goto out;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 634) }
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 635)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 636) size = offsetof(struct file_dedupe_range __user, info[count]);
b71dbf1032f54 (Darrick J. Wong 2016-09-14 20:20:44 -0700 637) if (size > PAGE_SIZE) {
b71dbf1032f54 (Darrick J. Wong 2016-09-14 20:20:44 -0700 638) ret = -ENOMEM;
b71dbf1032f54 (Darrick J. Wong 2016-09-14 20:20:44 -0700 639) goto out;
b71dbf1032f54 (Darrick J. Wong 2016-09-14 20:20:44 -0700 640) }
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 641)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 642) same = memdup_user(argp, size);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 643) if (IS_ERR(same)) {
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 644) ret = PTR_ERR(same);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 645) same = NULL;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 646) goto out;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 647) }
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 648)
10eec60ce7918 (Scott Bauer 2016-07-27 19:11:29 -0600 649) same->dest_count = count;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 650) ret = vfs_dedupe_file_range(file, same);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 651) if (ret)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 652) goto out;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 653)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 654) ret = copy_to_user(argp, same, size);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 655) if (ret)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 656) ret = -EFAULT;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 657)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 658) out:
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 659) kfree(same);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 660) return ret;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 661) }
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 662)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 663) /**
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 664) * fileattr_fill_xflags - initialize fileattr with xflags
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 665) * @fa: fileattr pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 666) * @xflags: FS_XFLAG_* flags
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 667) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 668) * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 669) * other fields are zeroed.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 670) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 671) void fileattr_fill_xflags(struct fileattr *fa, u32 xflags)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 672) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 673) memset(fa, 0, sizeof(*fa));
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 674) fa->fsx_valid = true;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 675) fa->fsx_xflags = xflags;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 676) if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 677) fa->flags |= FS_IMMUTABLE_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 678) if (fa->fsx_xflags & FS_XFLAG_APPEND)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 679) fa->flags |= FS_APPEND_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 680) if (fa->fsx_xflags & FS_XFLAG_SYNC)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 681) fa->flags |= FS_SYNC_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 682) if (fa->fsx_xflags & FS_XFLAG_NOATIME)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 683) fa->flags |= FS_NOATIME_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 684) if (fa->fsx_xflags & FS_XFLAG_NODUMP)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 685) fa->flags |= FS_NODUMP_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 686) if (fa->fsx_xflags & FS_XFLAG_DAX)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 687) fa->flags |= FS_DAX_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 688) if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 689) fa->flags |= FS_PROJINHERIT_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 690) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 691) EXPORT_SYMBOL(fileattr_fill_xflags);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 692)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 693) /**
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 694) * fileattr_fill_flags - initialize fileattr with flags
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 695) * @fa: fileattr pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 696) * @flags: FS_*_FL flags
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 697) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 698) * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags).
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 699) * All other fields are zeroed.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 700) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 701) void fileattr_fill_flags(struct fileattr *fa, u32 flags)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 702) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 703) memset(fa, 0, sizeof(*fa));
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 704) fa->flags_valid = true;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 705) fa->flags = flags;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 706) if (fa->flags & FS_SYNC_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 707) fa->fsx_xflags |= FS_XFLAG_SYNC;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 708) if (fa->flags & FS_IMMUTABLE_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 709) fa->fsx_xflags |= FS_XFLAG_IMMUTABLE;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 710) if (fa->flags & FS_APPEND_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 711) fa->fsx_xflags |= FS_XFLAG_APPEND;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 712) if (fa->flags & FS_NODUMP_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 713) fa->fsx_xflags |= FS_XFLAG_NODUMP;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 714) if (fa->flags & FS_NOATIME_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 715) fa->fsx_xflags |= FS_XFLAG_NOATIME;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 716) if (fa->flags & FS_DAX_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 717) fa->fsx_xflags |= FS_XFLAG_DAX;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 718) if (fa->flags & FS_PROJINHERIT_FL)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 719) fa->fsx_xflags |= FS_XFLAG_PROJINHERIT;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 720) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 721) EXPORT_SYMBOL(fileattr_fill_flags);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 722)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 723) /**
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 724) * vfs_fileattr_get - retrieve miscellaneous file attributes
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 725) * @dentry: the object to retrieve from
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 726) * @fa: fileattr pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 727) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 728) * Call i_op->fileattr_get() callback, if exists.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 729) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 730) * Return: 0 on success, or a negative error on failure.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 731) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 732) int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 733) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 734) struct inode *inode = d_inode(dentry);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 735)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 736) if (!inode->i_op->fileattr_get)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 737) return -ENOIOCTLCMD;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 738)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 739) return inode->i_op->fileattr_get(dentry, fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 740) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 741) EXPORT_SYMBOL(vfs_fileattr_get);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 742)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 743) /**
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 744) * copy_fsxattr_to_user - copy fsxattr to userspace.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 745) * @fa: fileattr pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 746) * @ufa: fsxattr user pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 747) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 748) * Return: 0 on success, or -EFAULT on failure.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 749) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 750) int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 751) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 752) struct fsxattr xfa;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 753)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 754) memset(&xfa, 0, sizeof(xfa));
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 755) xfa.fsx_xflags = fa->fsx_xflags;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 756) xfa.fsx_extsize = fa->fsx_extsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 757) xfa.fsx_nextents = fa->fsx_nextents;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 758) xfa.fsx_projid = fa->fsx_projid;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 759) xfa.fsx_cowextsize = fa->fsx_cowextsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 760)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 761) if (copy_to_user(ufa, &xfa, sizeof(xfa)))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 762) return -EFAULT;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 763)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 764) return 0;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 765) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 766) EXPORT_SYMBOL(copy_fsxattr_to_user);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 767)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 768) static int copy_fsxattr_from_user(struct fileattr *fa,
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 769) struct fsxattr __user *ufa)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 770) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 771) struct fsxattr xfa;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 772)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 773) if (copy_from_user(&xfa, ufa, sizeof(xfa)))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 774) return -EFAULT;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 775)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 776) fileattr_fill_xflags(fa, xfa.fsx_xflags);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 777) fa->fsx_extsize = xfa.fsx_extsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 778) fa->fsx_nextents = xfa.fsx_nextents;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 779) fa->fsx_projid = xfa.fsx_projid;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 780) fa->fsx_cowextsize = xfa.fsx_cowextsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 781)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 782) return 0;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 783) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 784)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 785) /*
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 786) * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 787) * any invalid configurations.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 788) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 789) * Note: must be called with inode lock held.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 790) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 791) static int fileattr_set_prepare(struct inode *inode,
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 792) const struct fileattr *old_ma,
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 793) struct fileattr *fa)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 794) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 795) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 796)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 797) /*
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 798) * The IMMUTABLE and APPEND_ONLY flags can only be changed by
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 799) * the relevant capability.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 800) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 801) if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 802) !capable(CAP_LINUX_IMMUTABLE))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 803) return -EPERM;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 804)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 805) err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 806) if (err)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 807) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 808)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 809) /*
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 810) * Project Quota ID state is only allowed to change from within the init
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 811) * namespace. Enforce that restriction only if we are trying to change
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 812) * the quota ID state. Everything else is allowed in user namespaces.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 813) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 814) if (current_user_ns() != &init_user_ns) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 815) if (old_ma->fsx_projid != fa->fsx_projid)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 816) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 817) if ((old_ma->fsx_xflags ^ fa->fsx_xflags) &
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 818) FS_XFLAG_PROJINHERIT)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 819) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 820) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 821)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 822) /* Check extent size hints. */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 823) if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 824) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 825)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 826) if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 827) !S_ISDIR(inode->i_mode))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 828) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 829)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 830) if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 831) !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 832) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 833)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 834) /*
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 835) * It is only valid to set the DAX flag on regular files and
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 836) * directories on filesystems.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 837) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 838) if ((fa->fsx_xflags & FS_XFLAG_DAX) &&
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 839) !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 840) return -EINVAL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 841)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 842) /* Extent size hints of zero turn off the flags. */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 843) if (fa->fsx_extsize == 0)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 844) fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 845) if (fa->fsx_cowextsize == 0)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 846) fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 847)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 848) return 0;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 849) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 850)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 851) /**
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 852) * vfs_fileattr_set - change miscellaneous file attributes
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 853) * @mnt_userns: user namespace of the mount
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 854) * @dentry: the object to change
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 855) * @fa: fileattr pointer
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 856) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 857) * After verifying permissions, call i_op->fileattr_set() callback, if
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 858) * exists.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 859) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 860) * Verifying attributes involves retrieving current attributes with
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 861) * i_op->fileattr_get(), this also allows initializing attributes that have
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 862) * not been set by the caller to current values. Inode lock is held
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 863) * thoughout to prevent racing with another instance.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 864) *
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 865) * Return: 0 on success, or a negative error on failure.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 866) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 867) int vfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry,
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 868) struct fileattr *fa)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 869) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 870) struct inode *inode = d_inode(dentry);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 871) struct fileattr old_ma = {};
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 872) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 873)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 874) if (!inode->i_op->fileattr_set)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 875) return -ENOIOCTLCMD;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 876)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 877) if (!inode_owner_or_capable(mnt_userns, inode))
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 878) return -EPERM;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 879)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 880) inode_lock(inode);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 881) err = vfs_fileattr_get(dentry, &old_ma);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 882) if (!err) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 883) /* initialize missing bits from old_ma */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 884) if (fa->flags_valid) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 885) fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 886) fa->fsx_extsize = old_ma.fsx_extsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 887) fa->fsx_nextents = old_ma.fsx_nextents;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 888) fa->fsx_projid = old_ma.fsx_projid;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 889) fa->fsx_cowextsize = old_ma.fsx_cowextsize;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 890) } else {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 891) fa->flags |= old_ma.flags & ~FS_COMMON_FL;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 892) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 893) err = fileattr_set_prepare(inode, &old_ma, fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 894) if (!err)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 895) err = inode->i_op->fileattr_set(mnt_userns, dentry, fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 896) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 897) inode_unlock(inode);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 898)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 899) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 900) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 901) EXPORT_SYMBOL(vfs_fileattr_set);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 902)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 903) static int ioctl_getflags(struct file *file, unsigned int __user *argp)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 904) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 905) struct fileattr fa = { .flags_valid = true }; /* hint only */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 906) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 907)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 908) err = vfs_fileattr_get(file->f_path.dentry, &fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 909) if (!err)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 910) err = put_user(fa.flags, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 911) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 912) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 913)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 914) static int ioctl_setflags(struct file *file, unsigned int __user *argp)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 915) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 916) struct user_namespace *mnt_userns = file_mnt_user_ns(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 917) struct dentry *dentry = file->f_path.dentry;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 918) struct fileattr fa;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 919) unsigned int flags;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 920) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 921)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 922) err = get_user(flags, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 923) if (!err) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 924) err = mnt_want_write_file(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 925) if (!err) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 926) fileattr_fill_flags(&fa, flags);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 927) err = vfs_fileattr_set(mnt_userns, dentry, &fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 928) mnt_drop_write_file(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 929) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 930) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 931) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 932) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 933)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 934) static int ioctl_fsgetxattr(struct file *file, void __user *argp)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 935) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 936) struct fileattr fa = { .fsx_valid = true }; /* hint only */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 937) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 938)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 939) err = vfs_fileattr_get(file->f_path.dentry, &fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 940) if (!err)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 941) err = copy_fsxattr_to_user(&fa, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 942)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 943) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 944) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 945)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 946) static int ioctl_fssetxattr(struct file *file, void __user *argp)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 947) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 948) struct user_namespace *mnt_userns = file_mnt_user_ns(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 949) struct dentry *dentry = file->f_path.dentry;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 950) struct fileattr fa;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 951) int err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 952)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 953) err = copy_fsxattr_from_user(&fa, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 954) if (!err) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 955) err = mnt_want_write_file(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 956) if (!err) {
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 957) err = vfs_fileattr_set(mnt_userns, dentry, &fa);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 958) mnt_drop_write_file(file);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 959) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 960) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 961) return err;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 962) }
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 963)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 964) /*
deb21db7788b9 (Erez Zadok 2008-02-07 00:13:25 -0800 965) * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 966) * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 967) *
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 968) * When you add any new common ioctls to the switches above and below,
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 969) * please ensure they have compatible arguments in compat mode.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 970) */
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 971) static int do_vfs_ioctl(struct file *filp, unsigned int fd,
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 972) unsigned int cmd, unsigned long arg)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 973) {
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 974) void __user *argp = (void __user *)arg;
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 975) struct inode *inode = file_inode(filp);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 976)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 977) switch (cmd) {
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 978) case FIOCLEX:
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 979) set_close_on_exec(fd, 1);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 980) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 981)
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 982) case FIONCLEX:
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 983) set_close_on_exec(fd, 0);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 984) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 985)
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 986) case FIONBIO:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 987) return ioctl_fionbio(filp, argp);
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 988)
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 989) case FIOASYNC:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 990) return ioctl_fioasync(fd, filp, argp);
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 991)
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 992) case FIOQSIZE:
27a4f7e61e1eb (Namhyung Kim 2011-01-17 00:48:17 +0900 993) if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
27a4f7e61e1eb (Namhyung Kim 2011-01-17 00:48:17 +0900 994) S_ISLNK(inode->i_mode)) {
27a4f7e61e1eb (Namhyung Kim 2011-01-17 00:48:17 +0900 995) loff_t res = inode_get_bytes(inode);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 996) return copy_to_user(argp, &res, sizeof(res)) ?
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 997) -EFAULT : 0;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 998) }
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 999)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1000) return -ENOTTY;
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 1001)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 1002) case FIFREEZE:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1003) return ioctl_fsfreeze(filp);
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 1004)
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 1005) case FITHAW:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1006) return ioctl_fsthaw(filp);
fcccf502540e3 (Takashi Sato 2009-01-09 16:40:59 -0800 1007)
19ba0559f9ce1 (Aneesh Kumar K.V 2009-05-13 18:12:05 -0400 1008) case FS_IOC_FIEMAP:
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 1009) return ioctl_fiemap(filp, argp);
19ba0559f9ce1 (Aneesh Kumar K.V 2009-05-13 18:12:05 -0400 1010)
19ba0559f9ce1 (Aneesh Kumar K.V 2009-05-13 18:12:05 -0400 1011) case FIGETBSZ:
8f97d1e99149a (Amir Goldstein 2018-10-11 17:38:14 +0300 1012) /* anon_bdev filesystems may not have a block size */
8f97d1e99149a (Amir Goldstein 2018-10-11 17:38:14 +0300 1013) if (!inode->i_sb->s_blocksize)
8f97d1e99149a (Amir Goldstein 2018-10-11 17:38:14 +0300 1014) return -EINVAL;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1015)
34d3d0e65e3a8 (Al Viro 2019-04-21 18:45:28 -0400 1016) return put_user(inode->i_sb->s_blocksize, (int __user *)argp);
19ba0559f9ce1 (Aneesh Kumar K.V 2009-05-13 18:12:05 -0400 1017)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1018) case FICLONE:
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1019) return ioctl_file_clone(filp, arg, 0, 0, 0);
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1020)
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1021) case FICLONERANGE:
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1022) return ioctl_file_clone_range(filp, argp);
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1023)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1024) case FIDEDUPERANGE:
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1025) return ioctl_file_dedupe_range(filp, argp);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1026)
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1027) case FIONREAD:
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1028) if (!S_ISREG(inode->i_mode))
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1029) return vfs_ioctl(filp, cmd, arg);
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1030)
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1031) return put_user(i_size_read(inode) - filp->f_pos,
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1032) (int __user *)argp);
0a061743af93f (Arnd Bergmann 2020-02-07 17:55:48 +0100 1033)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1034) case FS_IOC_GETFLAGS:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1035) return ioctl_getflags(filp, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1036)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1037) case FS_IOC_SETFLAGS:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1038) return ioctl_setflags(filp, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1039)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1040) case FS_IOC_FSGETXATTR:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1041) return ioctl_fsgetxattr(filp, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1042)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1043) case FS_IOC_FSSETXATTR:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1044) return ioctl_fssetxattr(filp, argp);
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1045)
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 1046) default:
27a4f7e61e1eb (Namhyung Kim 2011-01-17 00:48:17 +0900 1047) if (S_ISREG(inode->i_mode))
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1048) return file_ioctl(filp, cmd, argp);
c9845ff1df5ba (Erez Zadok 2008-02-07 00:13:23 -0800 1049) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1050) }
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1051)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1052) return -ENOIOCTLCMD;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1053) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1054)
863b67e15177a (Christoph Hellwig 2020-07-14 09:00:51 +0200 1055) SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1056) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1057) struct fd f = fdget(fd);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1058) int error;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1059)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1060) if (!f.file)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1061) return -EBADF;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1062)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1063) error = security_file_ioctl(f.file, cmd, arg);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1064) if (error)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1065) goto out;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1066)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1067) error = do_vfs_ioctl(f.file, fd, cmd, arg);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1068) if (error == -ENOIOCTLCMD)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1069) error = vfs_ioctl(f.file, cmd, arg);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1070)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1071) out:
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1072) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1073) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1074) }
cbb60b924b9f3 (Dominik Brodowski 2018-03-13 21:43:59 +0100 1075)
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1076) #ifdef CONFIG_COMPAT
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1077) /**
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1078) * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1079) *
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1080) * This is not normally called as a function, but instead set in struct
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1081) * file_operations as
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1082) *
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1083) * .compat_ioctl = compat_ptr_ioctl,
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1084) *
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1085) * On most architectures, the compat_ptr_ioctl() just passes all arguments
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1086) * to the corresponding ->ioctl handler. The exception is arch/s390, where
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1087) * compat_ptr() clears the top bit of a 32-bit pointer value, so user space
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1088) * pointers to the second 2GB alias the first 2GB, as is the case for
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1089) * native 32-bit s390 user space.
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1090) *
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1091) * The compat_ptr_ioctl() function must therefore be used only with ioctl
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1092) * functions that either ignore the argument or pass a pointer to a
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1093) * compatible data type.
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1094) *
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1095) * If any ioctl command handled by fops->unlocked_ioctl passes a plain
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1096) * integer instead of a pointer, or any of the passed data types
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1097) * is incompatible between 32-bit and 64-bit architectures, a proper
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1098) * handler is required instead of compat_ptr_ioctl.
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1099) */
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1100) long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1101) {
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1102) if (!file->f_op->unlocked_ioctl)
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1103) return -ENOIOCTLCMD;
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1104)
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1105) return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1106) }
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1107) EXPORT_SYMBOL(compat_ptr_ioctl);
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1108)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1109) COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1110) compat_ulong_t, arg)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1111) {
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1112) struct fd f = fdget(fd);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1113) int error;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1114)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1115) if (!f.file)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1116) return -EBADF;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1117)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1118) /* RED-PEN how should LSM module know it's handling 32bit? */
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1119) error = security_file_ioctl(f.file, cmd, arg);
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1120) if (error)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1121) goto out;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1122)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1123) switch (cmd) {
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1124) /* FICLONE takes an int argument, so don't use compat_ptr() */
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1125) case FICLONE:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1126) error = ioctl_file_clone(f.file, arg, 0, 0, 0);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1127) break;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1128)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1129) #if defined(CONFIG_X86_64)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1130) /* these get messy on amd64 due to alignment differences */
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1131) case FS_IOC_RESVSP_32:
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1132) case FS_IOC_RESVSP64_32:
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1133) error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1134) break;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1135) case FS_IOC_UNRESVSP_32:
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1136) case FS_IOC_UNRESVSP64_32:
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1137) error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1138) compat_ptr(arg));
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1139) break;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1140) case FS_IOC_ZERO_RANGE_32:
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1141) error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1142) compat_ptr(arg));
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1143) break;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1144) #endif
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1145)
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1146) /*
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1147) * These access 32-bit values anyway so no further handling is
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1148) * necessary.
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1149) */
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1150) case FS_IOC32_GETFLAGS:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1151) case FS_IOC32_SETFLAGS:
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1152) cmd = (cmd == FS_IOC32_GETFLAGS) ?
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1153) FS_IOC_GETFLAGS : FS_IOC_SETFLAGS;
4c5b479975212 (Miklos Szeredi 2021-04-07 14:36:42 +0200 1154) fallthrough;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1155) /*
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1156) * everything else in do_vfs_ioctl() takes either a compatible
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1157) * pointer argument or no argument -- call it with a modified
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1158) * argument.
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1159) */
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1160) default:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1161) error = do_vfs_ioctl(f.file, fd, cmd,
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1162) (unsigned long)compat_ptr(arg));
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1163) if (error != -ENOIOCTLCMD)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1164) break;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1165)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1166) if (f.file->f_op->compat_ioctl)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1167) error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1168) if (error == -ENOIOCTLCMD)
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1169) error = -ENOTTY;
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1170) break;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1171) }
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1172)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1173) out:
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1174) fdput(f);
77b9040195dea (Arnd Bergmann 2019-11-27 21:25:36 +0100 1175)
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1176) return error;
2af563d071d63 (Arnd Bergmann 2019-06-07 10:06:42 +0200 1177) }
2952db0fd51b0 (Arnd Bergmann 2018-09-11 16:55:03 +0200 1178) #endif