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