compat_ioctl: scsi: move ioctl handling into drivers
[linux-2.6-block.git] / fs / compat_ioctl.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4  *
5  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
6  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
7  * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
8  * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
9  *
10  * These routines maintain argument size conversion between 32bit and 64bit
11  * ioctls.
12  */
13
14 #include <linux/types.h>
15 #include <linux/compat.h>
16 #include <linux/kernel.h>
17 #include <linux/capability.h>
18 #include <linux/compiler.h>
19 #include <linux/sched.h>
20 #include <linux/smp.h>
21 #include <linux/ioctl.h>
22 #include <linux/if.h>
23 #include <linux/raid/md_u.h>
24 #include <linux/falloc.h>
25 #include <linux/file.h>
26 #include <linux/ppp-ioctl.h>
27 #include <linux/if_pppox.h>
28 #include <linux/tty.h>
29 #include <linux/vt_kern.h>
30 #include <linux/blkdev.h>
31 #include <linux/serial.h>
32 #include <linux/ctype.h>
33 #include <linux/syscalls.h>
34 #include <linux/gfp.h>
35 #include <linux/cec.h>
36
37 #include "internal.h"
38
39 #include <linux/uaccess.h>
40 #include <linux/watchdog.h>
41
42 #include <linux/hiddev.h>
43
44 COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
45                        compat_ulong_t, arg32)
46 {
47         unsigned long arg = arg32;
48         struct fd f = fdget(fd);
49         int error = -EBADF;
50         if (!f.file)
51                 goto out;
52
53         /* RED-PEN how should LSM module know it's handling 32bit? */
54         error = security_file_ioctl(f.file, cmd, arg);
55         if (error)
56                 goto out_fput;
57
58         switch (cmd) {
59         /* these are never seen by ->ioctl(), no argument or int argument */
60         case FIOCLEX:
61         case FIONCLEX:
62         case FIFREEZE:
63         case FITHAW:
64         case FICLONE:
65                 goto do_ioctl;
66         /* these are never seen by ->ioctl(), pointer argument */
67         case FIONBIO:
68         case FIOASYNC:
69         case FIOQSIZE:
70         case FS_IOC_FIEMAP:
71         case FIGETBSZ:
72         case FICLONERANGE:
73         case FIDEDUPERANGE:
74                 goto found_handler;
75         /*
76          * The next group is the stuff handled inside file_ioctl().
77          * For regular files these never reach ->ioctl(); for
78          * devices, sockets, etc. they do and one (FIONREAD) is
79          * even accepted in some cases.  In all those cases
80          * argument has the same type, so we can handle these
81          * here, shunting them towards do_vfs_ioctl().
82          * ->compat_ioctl() will never see any of those.
83          */
84         /* pointer argument, never actually handled by ->ioctl() */
85         case FIBMAP:
86                 goto found_handler;
87         /* handled by some ->ioctl(); always a pointer to int */
88         case FIONREAD:
89                 goto found_handler;
90         /* these get messy on amd64 due to alignment differences */
91 #if defined(CONFIG_X86_64)
92         case FS_IOC_RESVSP_32:
93         case FS_IOC_RESVSP64_32:
94                 error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
95                 goto out_fput;
96         case FS_IOC_UNRESVSP_32:
97         case FS_IOC_UNRESVSP64_32:
98                 error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
99                                 compat_ptr(arg));
100                 goto out_fput;
101         case FS_IOC_ZERO_RANGE_32:
102                 error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
103                                 compat_ptr(arg));
104                 goto out_fput;
105 #else
106         case FS_IOC_RESVSP:
107         case FS_IOC_RESVSP64:
108         case FS_IOC_UNRESVSP:
109         case FS_IOC_UNRESVSP64:
110         case FS_IOC_ZERO_RANGE:
111                 goto found_handler;
112 #endif
113
114         default:
115                 if (f.file->f_op->compat_ioctl) {
116                         error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
117                         if (error != -ENOIOCTLCMD)
118                                 goto out_fput;
119                 }
120
121                 error = -ENOTTY;
122                 goto out_fput;
123         }
124
125  found_handler:
126         arg = (unsigned long)compat_ptr(arg);
127  do_ioctl:
128         error = do_vfs_ioctl(f.file, fd, cmd, arg);
129  out_fput:
130         fdput(f);
131  out:
132         return error;
133 }