Merge tag 'riscv/for-v5.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv...
[linux-2.6-microblaze.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 #ifdef CONFIG_BLOCK
40 #include <linux/cdrom.h>
41 #include <linux/fd.h>
42 #include <scsi/scsi.h>
43 #include <scsi/scsi_ioctl.h>
44 #include <scsi/sg.h>
45 #endif
46
47 #include <linux/uaccess.h>
48 #include <linux/watchdog.h>
49
50 #include <linux/hiddev.h>
51
52
53 #include <linux/sort.h>
54
55 /*
56  * simple reversible transform to make our table more evenly
57  * distributed after sorting.
58  */
59 #define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff)
60
61 #define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd),
62 static unsigned int ioctl_pointer[] = {
63 #ifdef CONFIG_BLOCK
64 /* Big S */
65 COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
66 COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
67 COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
68 COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
69 COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
70 COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
71 COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
72 COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
73 #endif
74 #ifdef CONFIG_BLOCK
75 /* SG stuff */
76 COMPATIBLE_IOCTL(SG_IO)
77 COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
78 COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
79 COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
80 COMPATIBLE_IOCTL(SG_EMULATED_HOST)
81 COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
82 COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
83 COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
84 COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
85 COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
86 COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
87 COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
88 COMPATIBLE_IOCTL(SG_GET_PACK_ID)
89 COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
90 COMPATIBLE_IOCTL(SG_SET_DEBUG)
91 COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
92 COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
93 COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
94 COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
95 COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
96 COMPATIBLE_IOCTL(SG_SCSI_RESET)
97 COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
98 COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
99 COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
100 #endif
101 };
102
103 /*
104  * Convert common ioctl arguments based on their command number
105  *
106  * Please do not add any code in here. Instead, implement
107  * a compat_ioctl operation in the place that handleŃ• the
108  * ioctl for the native case.
109  */
110 static long do_ioctl_trans(unsigned int cmd,
111                  unsigned long arg, struct file *file)
112 {
113         return -ENOIOCTLCMD;
114 }
115
116 static int compat_ioctl_check_table(unsigned int xcmd)
117 {
118 #ifdef CONFIG_BLOCK
119         int i;
120         const int max = ARRAY_SIZE(ioctl_pointer) - 1;
121
122         BUILD_BUG_ON(max >= (1 << 16));
123
124         /* guess initial offset into table, assuming a
125            normalized distribution */
126         i = ((xcmd >> 16) * max) >> 16;
127
128         /* do linear search up first, until greater or equal */
129         while (ioctl_pointer[i] < xcmd && i < max)
130                 i++;
131
132         /* then do linear search down */
133         while (ioctl_pointer[i] > xcmd && i > 0)
134                 i--;
135
136         return ioctl_pointer[i] == xcmd;
137 #else
138         return 0;
139 #endif
140 }
141
142 COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
143                        compat_ulong_t, arg32)
144 {
145         unsigned long arg = arg32;
146         struct fd f = fdget(fd);
147         int error = -EBADF;
148         if (!f.file)
149                 goto out;
150
151         /* RED-PEN how should LSM module know it's handling 32bit? */
152         error = security_file_ioctl(f.file, cmd, arg);
153         if (error)
154                 goto out_fput;
155
156         switch (cmd) {
157         /* these are never seen by ->ioctl(), no argument or int argument */
158         case FIOCLEX:
159         case FIONCLEX:
160         case FIFREEZE:
161         case FITHAW:
162         case FICLONE:
163                 goto do_ioctl;
164         /* these are never seen by ->ioctl(), pointer argument */
165         case FIONBIO:
166         case FIOASYNC:
167         case FIOQSIZE:
168         case FS_IOC_FIEMAP:
169         case FIGETBSZ:
170         case FICLONERANGE:
171         case FIDEDUPERANGE:
172                 goto found_handler;
173         /*
174          * The next group is the stuff handled inside file_ioctl().
175          * For regular files these never reach ->ioctl(); for
176          * devices, sockets, etc. they do and one (FIONREAD) is
177          * even accepted in some cases.  In all those cases
178          * argument has the same type, so we can handle these
179          * here, shunting them towards do_vfs_ioctl().
180          * ->compat_ioctl() will never see any of those.
181          */
182         /* pointer argument, never actually handled by ->ioctl() */
183         case FIBMAP:
184                 goto found_handler;
185         /* handled by some ->ioctl(); always a pointer to int */
186         case FIONREAD:
187                 goto found_handler;
188         /* these get messy on amd64 due to alignment differences */
189 #if defined(CONFIG_X86_64)
190         case FS_IOC_RESVSP_32:
191         case FS_IOC_RESVSP64_32:
192                 error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
193                 goto out_fput;
194         case FS_IOC_UNRESVSP_32:
195         case FS_IOC_UNRESVSP64_32:
196                 error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
197                                 compat_ptr(arg));
198                 goto out_fput;
199         case FS_IOC_ZERO_RANGE_32:
200                 error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
201                                 compat_ptr(arg));
202                 goto out_fput;
203 #else
204         case FS_IOC_RESVSP:
205         case FS_IOC_RESVSP64:
206         case FS_IOC_UNRESVSP:
207         case FS_IOC_UNRESVSP64:
208         case FS_IOC_ZERO_RANGE:
209                 goto found_handler;
210 #endif
211
212         default:
213                 if (f.file->f_op->compat_ioctl) {
214                         error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
215                         if (error != -ENOIOCTLCMD)
216                                 goto out_fput;
217                 }
218
219                 if (!f.file->f_op->unlocked_ioctl)
220                         goto do_ioctl;
221                 break;
222         }
223
224         if (compat_ioctl_check_table(XFORM(cmd)))
225                 goto found_handler;
226
227         error = do_ioctl_trans(cmd, arg, f.file);
228         if (error == -ENOIOCTLCMD)
229                 error = -ENOTTY;
230
231         goto out_fput;
232
233  found_handler:
234         arg = (unsigned long)compat_ptr(arg);
235  do_ioctl:
236         error = do_vfs_ioctl(f.file, fd, cmd, arg);
237  out_fput:
238         fdput(f);
239  out:
240         return error;
241 }
242
243 static int __init init_sys32_ioctl_cmp(const void *p, const void *q)
244 {
245         unsigned int a, b;
246         a = *(unsigned int *)p;
247         b = *(unsigned int *)q;
248         if (a > b)
249                 return 1;
250         if (a < b)
251                 return -1;
252         return 0;
253 }
254
255 static int __init init_sys32_ioctl(void)
256 {
257         sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer),
258                 init_sys32_ioctl_cmp, NULL);
259         return 0;
260 }
261 __initcall(init_sys32_ioctl);