1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * linux/fs/ioctl.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
7
8 #include <linux/syscalls.h>
9 #include <linux/mm.h>
10 #include <linux/capability.h>
11 #include <linux/compat.h>
12 #include <linux/file.h>
13 #include <linux/fs.h>
14 #include <linux/security.h>
15 #include <linux/export.h>
16 #include <linux/uaccess.h>
17 #include <linux/writeback.h>
18 #include <linux/buffer_head.h>
19 #include <linux/falloc.h>
20 #include <linux/sched/signal.h>
21 #include <linux/fiemap.h>
22 #include <linux/mount.h>
23 #include <linux/fscrypt.h>
24 #include <linux/fileattr.h>
25
26 #include "internal.h"
27
28 #include <asm/ioctls.h>
29
30 /* So that the fiemap access checks can't overflow on 32 bit machines. */
31 #define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
32
33 /**
34 * vfs_ioctl - call filesystem specific ioctl methods
35 * @filp: open file to invoke ioctl method on
36 * @cmd: ioctl command to execute
37 * @arg: command-specific argument for ioctl
38 *
39 * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
40 * returns -ENOTTY.
41 *
42 * Returns 0 on success, -errno on error.
43 */
vfs_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)44 static int vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
45 {
46 int error = -ENOTTY;
47
48 if (!filp->f_op->unlocked_ioctl)
49 goto out;
50
51 error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
52 if (error == -ENOIOCTLCMD)
53 error = -ENOTTY;
54 out:
55 return error;
56 }
57
ioctl_fibmap(struct file * filp,int __user * p)58 static int ioctl_fibmap(struct file *filp, int __user *p)
59 {
60 struct inode *inode = file_inode(filp);
61 struct super_block *sb = inode->i_sb;
62 int error, ur_block;
63 sector_t block;
64
65 if (!capable(CAP_SYS_RAWIO))
66 return -EPERM;
67
68 error = get_user(ur_block, p);
69 if (error)
70 return error;
71
72 if (ur_block < 0)
73 return -EINVAL;
74
75 block = ur_block;
76 error = bmap(inode, &block);
77
78 if (block > INT_MAX) {
79 error = -ERANGE;
80 pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
81 current->comm, task_pid_nr(current),
82 sb->s_id, filp);
83 }
84
85 if (error)
86 ur_block = 0;
87 else
88 ur_block = block;
89
90 if (put_user(ur_block, p))
91 error = -EFAULT;
92
93 return error;
94 }
95
96 /**
97 * fiemap_fill_next_extent - Fiemap helper function
98 * @fieinfo: Fiemap context passed into ->fiemap
99 * @logical: Extent logical start offset, in bytes
100 * @phys: Extent physical start offset, in bytes
101 * @len: Extent length, in bytes
102 * @flags: FIEMAP_EXTENT flags that describe this extent
103 *
104 * Called from file system ->fiemap callback. Will populate extent
105 * info as passed in via arguments and copy to user memory. On
106 * success, extent count on fieinfo is incremented.
107 *
108 * Returns 0 on success, -errno on error, 1 if this was the last
109 * extent that will fit in user array.
110 */
fiemap_fill_next_extent(struct fiemap_extent_info * fieinfo,u64 logical,u64 phys,u64 len,u32 flags)111 int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
112 u64 phys, u64 len, u32 flags)
113 {
114 struct fiemap_extent extent;
115 struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
116
117 /* only count the extents */
118 if (fieinfo->fi_extents_max == 0) {
119 fieinfo->fi_extents_mapped++;
120 return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
121 }
122
123 if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
124 return 1;
125
126 #define SET_UNKNOWN_FLAGS (FIEMAP_EXTENT_DELALLOC)
127 #define SET_NO_UNMOUNTED_IO_FLAGS (FIEMAP_EXTENT_DATA_ENCRYPTED)
128 #define SET_NOT_ALIGNED_FLAGS (FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
129
130 if (flags & SET_UNKNOWN_FLAGS)
131 flags |= FIEMAP_EXTENT_UNKNOWN;
132 if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
133 flags |= FIEMAP_EXTENT_ENCODED;
134 if (flags & SET_NOT_ALIGNED_FLAGS)
135 flags |= FIEMAP_EXTENT_NOT_ALIGNED;
136
137 memset(&extent, 0, sizeof(extent));
138 extent.fe_logical = logical;
139 extent.fe_physical = phys;
140 extent.fe_length = len;
141 extent.fe_flags = flags;
142
143 dest += fieinfo->fi_extents_mapped;
144 if (copy_to_user(dest, &extent, sizeof(extent)))
145 return -EFAULT;
146
147 fieinfo->fi_extents_mapped++;
148 if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
149 return 1;
150 return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
151 }
152 EXPORT_SYMBOL(fiemap_fill_next_extent);
153
154 /**
155 * fiemap_prep - check validity of requested flags for fiemap
156 * @inode: Inode to operate on
157 * @fieinfo: Fiemap context passed into ->fiemap
158 * @start: Start of the mapped range
159 * @len: Length of the mapped range, can be truncated by this function.
160 * @supported_flags: Set of fiemap flags that the file system understands
161 *
162 * This function must be called from each ->fiemap instance to validate the
163 * fiemap request against the file system parameters.
164 *
165 * Returns 0 on success, or a negative error on failure.
166 */
fiemap_prep(struct inode * inode,struct fiemap_extent_info * fieinfo,u64 start,u64 * len,u32 supported_flags)167 int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
168 u64 start, u64 *len, u32 supported_flags)
169 {
170 u64 maxbytes = inode->i_sb->s_maxbytes;
171 u32 incompat_flags;
172 int ret = 0;
173
174 if (*len == 0)
175 return -EINVAL;
176 if (start >= maxbytes)
177 return -EFBIG;
178
179 /*
180 * Shrink request scope to what the fs can actually handle.
181 */
182 if (*len > maxbytes || (maxbytes - *len) < start)
183 *len = maxbytes - start;
184
185 supported_flags |= FIEMAP_FLAG_SYNC;
186 supported_flags &= FIEMAP_FLAGS_COMPAT;
187 incompat_flags = fieinfo->fi_flags & ~supported_flags;
188 if (incompat_flags) {
189 fieinfo->fi_flags = incompat_flags;
190 return -EBADR;
191 }
192
193 if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
194 ret = filemap_write_and_wait(inode->i_mapping);
195 return ret;
196 }
197 EXPORT_SYMBOL(fiemap_prep);
198
ioctl_fiemap(struct file * filp,struct fiemap __user * ufiemap)199 static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
200 {
201 struct fiemap fiemap;
202 struct fiemap_extent_info fieinfo = { 0, };
203 struct inode *inode = file_inode(filp);
204 int error;
205
206 if (!inode->i_op->fiemap)
207 return -EOPNOTSUPP;
208
209 if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
210 return -EFAULT;
211
212 if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
213 return -EINVAL;
214
215 fieinfo.fi_flags = fiemap.fm_flags;
216 fieinfo.fi_extents_max = fiemap.fm_extent_count;
217 fieinfo.fi_extents_start = ufiemap->fm_extents;
218
219 error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start,
220 fiemap.fm_length);
221
222 fiemap.fm_flags = fieinfo.fi_flags;
223 fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
224 if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
225 error = -EFAULT;
226
227 return error;
228 }
229
ioctl_file_clone(struct file * dst_file,unsigned long srcfd,u64 off,u64 olen,u64 destoff)230 static int ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
231 u64 off, u64 olen, u64 destoff)
232 {
233 CLASS(fd, src_file)(srcfd);
234 loff_t cloned;
235 int ret;
236
237 if (fd_empty(src_file))
238 return -EBADF;
239 cloned = vfs_clone_file_range(fd_file(src_file), off, dst_file, destoff,
240 olen, 0);
241 if (cloned < 0)
242 ret = cloned;
243 else if (olen && cloned != olen)
244 ret = -EINVAL;
245 else
246 ret = 0;
247 return ret;
248 }
249
ioctl_file_clone_range(struct file * file,struct file_clone_range __user * argp)250 static int ioctl_file_clone_range(struct file *file,
251 struct file_clone_range __user *argp)
252 {
253 struct file_clone_range args;
254
255 if (copy_from_user(&args, argp, sizeof(args)))
256 return -EFAULT;
257 return ioctl_file_clone(file, args.src_fd, args.src_offset,
258 args.src_length, args.dest_offset);
259 }
260
261 /*
262 * This provides compatibility with legacy XFS pre-allocation ioctls
263 * which predate the fallocate syscall.
264 *
265 * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
266 * are used here, rest are ignored.
267 */
ioctl_preallocate(struct file * filp,int mode,void __user * argp)268 static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
269 {
270 struct inode *inode = file_inode(filp);
271 struct space_resv sr;
272
273 if (copy_from_user(&sr, argp, sizeof(sr)))
274 return -EFAULT;
275
276 switch (sr.l_whence) {
277 case SEEK_SET:
278 break;
279 case SEEK_CUR:
280 sr.l_start += filp->f_pos;
281 break;
282 case SEEK_END:
283 sr.l_start += i_size_read(inode);
284 break;
285 default:
286 return -EINVAL;
287 }
288
289 return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
290 sr.l_len);
291 }
292
293 /* on ia32 l_start is on a 32-bit boundary */
294 #if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
295 /* just account for different alignment */
compat_ioctl_preallocate(struct file * file,int mode,struct space_resv_32 __user * argp)296 static int compat_ioctl_preallocate(struct file *file, int mode,
297 struct space_resv_32 __user *argp)
298 {
299 struct inode *inode = file_inode(file);
300 struct space_resv_32 sr;
301
302 if (copy_from_user(&sr, argp, sizeof(sr)))
303 return -EFAULT;
304
305 switch (sr.l_whence) {
306 case SEEK_SET:
307 break;
308 case SEEK_CUR:
309 sr.l_start += file->f_pos;
310 break;
311 case SEEK_END:
312 sr.l_start += i_size_read(inode);
313 break;
314 default:
315 return -EINVAL;
316 }
317
318 return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
319 }
320 #endif
321
file_ioctl(struct file * filp,unsigned int cmd,int __user * p)322 static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
323 {
324 switch (cmd) {
325 case FIBMAP:
326 return ioctl_fibmap(filp, p);
327 case FS_IOC_RESVSP:
328 case FS_IOC_RESVSP64:
329 return ioctl_preallocate(filp, 0, p);
330 case FS_IOC_UNRESVSP:
331 case FS_IOC_UNRESVSP64:
332 return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
333 case FS_IOC_ZERO_RANGE:
334 return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
335 }
336
337 return -ENOIOCTLCMD;
338 }
339
ioctl_fionbio(struct file * filp,int __user * argp)340 static int ioctl_fionbio(struct file *filp, int __user *argp)
341 {
342 unsigned int flag;
343 int on, error;
344
345 error = get_user(on, argp);
346 if (error)
347 return error;
348 flag = O_NONBLOCK;
349 #ifdef __sparc__
350 /* SunOS compatibility item. */
351 if (O_NONBLOCK != O_NDELAY)
352 flag |= O_NDELAY;
353 #endif
354 spin_lock(&filp->f_lock);
355 if (on)
356 filp->f_flags |= flag;
357 else
358 filp->f_flags &= ~flag;
359 spin_unlock(&filp->f_lock);
360 return error;
361 }
362
ioctl_fioasync(unsigned int fd,struct file * filp,int __user * argp)363 static int ioctl_fioasync(unsigned int fd, struct file *filp,
364 int __user *argp)
365 {
366 unsigned int flag;
367 int on, error;
368
369 error = get_user(on, argp);
370 if (error)
371 return error;
372 flag = on ? FASYNC : 0;
373
374 /* Did FASYNC state change ? */
375 if ((flag ^ filp->f_flags) & FASYNC) {
376 if (filp->f_op->fasync)
377 /* fasync() adjusts filp->f_flags */
378 error = filp->f_op->fasync(fd, filp, on);
379 else
380 error = -ENOTTY;
381 }
382 return error < 0 ? error : 0;
383 }
384
ioctl_fsfreeze(struct file * filp)385 static int ioctl_fsfreeze(struct file *filp)
386 {
387 struct super_block *sb = file_inode(filp)->i_sb;
388
389 if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
390 return -EPERM;
391
392 /* If filesystem doesn't support freeze feature, return. */
393 if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
394 return -EOPNOTSUPP;
395
396 /* Freeze */
397 if (sb->s_op->freeze_super)
398 return sb->s_op->freeze_super(sb, FREEZE_HOLDER_USERSPACE, NULL);
399 return freeze_super(sb, FREEZE_HOLDER_USERSPACE, NULL);
400 }
401
ioctl_fsthaw(struct file * filp)402 static int ioctl_fsthaw(struct file *filp)
403 {
404 struct super_block *sb = file_inode(filp)->i_sb;
405
406 if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
407 return -EPERM;
408
409 /* Thaw */
410 if (sb->s_op->thaw_super)
411 return sb->s_op->thaw_super(sb, FREEZE_HOLDER_USERSPACE, NULL);
412 return thaw_super(sb, FREEZE_HOLDER_USERSPACE, NULL);
413 }
414
ioctl_file_dedupe_range(struct file * file,struct file_dedupe_range __user * argp)415 static int ioctl_file_dedupe_range(struct file *file,
416 struct file_dedupe_range __user *argp)
417 {
418 struct file_dedupe_range *same = NULL;
419 int ret;
420 unsigned long size;
421 u16 count;
422
423 if (get_user(count, &argp->dest_count)) {
424 ret = -EFAULT;
425 goto out;
426 }
427
428 size = struct_size(same, info, count);
429 if (size > PAGE_SIZE) {
430 ret = -ENOMEM;
431 goto out;
432 }
433
434 same = memdup_user(argp, size);
435 if (IS_ERR(same)) {
436 ret = PTR_ERR(same);
437 same = NULL;
438 goto out;
439 }
440
441 same->dest_count = count;
442 ret = vfs_dedupe_file_range(file, same);
443 if (ret)
444 goto out;
445
446 ret = copy_to_user(argp, same, size);
447 if (ret)
448 ret = -EFAULT;
449
450 out:
451 kfree(same);
452 return ret;
453 }
454
ioctl_getfsuuid(struct file * file,void __user * argp)455 static int ioctl_getfsuuid(struct file *file, void __user *argp)
456 {
457 struct super_block *sb = file_inode(file)->i_sb;
458 struct fsuuid2 u = { .len = sb->s_uuid_len, };
459
460 if (!sb->s_uuid_len)
461 return -ENOTTY;
462
463 memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
464
465 return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
466 }
467
ioctl_get_fs_sysfs_path(struct file * file,void __user * argp)468 static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
469 {
470 struct super_block *sb = file_inode(file)->i_sb;
471
472 if (!strlen(sb->s_sysfs_name))
473 return -ENOTTY;
474
475 struct fs_sysfs_path u = {};
476
477 u.len = scnprintf(u.name, sizeof(u.name), "%s/%s", sb->s_type->name, sb->s_sysfs_name);
478
479 return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
480 }
481
482 /*
483 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
484 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
485 *
486 * When you add any new common ioctls to the switches above and below,
487 * please ensure they have compatible arguments in compat mode.
488 *
489 * The LSM mailing list should also be notified of any command additions or
490 * changes, as specific LSMs may be affected.
491 */
do_vfs_ioctl(struct file * filp,unsigned int fd,unsigned int cmd,unsigned long arg)492 static int do_vfs_ioctl(struct file *filp, unsigned int fd,
493 unsigned int cmd, unsigned long arg)
494 {
495 void __user *argp = (void __user *)arg;
496 struct inode *inode = file_inode(filp);
497
498 switch (cmd) {
499 case FIOCLEX:
500 set_close_on_exec(fd, 1);
501 return 0;
502
503 case FIONCLEX:
504 set_close_on_exec(fd, 0);
505 return 0;
506
507 case FIONBIO:
508 return ioctl_fionbio(filp, argp);
509
510 case FIOASYNC:
511 return ioctl_fioasync(fd, filp, argp);
512
513 case FIOQSIZE:
514 if (S_ISDIR(inode->i_mode) ||
515 (S_ISREG(inode->i_mode) && !IS_ANON_FILE(inode)) ||
516 S_ISLNK(inode->i_mode)) {
517 loff_t res = inode_get_bytes(inode);
518 return copy_to_user(argp, &res, sizeof(res)) ?
519 -EFAULT : 0;
520 }
521
522 return -ENOTTY;
523
524 case FIFREEZE:
525 return ioctl_fsfreeze(filp);
526
527 case FITHAW:
528 return ioctl_fsthaw(filp);
529
530 case FS_IOC_FIEMAP:
531 return ioctl_fiemap(filp, argp);
532
533 case FIGETBSZ:
534 /* anon_bdev filesystems may not have a block size */
535 if (!inode->i_sb->s_blocksize)
536 return -EINVAL;
537
538 return put_user(inode->i_sb->s_blocksize, (int __user *)argp);
539
540 case FICLONE:
541 return ioctl_file_clone(filp, arg, 0, 0, 0);
542
543 case FICLONERANGE:
544 return ioctl_file_clone_range(filp, argp);
545
546 case FIDEDUPERANGE:
547 return ioctl_file_dedupe_range(filp, argp);
548
549 case FIONREAD:
550 if (!S_ISREG(inode->i_mode) || IS_ANON_FILE(inode))
551 return vfs_ioctl(filp, cmd, arg);
552
553 return put_user(i_size_read(inode) - filp->f_pos,
554 (int __user *)argp);
555
556 case FS_IOC_GETFLAGS:
557 return ioctl_getflags(filp, argp);
558
559 case FS_IOC_SETFLAGS:
560 return ioctl_setflags(filp, argp);
561
562 case FS_IOC_FSGETXATTR:
563 return ioctl_fsgetxattr(filp, argp);
564
565 case FS_IOC_FSSETXATTR:
566 return ioctl_fssetxattr(filp, argp);
567
568 case FS_IOC_GETFSUUID:
569 return ioctl_getfsuuid(filp, argp);
570
571 case FS_IOC_GETFSSYSFSPATH:
572 return ioctl_get_fs_sysfs_path(filp, argp);
573
574 default:
575 if (S_ISREG(inode->i_mode) && !IS_ANON_FILE(inode))
576 return file_ioctl(filp, cmd, argp);
577 break;
578 }
579
580 return -ENOIOCTLCMD;
581 }
582
SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,unsigned long,arg)583 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
584 {
585 CLASS(fd, f)(fd);
586 int error;
587
588 if (fd_empty(f))
589 return -EBADF;
590
591 error = security_file_ioctl(fd_file(f), cmd, arg);
592 if (error)
593 return error;
594
595 error = do_vfs_ioctl(fd_file(f), fd, cmd, arg);
596 if (error == -ENOIOCTLCMD)
597 error = vfs_ioctl(fd_file(f), cmd, arg);
598
599 return error;
600 }
601
602 #ifdef CONFIG_COMPAT
603 /**
604 * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
605 * @file: The file to operate on.
606 * @cmd: The ioctl command number.
607 * @arg: The argument to the ioctl.
608 *
609 * This is not normally called as a function, but instead set in struct
610 * file_operations as
611 *
612 * .compat_ioctl = compat_ptr_ioctl,
613 *
614 * On most architectures, the compat_ptr_ioctl() just passes all arguments
615 * to the corresponding ->ioctl handler. The exception is arch/s390, where
616 * compat_ptr() clears the top bit of a 32-bit pointer value, so user space
617 * pointers to the second 2GB alias the first 2GB, as is the case for
618 * native 32-bit s390 user space.
619 *
620 * The compat_ptr_ioctl() function must therefore be used only with ioctl
621 * functions that either ignore the argument or pass a pointer to a
622 * compatible data type.
623 *
624 * If any ioctl command handled by fops->unlocked_ioctl passes a plain
625 * integer instead of a pointer, or any of the passed data types
626 * is incompatible between 32-bit and 64-bit architectures, a proper
627 * handler is required instead of compat_ptr_ioctl.
628 */
compat_ptr_ioctl(struct file * file,unsigned int cmd,unsigned long arg)629 long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
630 {
631 if (!file->f_op->unlocked_ioctl)
632 return -ENOIOCTLCMD;
633
634 return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
635 }
636 EXPORT_SYMBOL(compat_ptr_ioctl);
637
COMPAT_SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,compat_ulong_t,arg)638 COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
639 compat_ulong_t, arg)
640 {
641 CLASS(fd, f)(fd);
642 int error;
643
644 if (fd_empty(f))
645 return -EBADF;
646
647 error = security_file_ioctl_compat(fd_file(f), cmd, arg);
648 if (error)
649 return error;
650
651 switch (cmd) {
652 /* FICLONE takes an int argument, so don't use compat_ptr() */
653 case FICLONE:
654 error = ioctl_file_clone(fd_file(f), arg, 0, 0, 0);
655 break;
656
657 #if defined(CONFIG_X86_64)
658 /* these get messy on amd64 due to alignment differences */
659 case FS_IOC_RESVSP_32:
660 case FS_IOC_RESVSP64_32:
661 error = compat_ioctl_preallocate(fd_file(f), 0, compat_ptr(arg));
662 break;
663 case FS_IOC_UNRESVSP_32:
664 case FS_IOC_UNRESVSP64_32:
665 error = compat_ioctl_preallocate(fd_file(f), FALLOC_FL_PUNCH_HOLE,
666 compat_ptr(arg));
667 break;
668 case FS_IOC_ZERO_RANGE_32:
669 error = compat_ioctl_preallocate(fd_file(f), FALLOC_FL_ZERO_RANGE,
670 compat_ptr(arg));
671 break;
672 #endif
673
674 /*
675 * These access 32-bit values anyway so no further handling is
676 * necessary.
677 */
678 case FS_IOC32_GETFLAGS:
679 case FS_IOC32_SETFLAGS:
680 cmd = (cmd == FS_IOC32_GETFLAGS) ?
681 FS_IOC_GETFLAGS : FS_IOC_SETFLAGS;
682 fallthrough;
683 /*
684 * everything else in do_vfs_ioctl() takes either a compatible
685 * pointer argument or no argument -- call it with a modified
686 * argument.
687 */
688 default:
689 error = do_vfs_ioctl(fd_file(f), fd, cmd,
690 (unsigned long)compat_ptr(arg));
691 if (error != -ENOIOCTLCMD)
692 break;
693
694 if (fd_file(f)->f_op->compat_ioctl)
695 error = fd_file(f)->f_op->compat_ioctl(fd_file(f), cmd, arg);
696 if (error == -ENOIOCTLCMD)
697 error = -ENOTTY;
698 break;
699 }
700 return error;
701 }
702 #endif
703