1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/fs/ioctl.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 1991, 1992 Linus Torvalds
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/syscalls.h>
9*4882a593Smuzhiyun #include <linux/mm.h>
10*4882a593Smuzhiyun #include <linux/capability.h>
11*4882a593Smuzhiyun #include <linux/compat.h>
12*4882a593Smuzhiyun #include <linux/file.h>
13*4882a593Smuzhiyun #include <linux/fs.h>
14*4882a593Smuzhiyun #include <linux/security.h>
15*4882a593Smuzhiyun #include <linux/export.h>
16*4882a593Smuzhiyun #include <linux/uaccess.h>
17*4882a593Smuzhiyun #include <linux/writeback.h>
18*4882a593Smuzhiyun #include <linux/buffer_head.h>
19*4882a593Smuzhiyun #include <linux/falloc.h>
20*4882a593Smuzhiyun #include <linux/sched/signal.h>
21*4882a593Smuzhiyun #include <linux/fiemap.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "internal.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <asm/ioctls.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /* So that the fiemap access checks can't overflow on 32 bit machines. */
28*4882a593Smuzhiyun #define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /**
31*4882a593Smuzhiyun * vfs_ioctl - call filesystem specific ioctl methods
32*4882a593Smuzhiyun * @filp: open file to invoke ioctl method on
33*4882a593Smuzhiyun * @cmd: ioctl command to execute
34*4882a593Smuzhiyun * @arg: command-specific argument for ioctl
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
37*4882a593Smuzhiyun * returns -ENOTTY.
38*4882a593Smuzhiyun *
39*4882a593Smuzhiyun * Returns 0 on success, -errno on error.
40*4882a593Smuzhiyun */
vfs_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)41*4882a593Smuzhiyun long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun int error = -ENOTTY;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun if (!filp->f_op->unlocked_ioctl)
46*4882a593Smuzhiyun goto out;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
49*4882a593Smuzhiyun if (error == -ENOIOCTLCMD)
50*4882a593Smuzhiyun error = -ENOTTY;
51*4882a593Smuzhiyun out:
52*4882a593Smuzhiyun return error;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun EXPORT_SYMBOL(vfs_ioctl);
55*4882a593Smuzhiyun
ioctl_fibmap(struct file * filp,int __user * p)56*4882a593Smuzhiyun static int ioctl_fibmap(struct file *filp, int __user *p)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
59*4882a593Smuzhiyun struct super_block *sb = inode->i_sb;
60*4882a593Smuzhiyun int error, ur_block;
61*4882a593Smuzhiyun sector_t block;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (!capable(CAP_SYS_RAWIO))
64*4882a593Smuzhiyun return -EPERM;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun error = get_user(ur_block, p);
67*4882a593Smuzhiyun if (error)
68*4882a593Smuzhiyun return error;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun if (ur_block < 0)
71*4882a593Smuzhiyun return -EINVAL;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun block = ur_block;
74*4882a593Smuzhiyun error = bmap(inode, &block);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun if (block > INT_MAX) {
77*4882a593Smuzhiyun error = -ERANGE;
78*4882a593Smuzhiyun pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
79*4882a593Smuzhiyun current->comm, task_pid_nr(current),
80*4882a593Smuzhiyun sb->s_id, filp);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun if (error)
84*4882a593Smuzhiyun ur_block = 0;
85*4882a593Smuzhiyun else
86*4882a593Smuzhiyun ur_block = block;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (put_user(ur_block, p))
89*4882a593Smuzhiyun error = -EFAULT;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun return error;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /**
95*4882a593Smuzhiyun * fiemap_fill_next_extent - Fiemap helper function
96*4882a593Smuzhiyun * @fieinfo: Fiemap context passed into ->fiemap
97*4882a593Smuzhiyun * @logical: Extent logical start offset, in bytes
98*4882a593Smuzhiyun * @phys: Extent physical start offset, in bytes
99*4882a593Smuzhiyun * @len: Extent length, in bytes
100*4882a593Smuzhiyun * @flags: FIEMAP_EXTENT flags that describe this extent
101*4882a593Smuzhiyun *
102*4882a593Smuzhiyun * Called from file system ->fiemap callback. Will populate extent
103*4882a593Smuzhiyun * info as passed in via arguments and copy to user memory. On
104*4882a593Smuzhiyun * success, extent count on fieinfo is incremented.
105*4882a593Smuzhiyun *
106*4882a593Smuzhiyun * Returns 0 on success, -errno on error, 1 if this was the last
107*4882a593Smuzhiyun * extent that will fit in user array.
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun #define SET_UNKNOWN_FLAGS (FIEMAP_EXTENT_DELALLOC)
110*4882a593Smuzhiyun #define SET_NO_UNMOUNTED_IO_FLAGS (FIEMAP_EXTENT_DATA_ENCRYPTED)
111*4882a593Smuzhiyun #define SET_NOT_ALIGNED_FLAGS (FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
fiemap_fill_next_extent(struct fiemap_extent_info * fieinfo,u64 logical,u64 phys,u64 len,u32 flags)112*4882a593Smuzhiyun int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
113*4882a593Smuzhiyun u64 phys, u64 len, u32 flags)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun struct fiemap_extent extent;
116*4882a593Smuzhiyun struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* only count the extents */
119*4882a593Smuzhiyun if (fieinfo->fi_extents_max == 0) {
120*4882a593Smuzhiyun fieinfo->fi_extents_mapped++;
121*4882a593Smuzhiyun return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
125*4882a593Smuzhiyun return 1;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (flags & SET_UNKNOWN_FLAGS)
128*4882a593Smuzhiyun flags |= FIEMAP_EXTENT_UNKNOWN;
129*4882a593Smuzhiyun if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
130*4882a593Smuzhiyun flags |= FIEMAP_EXTENT_ENCODED;
131*4882a593Smuzhiyun if (flags & SET_NOT_ALIGNED_FLAGS)
132*4882a593Smuzhiyun flags |= FIEMAP_EXTENT_NOT_ALIGNED;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun memset(&extent, 0, sizeof(extent));
135*4882a593Smuzhiyun extent.fe_logical = logical;
136*4882a593Smuzhiyun extent.fe_physical = phys;
137*4882a593Smuzhiyun extent.fe_length = len;
138*4882a593Smuzhiyun extent.fe_flags = flags;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun dest += fieinfo->fi_extents_mapped;
141*4882a593Smuzhiyun if (copy_to_user(dest, &extent, sizeof(extent)))
142*4882a593Smuzhiyun return -EFAULT;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun fieinfo->fi_extents_mapped++;
145*4882a593Smuzhiyun if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
146*4882a593Smuzhiyun return 1;
147*4882a593Smuzhiyun return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun EXPORT_SYMBOL_NS(fiemap_fill_next_extent, ANDROID_GKI_VFS_EXPORT_ONLY);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /**
152*4882a593Smuzhiyun * fiemap_prep - check validity of requested flags for fiemap
153*4882a593Smuzhiyun * @inode: Inode to operate on
154*4882a593Smuzhiyun * @fieinfo: Fiemap context passed into ->fiemap
155*4882a593Smuzhiyun * @start: Start of the mapped range
156*4882a593Smuzhiyun * @len: Length of the mapped range, can be truncated by this function.
157*4882a593Smuzhiyun * @supported_flags: Set of fiemap flags that the file system understands
158*4882a593Smuzhiyun *
159*4882a593Smuzhiyun * This function must be called from each ->fiemap instance to validate the
160*4882a593Smuzhiyun * fiemap request against the file system parameters.
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * Returns 0 on success, or a negative error on failure.
163*4882a593Smuzhiyun */
fiemap_prep(struct inode * inode,struct fiemap_extent_info * fieinfo,u64 start,u64 * len,u32 supported_flags)164*4882a593Smuzhiyun int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
165*4882a593Smuzhiyun u64 start, u64 *len, u32 supported_flags)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun u64 maxbytes = inode->i_sb->s_maxbytes;
168*4882a593Smuzhiyun u32 incompat_flags;
169*4882a593Smuzhiyun int ret = 0;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (*len == 0)
172*4882a593Smuzhiyun return -EINVAL;
173*4882a593Smuzhiyun if (start >= maxbytes)
174*4882a593Smuzhiyun return -EFBIG;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /*
177*4882a593Smuzhiyun * Shrink request scope to what the fs can actually handle.
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun if (*len > maxbytes || (maxbytes - *len) < start)
180*4882a593Smuzhiyun *len = maxbytes - start;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun supported_flags |= FIEMAP_FLAG_SYNC;
183*4882a593Smuzhiyun supported_flags &= FIEMAP_FLAGS_COMPAT;
184*4882a593Smuzhiyun incompat_flags = fieinfo->fi_flags & ~supported_flags;
185*4882a593Smuzhiyun if (incompat_flags) {
186*4882a593Smuzhiyun fieinfo->fi_flags = incompat_flags;
187*4882a593Smuzhiyun return -EBADR;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
191*4882a593Smuzhiyun ret = filemap_write_and_wait(inode->i_mapping);
192*4882a593Smuzhiyun return ret;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun EXPORT_SYMBOL_NS(fiemap_prep, ANDROID_GKI_VFS_EXPORT_ONLY);
195*4882a593Smuzhiyun
ioctl_fiemap(struct file * filp,struct fiemap __user * ufiemap)196*4882a593Smuzhiyun static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct fiemap fiemap;
199*4882a593Smuzhiyun struct fiemap_extent_info fieinfo = { 0, };
200*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
201*4882a593Smuzhiyun int error;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (!inode->i_op->fiemap)
204*4882a593Smuzhiyun return -EOPNOTSUPP;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
207*4882a593Smuzhiyun return -EFAULT;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
210*4882a593Smuzhiyun return -EINVAL;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun fieinfo.fi_flags = fiemap.fm_flags;
213*4882a593Smuzhiyun fieinfo.fi_extents_max = fiemap.fm_extent_count;
214*4882a593Smuzhiyun fieinfo.fi_extents_start = ufiemap->fm_extents;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start,
217*4882a593Smuzhiyun fiemap.fm_length);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun fiemap.fm_flags = fieinfo.fi_flags;
220*4882a593Smuzhiyun fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
221*4882a593Smuzhiyun if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
222*4882a593Smuzhiyun error = -EFAULT;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun return error;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
ioctl_file_clone(struct file * dst_file,unsigned long srcfd,u64 off,u64 olen,u64 destoff)227*4882a593Smuzhiyun static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
228*4882a593Smuzhiyun u64 off, u64 olen, u64 destoff)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun struct fd src_file = fdget(srcfd);
231*4882a593Smuzhiyun loff_t cloned;
232*4882a593Smuzhiyun int ret;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (!src_file.file)
235*4882a593Smuzhiyun return -EBADF;
236*4882a593Smuzhiyun ret = -EXDEV;
237*4882a593Smuzhiyun if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
238*4882a593Smuzhiyun goto fdput;
239*4882a593Smuzhiyun cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
240*4882a593Smuzhiyun olen, 0);
241*4882a593Smuzhiyun if (cloned < 0)
242*4882a593Smuzhiyun ret = cloned;
243*4882a593Smuzhiyun else if (olen && cloned != olen)
244*4882a593Smuzhiyun ret = -EINVAL;
245*4882a593Smuzhiyun else
246*4882a593Smuzhiyun ret = 0;
247*4882a593Smuzhiyun fdput:
248*4882a593Smuzhiyun fdput(src_file);
249*4882a593Smuzhiyun return ret;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
ioctl_file_clone_range(struct file * file,struct file_clone_range __user * argp)252*4882a593Smuzhiyun static long ioctl_file_clone_range(struct file *file,
253*4882a593Smuzhiyun struct file_clone_range __user *argp)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun struct file_clone_range args;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun if (copy_from_user(&args, argp, sizeof(args)))
258*4882a593Smuzhiyun return -EFAULT;
259*4882a593Smuzhiyun return ioctl_file_clone(file, args.src_fd, args.src_offset,
260*4882a593Smuzhiyun args.src_length, args.dest_offset);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun #ifdef CONFIG_BLOCK
264*4882a593Smuzhiyun
logical_to_blk(struct inode * inode,loff_t offset)265*4882a593Smuzhiyun static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun return (offset >> inode->i_blkbits);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
blk_to_logical(struct inode * inode,sector_t blk)270*4882a593Smuzhiyun static inline loff_t blk_to_logical(struct inode *inode, sector_t blk)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun return (blk << inode->i_blkbits);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /**
276*4882a593Smuzhiyun * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
277*4882a593Smuzhiyun * @inode: the inode to map
278*4882a593Smuzhiyun * @fieinfo: the fiemap info struct that will be passed back to userspace
279*4882a593Smuzhiyun * @start: where to start mapping in the inode
280*4882a593Smuzhiyun * @len: how much space to map
281*4882a593Smuzhiyun * @get_block: the fs's get_block function
282*4882a593Smuzhiyun *
283*4882a593Smuzhiyun * This does FIEMAP for block based inodes. Basically it will just loop
284*4882a593Smuzhiyun * through get_block until we hit the number of extents we want to map, or we
285*4882a593Smuzhiyun * go past the end of the file and hit a hole.
286*4882a593Smuzhiyun *
287*4882a593Smuzhiyun * If it is possible to have data blocks beyond a hole past @inode->i_size, then
288*4882a593Smuzhiyun * please do not use this function, it will stop at the first unmapped block
289*4882a593Smuzhiyun * beyond i_size.
290*4882a593Smuzhiyun *
291*4882a593Smuzhiyun * If you use this function directly, you need to do your own locking. Use
292*4882a593Smuzhiyun * generic_block_fiemap if you want the locking done for you.
293*4882a593Smuzhiyun */
__generic_block_fiemap(struct inode * inode,struct fiemap_extent_info * fieinfo,loff_t start,loff_t len,get_block_t * get_block)294*4882a593Smuzhiyun static int __generic_block_fiemap(struct inode *inode,
295*4882a593Smuzhiyun struct fiemap_extent_info *fieinfo, loff_t start,
296*4882a593Smuzhiyun loff_t len, get_block_t *get_block)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun struct buffer_head map_bh;
299*4882a593Smuzhiyun sector_t start_blk, last_blk;
300*4882a593Smuzhiyun loff_t isize = i_size_read(inode);
301*4882a593Smuzhiyun u64 logical = 0, phys = 0, size = 0;
302*4882a593Smuzhiyun u32 flags = FIEMAP_EXTENT_MERGED;
303*4882a593Smuzhiyun bool past_eof = false, whole_file = false;
304*4882a593Smuzhiyun int ret = 0;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_SYNC);
307*4882a593Smuzhiyun if (ret)
308*4882a593Smuzhiyun return ret;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /*
311*4882a593Smuzhiyun * Either the i_mutex or other appropriate locking needs to be held
312*4882a593Smuzhiyun * since we expect isize to not change at all through the duration of
313*4882a593Smuzhiyun * this call.
314*4882a593Smuzhiyun */
315*4882a593Smuzhiyun if (len >= isize) {
316*4882a593Smuzhiyun whole_file = true;
317*4882a593Smuzhiyun len = isize;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /*
321*4882a593Smuzhiyun * Some filesystems can't deal with being asked to map less than
322*4882a593Smuzhiyun * blocksize, so make sure our len is at least block length.
323*4882a593Smuzhiyun */
324*4882a593Smuzhiyun if (logical_to_blk(inode, len) == 0)
325*4882a593Smuzhiyun len = blk_to_logical(inode, 1);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun start_blk = logical_to_blk(inode, start);
328*4882a593Smuzhiyun last_blk = logical_to_blk(inode, start + len - 1);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun do {
331*4882a593Smuzhiyun /*
332*4882a593Smuzhiyun * we set b_size to the total size we want so it will map as
333*4882a593Smuzhiyun * many contiguous blocks as possible at once
334*4882a593Smuzhiyun */
335*4882a593Smuzhiyun memset(&map_bh, 0, sizeof(struct buffer_head));
336*4882a593Smuzhiyun map_bh.b_size = len;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun ret = get_block(inode, start_blk, &map_bh, 0);
339*4882a593Smuzhiyun if (ret)
340*4882a593Smuzhiyun break;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* HOLE */
343*4882a593Smuzhiyun if (!buffer_mapped(&map_bh)) {
344*4882a593Smuzhiyun start_blk++;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /*
347*4882a593Smuzhiyun * We want to handle the case where there is an
348*4882a593Smuzhiyun * allocated block at the front of the file, and then
349*4882a593Smuzhiyun * nothing but holes up to the end of the file properly,
350*4882a593Smuzhiyun * to make sure that extent at the front gets properly
351*4882a593Smuzhiyun * marked with FIEMAP_EXTENT_LAST
352*4882a593Smuzhiyun */
353*4882a593Smuzhiyun if (!past_eof &&
354*4882a593Smuzhiyun blk_to_logical(inode, start_blk) >= isize)
355*4882a593Smuzhiyun past_eof = 1;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /*
358*4882a593Smuzhiyun * First hole after going past the EOF, this is our
359*4882a593Smuzhiyun * last extent
360*4882a593Smuzhiyun */
361*4882a593Smuzhiyun if (past_eof && size) {
362*4882a593Smuzhiyun flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
363*4882a593Smuzhiyun ret = fiemap_fill_next_extent(fieinfo, logical,
364*4882a593Smuzhiyun phys, size,
365*4882a593Smuzhiyun flags);
366*4882a593Smuzhiyun } else if (size) {
367*4882a593Smuzhiyun ret = fiemap_fill_next_extent(fieinfo, logical,
368*4882a593Smuzhiyun phys, size, flags);
369*4882a593Smuzhiyun size = 0;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* if we have holes up to/past EOF then we're done */
373*4882a593Smuzhiyun if (start_blk > last_blk || past_eof || ret)
374*4882a593Smuzhiyun break;
375*4882a593Smuzhiyun } else {
376*4882a593Smuzhiyun /*
377*4882a593Smuzhiyun * We have gone over the length of what we wanted to
378*4882a593Smuzhiyun * map, and it wasn't the entire file, so add the extent
379*4882a593Smuzhiyun * we got last time and exit.
380*4882a593Smuzhiyun *
381*4882a593Smuzhiyun * This is for the case where say we want to map all the
382*4882a593Smuzhiyun * way up to the second to the last block in a file, but
383*4882a593Smuzhiyun * the last block is a hole, making the second to last
384*4882a593Smuzhiyun * block FIEMAP_EXTENT_LAST. In this case we want to
385*4882a593Smuzhiyun * see if there is a hole after the second to last block
386*4882a593Smuzhiyun * so we can mark it properly. If we found data after
387*4882a593Smuzhiyun * we exceeded the length we were requesting, then we
388*4882a593Smuzhiyun * are good to go, just add the extent to the fieinfo
389*4882a593Smuzhiyun * and break
390*4882a593Smuzhiyun */
391*4882a593Smuzhiyun if (start_blk > last_blk && !whole_file) {
392*4882a593Smuzhiyun ret = fiemap_fill_next_extent(fieinfo, logical,
393*4882a593Smuzhiyun phys, size,
394*4882a593Smuzhiyun flags);
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun /*
399*4882a593Smuzhiyun * if size != 0 then we know we already have an extent
400*4882a593Smuzhiyun * to add, so add it.
401*4882a593Smuzhiyun */
402*4882a593Smuzhiyun if (size) {
403*4882a593Smuzhiyun ret = fiemap_fill_next_extent(fieinfo, logical,
404*4882a593Smuzhiyun phys, size,
405*4882a593Smuzhiyun flags);
406*4882a593Smuzhiyun if (ret)
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun logical = blk_to_logical(inode, start_blk);
411*4882a593Smuzhiyun phys = blk_to_logical(inode, map_bh.b_blocknr);
412*4882a593Smuzhiyun size = map_bh.b_size;
413*4882a593Smuzhiyun flags = FIEMAP_EXTENT_MERGED;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun start_blk += logical_to_blk(inode, size);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun * If we are past the EOF, then we need to make sure as
419*4882a593Smuzhiyun * soon as we find a hole that the last extent we found
420*4882a593Smuzhiyun * is marked with FIEMAP_EXTENT_LAST
421*4882a593Smuzhiyun */
422*4882a593Smuzhiyun if (!past_eof && logical + size >= isize)
423*4882a593Smuzhiyun past_eof = true;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun cond_resched();
426*4882a593Smuzhiyun if (fatal_signal_pending(current)) {
427*4882a593Smuzhiyun ret = -EINTR;
428*4882a593Smuzhiyun break;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun } while (1);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /* If ret is 1 then we just hit the end of the extent array */
434*4882a593Smuzhiyun if (ret == 1)
435*4882a593Smuzhiyun ret = 0;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun return ret;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /**
441*4882a593Smuzhiyun * generic_block_fiemap - FIEMAP for block based inodes
442*4882a593Smuzhiyun * @inode: The inode to map
443*4882a593Smuzhiyun * @fieinfo: The mapping information
444*4882a593Smuzhiyun * @start: The initial block to map
445*4882a593Smuzhiyun * @len: The length of the extect to attempt to map
446*4882a593Smuzhiyun * @get_block: The block mapping function for the fs
447*4882a593Smuzhiyun *
448*4882a593Smuzhiyun * Calls __generic_block_fiemap to map the inode, after taking
449*4882a593Smuzhiyun * the inode's mutex lock.
450*4882a593Smuzhiyun */
451*4882a593Smuzhiyun
generic_block_fiemap(struct inode * inode,struct fiemap_extent_info * fieinfo,u64 start,u64 len,get_block_t * get_block)452*4882a593Smuzhiyun int generic_block_fiemap(struct inode *inode,
453*4882a593Smuzhiyun struct fiemap_extent_info *fieinfo, u64 start,
454*4882a593Smuzhiyun u64 len, get_block_t *get_block)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun int ret;
457*4882a593Smuzhiyun inode_lock(inode);
458*4882a593Smuzhiyun ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
459*4882a593Smuzhiyun inode_unlock(inode);
460*4882a593Smuzhiyun return ret;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun EXPORT_SYMBOL(generic_block_fiemap);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun #endif /* CONFIG_BLOCK */
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /*
467*4882a593Smuzhiyun * This provides compatibility with legacy XFS pre-allocation ioctls
468*4882a593Smuzhiyun * which predate the fallocate syscall.
469*4882a593Smuzhiyun *
470*4882a593Smuzhiyun * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
471*4882a593Smuzhiyun * are used here, rest are ignored.
472*4882a593Smuzhiyun */
ioctl_preallocate(struct file * filp,int mode,void __user * argp)473*4882a593Smuzhiyun static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
476*4882a593Smuzhiyun struct space_resv sr;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun if (copy_from_user(&sr, argp, sizeof(sr)))
479*4882a593Smuzhiyun return -EFAULT;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun switch (sr.l_whence) {
482*4882a593Smuzhiyun case SEEK_SET:
483*4882a593Smuzhiyun break;
484*4882a593Smuzhiyun case SEEK_CUR:
485*4882a593Smuzhiyun sr.l_start += filp->f_pos;
486*4882a593Smuzhiyun break;
487*4882a593Smuzhiyun case SEEK_END:
488*4882a593Smuzhiyun sr.l_start += i_size_read(inode);
489*4882a593Smuzhiyun break;
490*4882a593Smuzhiyun default:
491*4882a593Smuzhiyun return -EINVAL;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
495*4882a593Smuzhiyun sr.l_len);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /* on ia32 l_start is on a 32-bit boundary */
499*4882a593Smuzhiyun #if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
500*4882a593Smuzhiyun /* just account for different alignment */
compat_ioctl_preallocate(struct file * file,int mode,struct space_resv_32 __user * argp)501*4882a593Smuzhiyun static int compat_ioctl_preallocate(struct file *file, int mode,
502*4882a593Smuzhiyun struct space_resv_32 __user *argp)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun struct inode *inode = file_inode(file);
505*4882a593Smuzhiyun struct space_resv_32 sr;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun if (copy_from_user(&sr, argp, sizeof(sr)))
508*4882a593Smuzhiyun return -EFAULT;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun switch (sr.l_whence) {
511*4882a593Smuzhiyun case SEEK_SET:
512*4882a593Smuzhiyun break;
513*4882a593Smuzhiyun case SEEK_CUR:
514*4882a593Smuzhiyun sr.l_start += file->f_pos;
515*4882a593Smuzhiyun break;
516*4882a593Smuzhiyun case SEEK_END:
517*4882a593Smuzhiyun sr.l_start += i_size_read(inode);
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun default:
520*4882a593Smuzhiyun return -EINVAL;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun #endif
526*4882a593Smuzhiyun
file_ioctl(struct file * filp,unsigned int cmd,int __user * p)527*4882a593Smuzhiyun static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun switch (cmd) {
530*4882a593Smuzhiyun case FIBMAP:
531*4882a593Smuzhiyun return ioctl_fibmap(filp, p);
532*4882a593Smuzhiyun case FS_IOC_RESVSP:
533*4882a593Smuzhiyun case FS_IOC_RESVSP64:
534*4882a593Smuzhiyun return ioctl_preallocate(filp, 0, p);
535*4882a593Smuzhiyun case FS_IOC_UNRESVSP:
536*4882a593Smuzhiyun case FS_IOC_UNRESVSP64:
537*4882a593Smuzhiyun return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
538*4882a593Smuzhiyun case FS_IOC_ZERO_RANGE:
539*4882a593Smuzhiyun return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun return -ENOIOCTLCMD;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
ioctl_fionbio(struct file * filp,int __user * argp)545*4882a593Smuzhiyun static int ioctl_fionbio(struct file *filp, int __user *argp)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun unsigned int flag;
548*4882a593Smuzhiyun int on, error;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun error = get_user(on, argp);
551*4882a593Smuzhiyun if (error)
552*4882a593Smuzhiyun return error;
553*4882a593Smuzhiyun flag = O_NONBLOCK;
554*4882a593Smuzhiyun #ifdef __sparc__
555*4882a593Smuzhiyun /* SunOS compatibility item. */
556*4882a593Smuzhiyun if (O_NONBLOCK != O_NDELAY)
557*4882a593Smuzhiyun flag |= O_NDELAY;
558*4882a593Smuzhiyun #endif
559*4882a593Smuzhiyun spin_lock(&filp->f_lock);
560*4882a593Smuzhiyun if (on)
561*4882a593Smuzhiyun filp->f_flags |= flag;
562*4882a593Smuzhiyun else
563*4882a593Smuzhiyun filp->f_flags &= ~flag;
564*4882a593Smuzhiyun spin_unlock(&filp->f_lock);
565*4882a593Smuzhiyun return error;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
ioctl_fioasync(unsigned int fd,struct file * filp,int __user * argp)568*4882a593Smuzhiyun static int ioctl_fioasync(unsigned int fd, struct file *filp,
569*4882a593Smuzhiyun int __user *argp)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun unsigned int flag;
572*4882a593Smuzhiyun int on, error;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun error = get_user(on, argp);
575*4882a593Smuzhiyun if (error)
576*4882a593Smuzhiyun return error;
577*4882a593Smuzhiyun flag = on ? FASYNC : 0;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* Did FASYNC state change ? */
580*4882a593Smuzhiyun if ((flag ^ filp->f_flags) & FASYNC) {
581*4882a593Smuzhiyun if (filp->f_op->fasync)
582*4882a593Smuzhiyun /* fasync() adjusts filp->f_flags */
583*4882a593Smuzhiyun error = filp->f_op->fasync(fd, filp, on);
584*4882a593Smuzhiyun else
585*4882a593Smuzhiyun error = -ENOTTY;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun return error < 0 ? error : 0;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
ioctl_fsfreeze(struct file * filp)590*4882a593Smuzhiyun static int ioctl_fsfreeze(struct file *filp)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun struct super_block *sb = file_inode(filp)->i_sb;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
595*4882a593Smuzhiyun return -EPERM;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun /* If filesystem doesn't support freeze feature, return. */
598*4882a593Smuzhiyun if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
599*4882a593Smuzhiyun return -EOPNOTSUPP;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /* Freeze */
602*4882a593Smuzhiyun if (sb->s_op->freeze_super)
603*4882a593Smuzhiyun return sb->s_op->freeze_super(sb);
604*4882a593Smuzhiyun return freeze_super(sb);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
ioctl_fsthaw(struct file * filp)607*4882a593Smuzhiyun static int ioctl_fsthaw(struct file *filp)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun struct super_block *sb = file_inode(filp)->i_sb;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
612*4882a593Smuzhiyun return -EPERM;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun /* Thaw */
615*4882a593Smuzhiyun if (sb->s_op->thaw_super)
616*4882a593Smuzhiyun return sb->s_op->thaw_super(sb);
617*4882a593Smuzhiyun return thaw_super(sb);
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
ioctl_file_dedupe_range(struct file * file,struct file_dedupe_range __user * argp)620*4882a593Smuzhiyun static int ioctl_file_dedupe_range(struct file *file,
621*4882a593Smuzhiyun struct file_dedupe_range __user *argp)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun struct file_dedupe_range *same = NULL;
624*4882a593Smuzhiyun int ret;
625*4882a593Smuzhiyun unsigned long size;
626*4882a593Smuzhiyun u16 count;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (get_user(count, &argp->dest_count)) {
629*4882a593Smuzhiyun ret = -EFAULT;
630*4882a593Smuzhiyun goto out;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun size = offsetof(struct file_dedupe_range __user, info[count]);
634*4882a593Smuzhiyun if (size > PAGE_SIZE) {
635*4882a593Smuzhiyun ret = -ENOMEM;
636*4882a593Smuzhiyun goto out;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun same = memdup_user(argp, size);
640*4882a593Smuzhiyun if (IS_ERR(same)) {
641*4882a593Smuzhiyun ret = PTR_ERR(same);
642*4882a593Smuzhiyun same = NULL;
643*4882a593Smuzhiyun goto out;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun same->dest_count = count;
647*4882a593Smuzhiyun ret = vfs_dedupe_file_range(file, same);
648*4882a593Smuzhiyun if (ret)
649*4882a593Smuzhiyun goto out;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun ret = copy_to_user(argp, same, size);
652*4882a593Smuzhiyun if (ret)
653*4882a593Smuzhiyun ret = -EFAULT;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun out:
656*4882a593Smuzhiyun kfree(same);
657*4882a593Smuzhiyun return ret;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun /*
661*4882a593Smuzhiyun * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
662*4882a593Smuzhiyun * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
663*4882a593Smuzhiyun *
664*4882a593Smuzhiyun * When you add any new common ioctls to the switches above and below,
665*4882a593Smuzhiyun * please ensure they have compatible arguments in compat mode.
666*4882a593Smuzhiyun */
do_vfs_ioctl(struct file * filp,unsigned int fd,unsigned int cmd,unsigned long arg)667*4882a593Smuzhiyun static int do_vfs_ioctl(struct file *filp, unsigned int fd,
668*4882a593Smuzhiyun unsigned int cmd, unsigned long arg)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun void __user *argp = (void __user *)arg;
671*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun switch (cmd) {
674*4882a593Smuzhiyun case FIOCLEX:
675*4882a593Smuzhiyun set_close_on_exec(fd, 1);
676*4882a593Smuzhiyun return 0;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun case FIONCLEX:
679*4882a593Smuzhiyun set_close_on_exec(fd, 0);
680*4882a593Smuzhiyun return 0;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun case FIONBIO:
683*4882a593Smuzhiyun return ioctl_fionbio(filp, argp);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun case FIOASYNC:
686*4882a593Smuzhiyun return ioctl_fioasync(fd, filp, argp);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun case FIOQSIZE:
689*4882a593Smuzhiyun if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
690*4882a593Smuzhiyun S_ISLNK(inode->i_mode)) {
691*4882a593Smuzhiyun loff_t res = inode_get_bytes(inode);
692*4882a593Smuzhiyun return copy_to_user(argp, &res, sizeof(res)) ?
693*4882a593Smuzhiyun -EFAULT : 0;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun return -ENOTTY;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun case FIFREEZE:
699*4882a593Smuzhiyun return ioctl_fsfreeze(filp);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun case FITHAW:
702*4882a593Smuzhiyun return ioctl_fsthaw(filp);
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun case FS_IOC_FIEMAP:
705*4882a593Smuzhiyun return ioctl_fiemap(filp, argp);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun case FIGETBSZ:
708*4882a593Smuzhiyun /* anon_bdev filesystems may not have a block size */
709*4882a593Smuzhiyun if (!inode->i_sb->s_blocksize)
710*4882a593Smuzhiyun return -EINVAL;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun return put_user(inode->i_sb->s_blocksize, (int __user *)argp);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun case FICLONE:
715*4882a593Smuzhiyun return ioctl_file_clone(filp, arg, 0, 0, 0);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun case FICLONERANGE:
718*4882a593Smuzhiyun return ioctl_file_clone_range(filp, argp);
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun case FIDEDUPERANGE:
721*4882a593Smuzhiyun return ioctl_file_dedupe_range(filp, argp);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun case FIONREAD:
724*4882a593Smuzhiyun if (!S_ISREG(inode->i_mode))
725*4882a593Smuzhiyun return vfs_ioctl(filp, cmd, arg);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun return put_user(i_size_read(inode) - filp->f_pos,
728*4882a593Smuzhiyun (int __user *)argp);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun default:
731*4882a593Smuzhiyun if (S_ISREG(inode->i_mode))
732*4882a593Smuzhiyun return file_ioctl(filp, cmd, argp);
733*4882a593Smuzhiyun break;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun return -ENOIOCTLCMD;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,unsigned long,arg)739*4882a593Smuzhiyun SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun struct fd f = fdget(fd);
742*4882a593Smuzhiyun int error;
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun if (!f.file)
745*4882a593Smuzhiyun return -EBADF;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun error = security_file_ioctl(f.file, cmd, arg);
748*4882a593Smuzhiyun if (error)
749*4882a593Smuzhiyun goto out;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun error = do_vfs_ioctl(f.file, fd, cmd, arg);
752*4882a593Smuzhiyun if (error == -ENOIOCTLCMD)
753*4882a593Smuzhiyun error = vfs_ioctl(f.file, cmd, arg);
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun out:
756*4882a593Smuzhiyun fdput(f);
757*4882a593Smuzhiyun return error;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
761*4882a593Smuzhiyun /**
762*4882a593Smuzhiyun * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
763*4882a593Smuzhiyun *
764*4882a593Smuzhiyun * This is not normally called as a function, but instead set in struct
765*4882a593Smuzhiyun * file_operations as
766*4882a593Smuzhiyun *
767*4882a593Smuzhiyun * .compat_ioctl = compat_ptr_ioctl,
768*4882a593Smuzhiyun *
769*4882a593Smuzhiyun * On most architectures, the compat_ptr_ioctl() just passes all arguments
770*4882a593Smuzhiyun * to the corresponding ->ioctl handler. The exception is arch/s390, where
771*4882a593Smuzhiyun * compat_ptr() clears the top bit of a 32-bit pointer value, so user space
772*4882a593Smuzhiyun * pointers to the second 2GB alias the first 2GB, as is the case for
773*4882a593Smuzhiyun * native 32-bit s390 user space.
774*4882a593Smuzhiyun *
775*4882a593Smuzhiyun * The compat_ptr_ioctl() function must therefore be used only with ioctl
776*4882a593Smuzhiyun * functions that either ignore the argument or pass a pointer to a
777*4882a593Smuzhiyun * compatible data type.
778*4882a593Smuzhiyun *
779*4882a593Smuzhiyun * If any ioctl command handled by fops->unlocked_ioctl passes a plain
780*4882a593Smuzhiyun * integer instead of a pointer, or any of the passed data types
781*4882a593Smuzhiyun * is incompatible between 32-bit and 64-bit architectures, a proper
782*4882a593Smuzhiyun * handler is required instead of compat_ptr_ioctl.
783*4882a593Smuzhiyun */
compat_ptr_ioctl(struct file * file,unsigned int cmd,unsigned long arg)784*4882a593Smuzhiyun long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun if (!file->f_op->unlocked_ioctl)
787*4882a593Smuzhiyun return -ENOIOCTLCMD;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun EXPORT_SYMBOL(compat_ptr_ioctl);
792*4882a593Smuzhiyun
COMPAT_SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,compat_ulong_t,arg)793*4882a593Smuzhiyun COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
794*4882a593Smuzhiyun compat_ulong_t, arg)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun struct fd f = fdget(fd);
797*4882a593Smuzhiyun int error;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (!f.file)
800*4882a593Smuzhiyun return -EBADF;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun /* RED-PEN how should LSM module know it's handling 32bit? */
803*4882a593Smuzhiyun error = security_file_ioctl(f.file, cmd, arg);
804*4882a593Smuzhiyun if (error)
805*4882a593Smuzhiyun goto out;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun switch (cmd) {
808*4882a593Smuzhiyun /* FICLONE takes an int argument, so don't use compat_ptr() */
809*4882a593Smuzhiyun case FICLONE:
810*4882a593Smuzhiyun error = ioctl_file_clone(f.file, arg, 0, 0, 0);
811*4882a593Smuzhiyun break;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun #if defined(CONFIG_X86_64)
814*4882a593Smuzhiyun /* these get messy on amd64 due to alignment differences */
815*4882a593Smuzhiyun case FS_IOC_RESVSP_32:
816*4882a593Smuzhiyun case FS_IOC_RESVSP64_32:
817*4882a593Smuzhiyun error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
818*4882a593Smuzhiyun break;
819*4882a593Smuzhiyun case FS_IOC_UNRESVSP_32:
820*4882a593Smuzhiyun case FS_IOC_UNRESVSP64_32:
821*4882a593Smuzhiyun error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
822*4882a593Smuzhiyun compat_ptr(arg));
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun case FS_IOC_ZERO_RANGE_32:
825*4882a593Smuzhiyun error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
826*4882a593Smuzhiyun compat_ptr(arg));
827*4882a593Smuzhiyun break;
828*4882a593Smuzhiyun #endif
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun /*
831*4882a593Smuzhiyun * everything else in do_vfs_ioctl() takes either a compatible
832*4882a593Smuzhiyun * pointer argument or no argument -- call it with a modified
833*4882a593Smuzhiyun * argument.
834*4882a593Smuzhiyun */
835*4882a593Smuzhiyun default:
836*4882a593Smuzhiyun error = do_vfs_ioctl(f.file, fd, cmd,
837*4882a593Smuzhiyun (unsigned long)compat_ptr(arg));
838*4882a593Smuzhiyun if (error != -ENOIOCTLCMD)
839*4882a593Smuzhiyun break;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun if (f.file->f_op->compat_ioctl)
842*4882a593Smuzhiyun error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
843*4882a593Smuzhiyun if (error == -ENOIOCTLCMD)
844*4882a593Smuzhiyun error = -ENOTTY;
845*4882a593Smuzhiyun break;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun out:
849*4882a593Smuzhiyun fdput(f);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun return error;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun #endif
854