compat_ioctl: move CDROM_SEND_PACKET handling into scsi
[linux-2.6-block.git] / block / compat_ioctl.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
f58c4c0a
AB
2#include <linux/blkdev.h>
3#include <linux/blkpg.h>
4#include <linux/blktrace_api.h>
5#include <linux/cdrom.h>
6#include <linux/compat.h>
7#include <linux/elevator.h>
f58c4c0a 8#include <linux/hdreg.h>
b2c0fcd2 9#include <linux/pr.h>
5a0e3ad6 10#include <linux/slab.h>
f58c4c0a 11#include <linux/syscalls.h>
f58c4c0a
AB
12#include <linux/types.h>
13#include <linux/uaccess.h>
14
15static int compat_put_ushort(unsigned long arg, unsigned short val)
16{
17 return put_user(val, (unsigned short __user *)compat_ptr(arg));
18}
19
20static int compat_put_int(unsigned long arg, int val)
21{
22 return put_user(val, (compat_int_t __user *)compat_ptr(arg));
23}
24
ac481c20
MP
25static int compat_put_uint(unsigned long arg, unsigned int val)
26{
27 return put_user(val, (compat_uint_t __user *)compat_ptr(arg));
28}
29
f58c4c0a
AB
30static int compat_put_long(unsigned long arg, long val)
31{
32 return put_user(val, (compat_long_t __user *)compat_ptr(arg));
33}
34
35static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
36{
37 return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
38}
39
40static int compat_put_u64(unsigned long arg, u64 val)
41{
42 return put_user(val, (compat_u64 __user *)compat_ptr(arg));
43}
44
9617db08
AB
45struct compat_hd_geometry {
46 unsigned char heads;
47 unsigned char sectors;
48 unsigned short cylinders;
49 u32 start;
50};
51
52static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
53 struct compat_hd_geometry __user *ugeo)
54{
55 struct hd_geometry geo;
56 int ret;
57
58 if (!ugeo)
59 return -EINVAL;
60 if (!disk->fops->getgeo)
61 return -ENOTTY;
62
8b0d77f1 63 memset(&geo, 0, sizeof(geo));
9617db08
AB
64 /*
65 * We need to set the startsect first, the driver may
66 * want to override it.
67 */
68 geo.start = get_start_sect(bdev);
69 ret = disk->fops->getgeo(bdev, &geo);
70 if (ret)
71 return ret;
72
73 ret = copy_to_user(ugeo, &geo, 4);
3ddc5b46 74 ret |= put_user(geo.start, &ugeo->start);
9617db08
AB
75 if (ret)
76 ret = -EFAULT;
77
78 return ret;
79}
80
33c2dca4
AV
81static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
82 unsigned int cmd, unsigned long arg)
9617db08 83{
8363dae2 84 unsigned long __user *p;
9617db08
AB
85 int error;
86
30138384 87 p = compat_alloc_user_space(sizeof(unsigned long));
33c2dca4 88 error = __blkdev_driver_ioctl(bdev, mode,
30138384 89 cmd, (unsigned long)p);
9617db08 90 if (error == 0) {
30138384
AV
91 unsigned int __user *uvp = compat_ptr(arg);
92 unsigned long v;
93 if (get_user(v, p) || put_user(v, uvp))
9617db08
AB
94 error = -EFAULT;
95 }
96 return error;
97}
98
b3087cc4
AB
99struct compat_cdrom_read_audio {
100 union cdrom_addr addr;
101 u8 addr_format;
102 compat_int_t nframes;
103 compat_caddr_t buf;
104};
105
33c2dca4
AV
106static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
107 unsigned int cmd, unsigned long arg)
b3087cc4
AB
108{
109 struct cdrom_read_audio __user *cdread_audio;
110 struct compat_cdrom_read_audio __user *cdread_audio32;
111 __u32 data;
112 void __user *datap;
113
114 cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
115 cdread_audio32 = compat_ptr(arg);
116
117 if (copy_in_user(&cdread_audio->addr,
118 &cdread_audio32->addr,
119 (sizeof(*cdread_audio32) -
120 sizeof(compat_caddr_t))))
121 return -EFAULT;
122
123 if (get_user(data, &cdread_audio32->buf))
124 return -EFAULT;
125 datap = compat_ptr(data);
126 if (put_user(datap, &cdread_audio->buf))
127 return -EFAULT;
128
33c2dca4 129 return __blkdev_driver_ioctl(bdev, mode, cmd,
b3087cc4
AB
130 (unsigned long)cdread_audio);
131}
132
18cf7f87
AB
133struct compat_blkpg_ioctl_arg {
134 compat_int_t op;
135 compat_int_t flags;
136 compat_int_t datalen;
137 compat_caddr_t data;
138};
139
56b26add 140static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
18cf7f87
AB
141 unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
142{
143 struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
144 compat_caddr_t udata;
145 compat_int_t n;
146 int err;
147
148 err = get_user(n, &ua32->op);
149 err |= put_user(n, &a->op);
150 err |= get_user(n, &ua32->flags);
151 err |= put_user(n, &a->flags);
152 err |= get_user(n, &ua32->datalen);
153 err |= put_user(n, &a->datalen);
154 err |= get_user(udata, &ua32->data);
155 err |= put_user(compat_ptr(udata), &a->data);
156 if (err)
157 return err;
158
56b26add 159 return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
18cf7f87
AB
160}
161
f58c4c0a
AB
162#define BLKBSZGET_32 _IOR(0x12, 112, int)
163#define BLKBSZSET_32 _IOW(0x12, 113, int)
164#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
165
33c2dca4
AV
166static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
167 unsigned cmd, unsigned long arg)
7199d4cd 168{
33013a88 169 switch (cmd) {
9617db08
AB
170 case HDIO_GET_UNMASKINTR:
171 case HDIO_GET_MULTCOUNT:
172 case HDIO_GET_KEEPSETTINGS:
173 case HDIO_GET_32BIT:
174 case HDIO_GET_NOWERR:
175 case HDIO_GET_DMA:
176 case HDIO_GET_NICE:
177 case HDIO_GET_WCACHE:
178 case HDIO_GET_ACOUSTIC:
179 case HDIO_GET_ADDRESS:
180 case HDIO_GET_BUSSTATE:
33c2dca4 181 return compat_hdio_ioctl(bdev, mode, cmd, arg);
b3087cc4 182 case CDROMREADAUDIO:
33c2dca4 183 return compat_cdrom_read_audio(bdev, mode, cmd, arg);
b3087cc4 184
7199d4cd
AB
185 /*
186 * No handler required for the ones below, we just need to
187 * convert arg to a 64 bit pointer.
188 */
189 case BLKSECTSET:
190 /*
191 * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
192 * Some need translations, these do not.
193 */
194 case HDIO_GET_IDENTITY:
195 case HDIO_DRIVE_TASK:
196 case HDIO_DRIVE_CMD:
7199d4cd
AB
197 /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
198 case 0x330:
7199d4cd
AB
199 /* CDROM stuff */
200 case CDROMPAUSE:
201 case CDROMRESUME:
202 case CDROMPLAYMSF:
203 case CDROMPLAYTRKIND:
204 case CDROMREADTOCHDR:
205 case CDROMREADTOCENTRY:
206 case CDROMSTOP:
207 case CDROMSTART:
208 case CDROMEJECT:
209 case CDROMVOLCTRL:
210 case CDROMSUBCHNL:
211 case CDROMMULTISESSION:
212 case CDROM_GET_MCN:
213 case CDROMRESET:
214 case CDROMVOLREAD:
215 case CDROMSEEK:
216 case CDROMPLAYBLK:
217 case CDROMCLOSETRAY:
218 case CDROM_DISC_STATUS:
219 case CDROM_CHANGER_NSLOTS:
220 case CDROM_GET_CAPABILITY:
f3ee6e63 221 case CDROM_SEND_PACKET:
7199d4cd
AB
222 /* Ignore cdrom.h about these next 5 ioctls, they absolutely do
223 * not take a struct cdrom_read, instead they take a struct cdrom_msf
224 * which is compatible.
225 */
226 case CDROMREADMODE2:
227 case CDROMREADMODE1:
228 case CDROMREADRAW:
229 case CDROMREADCOOKED:
230 case CDROMREADALL:
231 /* DVD ioctls */
232 case DVD_READ_STRUCT:
233 case DVD_WRITE_STRUCT:
234 case DVD_AUTH:
235 arg = (unsigned long)compat_ptr(arg);
1c925604
AS
236 /* These intepret arg as an unsigned long, not as a pointer,
237 * so we must not do compat_ptr() conversion. */
238 case HDIO_SET_MULTCOUNT:
239 case HDIO_SET_UNMASKINTR:
240 case HDIO_SET_KEEPSETTINGS:
241 case HDIO_SET_32BIT:
242 case HDIO_SET_NOWERR:
243 case HDIO_SET_DMA:
244 case HDIO_SET_PIO_MODE:
245 case HDIO_SET_NICE:
246 case HDIO_SET_WCACHE:
247 case HDIO_SET_ACOUSTIC:
248 case HDIO_SET_BUSSTATE:
249 case HDIO_SET_ADDRESS:
250 case CDROMEJECT_SW:
251 case CDROM_SET_OPTIONS:
252 case CDROM_CLEAR_OPTIONS:
253 case CDROM_SELECT_SPEED:
254 case CDROM_SELECT_DISC:
255 case CDROM_MEDIA_CHANGED:
256 case CDROM_DRIVE_STATUS:
257 case CDROM_LOCKDOOR:
258 case CDROM_DEBUG:
7199d4cd
AB
259 break;
260 default:
261 /* unknown ioctl number */
262 return -ENOIOCTLCMD;
263 }
264
33c2dca4 265 return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
7199d4cd
AB
266}
267
45048d09
AV
268/* Most of the generic ioctls are handled in the normal fallback path.
269 This assumes the blkdev's low level compat_ioctl always returns
270 ENOIOCTLCMD for unknown ioctls. */
271long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
f58c4c0a 272{
45048d09
AV
273 int ret = -ENOIOCTLCMD;
274 struct inode *inode = file->f_mapping->host;
275 struct block_device *bdev = inode->i_bdev;
276 struct gendisk *disk = bdev->bd_disk;
277 fmode_t mode = file->f_mode;
45048d09 278 loff_t size;
63f26496 279 unsigned int max_sectors;
45048d09 280
fd4ce1ac
CH
281 /*
282 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
283 * to updated it before every ioctl.
284 */
45048d09 285 if (file->f_flags & O_NDELAY)
fd4ce1ac
CH
286 mode |= FMODE_NDELAY;
287 else
288 mode &= ~FMODE_NDELAY;
f58c4c0a
AB
289
290 switch (cmd) {
45048d09
AV
291 case HDIO_GETGEO:
292 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
ac481c20
MP
293 case BLKPBSZGET:
294 return compat_put_uint(arg, bdev_physical_block_size(bdev));
295 case BLKIOMIN:
296 return compat_put_uint(arg, bdev_io_min(bdev));
297 case BLKIOOPT:
298 return compat_put_uint(arg, bdev_io_opt(bdev));
299 case BLKALIGNOFF:
300 return compat_put_int(arg, bdev_alignment_offset(bdev));
98262f27 301 case BLKDISCARDZEROES:
48920ff2 302 return compat_put_uint(arg, 0);
45048d09
AV
303 case BLKFLSBUF:
304 case BLKROSET:
305 case BLKDISCARD:
8d57a98c 306 case BLKSECDISCARD:
3b3a1814 307 case BLKZEROOUT:
45048d09
AV
308 /*
309 * the ones below are implemented in blkdev_locked_ioctl,
310 * but we call blkdev_ioctl, which gets the lock for us
311 */
312 case BLKRRPART:
673bdf8c
AB
313 case BLKREPORTZONE:
314 case BLKRESETZONE:
4b43f31d
AB
315 case BLKOPENZONE:
316 case BLKCLOSEZONE:
317 case BLKFINISHZONE:
21d37340
AB
318 case BLKGETZONESZ:
319 case BLKGETNRZONES:
56b26add 320 return blkdev_ioctl(bdev, mode, cmd,
45048d09
AV
321 (unsigned long)compat_ptr(arg));
322 case BLKBSZSET_32:
56b26add 323 return blkdev_ioctl(bdev, mode, BLKBSZSET,
45048d09
AV
324 (unsigned long)compat_ptr(arg));
325 case BLKPG:
56b26add 326 return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
f58c4c0a
AB
327 case BLKRAGET:
328 case BLKFRAGET:
329 if (!arg)
330 return -EINVAL;
f58c4c0a 331 return compat_put_long(arg,
efa7c9f9 332 (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512);
f58c4c0a
AB
333 case BLKROGET: /* compatible */
334 return compat_put_int(arg, bdev_read_only(bdev) != 0);
335 case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
336 return compat_put_int(arg, block_size(bdev));
337 case BLKSSZGET: /* get block device hardware sector size */
e1defc4f 338 return compat_put_int(arg, bdev_logical_block_size(bdev));
f58c4c0a 339 case BLKSECTGET:
63f26496
AM
340 max_sectors = min_t(unsigned int, USHRT_MAX,
341 queue_max_sectors(bdev_get_queue(bdev)));
342 return compat_put_ushort(arg, max_sectors);
ef00f59c
MP
343 case BLKROTATIONAL:
344 return compat_put_ushort(arg,
345 !blk_queue_nonrot(bdev_get_queue(bdev)));
f58c4c0a
AB
346 case BLKRASET: /* compatible, but no compat_ptr (!) */
347 case BLKFRASET:
348 if (!capable(CAP_SYS_ADMIN))
349 return -EACCES;
efa7c9f9 350 bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
f58c4c0a
AB
351 return 0;
352 case BLKGETSIZE:
77304d2a 353 size = i_size_read(bdev->bd_inode);
45048d09 354 if ((size >> 9) > ~0UL)
f58c4c0a 355 return -EFBIG;
45048d09 356 return compat_put_ulong(arg, size >> 9);
f58c4c0a
AB
357
358 case BLKGETSIZE64_32:
77304d2a 359 return compat_put_u64(arg, i_size_read(bdev->bd_inode));
171044d4
AB
360
361 case BLKTRACESETUP32:
171044d4
AB
362 case BLKTRACESTART: /* compatible */
363 case BLKTRACESTOP: /* compatible */
364 case BLKTRACETEARDOWN: /* compatible */
45048d09 365 ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
7199d4cd 366 return ret;
b2c0fcd2
AB
367 case IOC_PR_REGISTER:
368 case IOC_PR_RESERVE:
369 case IOC_PR_RELEASE:
370 case IOC_PR_PREEMPT:
371 case IOC_PR_PREEMPT_ABORT:
372 case IOC_PR_CLEAR:
373 return blkdev_ioctl(bdev, mode, cmd,
374 (unsigned long)compat_ptr(arg));
45048d09
AV
375 default:
376 if (disk->fops->compat_ioctl)
377 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
378 if (ret == -ENOIOCTLCMD)
379 ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
380 return ret;
381 }
f58c4c0a 382}