Root/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/fd.h>
8#include <linux/hdreg.h>
9#include <linux/slab.h>
10#include <linux/syscalls.h>
11#include <linux/smp_lock.h>
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
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
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
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
63    /*
64     * We need to set the startsect first, the driver may
65     * want to override it.
66     */
67    geo.start = get_start_sect(bdev);
68    ret = disk->fops->getgeo(bdev, &geo);
69    if (ret)
70        return ret;
71
72    ret = copy_to_user(ugeo, &geo, 4);
73    ret |= __put_user(geo.start, &ugeo->start);
74    if (ret)
75        ret = -EFAULT;
76
77    return ret;
78}
79
80static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
81        unsigned int cmd, unsigned long arg)
82{
83    mm_segment_t old_fs = get_fs();
84    unsigned long kval;
85    unsigned int __user *uvp;
86    int error;
87
88    set_fs(KERNEL_DS);
89    error = __blkdev_driver_ioctl(bdev, mode,
90                cmd, (unsigned long)(&kval));
91    set_fs(old_fs);
92
93    if (error == 0) {
94        uvp = compat_ptr(arg);
95        if (put_user(kval, uvp))
96            error = -EFAULT;
97    }
98    return error;
99}
100
101struct compat_cdrom_read_audio {
102    union cdrom_addr addr;
103    u8 addr_format;
104    compat_int_t nframes;
105    compat_caddr_t buf;
106};
107
108struct compat_cdrom_generic_command {
109    unsigned char cmd[CDROM_PACKET_SIZE];
110    compat_caddr_t buffer;
111    compat_uint_t buflen;
112    compat_int_t stat;
113    compat_caddr_t sense;
114    unsigned char data_direction;
115    compat_int_t quiet;
116    compat_int_t timeout;
117    compat_caddr_t reserved[1];
118};
119
120static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
121        unsigned int cmd, unsigned long arg)
122{
123    struct cdrom_read_audio __user *cdread_audio;
124    struct compat_cdrom_read_audio __user *cdread_audio32;
125    __u32 data;
126    void __user *datap;
127
128    cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
129    cdread_audio32 = compat_ptr(arg);
130
131    if (copy_in_user(&cdread_audio->addr,
132             &cdread_audio32->addr,
133             (sizeof(*cdread_audio32) -
134              sizeof(compat_caddr_t))))
135        return -EFAULT;
136
137    if (get_user(data, &cdread_audio32->buf))
138        return -EFAULT;
139    datap = compat_ptr(data);
140    if (put_user(datap, &cdread_audio->buf))
141        return -EFAULT;
142
143    return __blkdev_driver_ioctl(bdev, mode, cmd,
144            (unsigned long)cdread_audio);
145}
146
147static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
148        unsigned int cmd, unsigned long arg)
149{
150    struct cdrom_generic_command __user *cgc;
151    struct compat_cdrom_generic_command __user *cgc32;
152    u32 data;
153    unsigned char dir;
154    int itmp;
155
156    cgc = compat_alloc_user_space(sizeof(*cgc));
157    cgc32 = compat_ptr(arg);
158
159    if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
160        get_user(data, &cgc32->buffer) ||
161        put_user(compat_ptr(data), &cgc->buffer) ||
162        copy_in_user(&cgc->buflen, &cgc32->buflen,
163             (sizeof(unsigned int) + sizeof(int))) ||
164        get_user(data, &cgc32->sense) ||
165        put_user(compat_ptr(data), &cgc->sense) ||
166        get_user(dir, &cgc32->data_direction) ||
167        put_user(dir, &cgc->data_direction) ||
168        get_user(itmp, &cgc32->quiet) ||
169        put_user(itmp, &cgc->quiet) ||
170        get_user(itmp, &cgc32->timeout) ||
171        put_user(itmp, &cgc->timeout) ||
172        get_user(data, &cgc32->reserved[0]) ||
173        put_user(compat_ptr(data), &cgc->reserved[0]))
174        return -EFAULT;
175
176    return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
177}
178
179struct compat_blkpg_ioctl_arg {
180    compat_int_t op;
181    compat_int_t flags;
182    compat_int_t datalen;
183    compat_caddr_t data;
184};
185
186static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
187        unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
188{
189    struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
190    compat_caddr_t udata;
191    compat_int_t n;
192    int err;
193
194    err = get_user(n, &ua32->op);
195    err |= put_user(n, &a->op);
196    err |= get_user(n, &ua32->flags);
197    err |= put_user(n, &a->flags);
198    err |= get_user(n, &ua32->datalen);
199    err |= put_user(n, &a->datalen);
200    err |= get_user(udata, &ua32->data);
201    err |= put_user(compat_ptr(udata), &a->data);
202    if (err)
203        return err;
204
205    return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
206}
207
208#define BLKBSZGET_32 _IOR(0x12, 112, int)
209#define BLKBSZSET_32 _IOW(0x12, 113, int)
210#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
211
212struct compat_floppy_struct {
213    compat_uint_t size;
214    compat_uint_t sect;
215    compat_uint_t head;
216    compat_uint_t track;
217    compat_uint_t stretch;
218    unsigned char gap;
219    unsigned char rate;
220    unsigned char spec1;
221    unsigned char fmt_gap;
222    const compat_caddr_t name;
223};
224
225struct compat_floppy_drive_params {
226    char cmos;
227    compat_ulong_t max_dtr;
228    compat_ulong_t hlt;
229    compat_ulong_t hut;
230    compat_ulong_t srt;
231    compat_ulong_t spinup;
232    compat_ulong_t spindown;
233    unsigned char spindown_offset;
234    unsigned char select_delay;
235    unsigned char rps;
236    unsigned char tracks;
237    compat_ulong_t timeout;
238    unsigned char interleave_sect;
239    struct floppy_max_errors max_errors;
240    char flags;
241    char read_track;
242    short autodetect[8];
243    compat_int_t checkfreq;
244    compat_int_t native_format;
245};
246
247struct compat_floppy_drive_struct {
248    signed char flags;
249    compat_ulong_t spinup_date;
250    compat_ulong_t select_date;
251    compat_ulong_t first_read_date;
252    short probed_format;
253    short track;
254    short maxblock;
255    short maxtrack;
256    compat_int_t generation;
257    compat_int_t keep_data;
258    compat_int_t fd_ref;
259    compat_int_t fd_device;
260    compat_int_t last_checked;
261    compat_caddr_t dmabuf;
262    compat_int_t bufblocks;
263};
264
265struct compat_floppy_fdc_state {
266    compat_int_t spec1;
267    compat_int_t spec2;
268    compat_int_t dtr;
269    unsigned char version;
270    unsigned char dor;
271    compat_ulong_t address;
272    unsigned int rawcmd:2;
273    unsigned int reset:1;
274    unsigned int need_configure:1;
275    unsigned int perp_mode:2;
276    unsigned int has_fifo:1;
277    unsigned int driver_version;
278    unsigned char track[4];
279};
280
281struct compat_floppy_write_errors {
282    unsigned int write_errors;
283    compat_ulong_t first_error_sector;
284    compat_int_t first_error_generation;
285    compat_ulong_t last_error_sector;
286    compat_int_t last_error_generation;
287    compat_uint_t badness;
288};
289
290#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
291#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
292#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct)
293#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
294#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
295#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
296#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
297#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
298#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors)
299
300static struct {
301    unsigned int cmd32;
302    unsigned int cmd;
303} fd_ioctl_trans_table[] = {
304    { FDSETPRM32, FDSETPRM },
305    { FDDEFPRM32, FDDEFPRM },
306    { FDGETPRM32, FDGETPRM },
307    { FDSETDRVPRM32, FDSETDRVPRM },
308    { FDGETDRVPRM32, FDGETDRVPRM },
309    { FDGETDRVSTAT32, FDGETDRVSTAT },
310    { FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
311    { FDGETFDCSTAT32, FDGETFDCSTAT },
312    { FDWERRORGET32, FDWERRORGET }
313};
314
315#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
316
317static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
318        unsigned int cmd, unsigned long arg)
319{
320    mm_segment_t old_fs = get_fs();
321    void *karg = NULL;
322    unsigned int kcmd = 0;
323    int i, err;
324
325    for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
326        if (cmd == fd_ioctl_trans_table[i].cmd32) {
327            kcmd = fd_ioctl_trans_table[i].cmd;
328            break;
329        }
330    if (!kcmd)
331        return -EINVAL;
332
333    switch (cmd) {
334    case FDSETPRM32:
335    case FDDEFPRM32:
336    case FDGETPRM32:
337    {
338        compat_uptr_t name;
339        struct compat_floppy_struct __user *uf;
340        struct floppy_struct *f;
341
342        uf = compat_ptr(arg);
343        f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
344        if (!karg)
345            return -ENOMEM;
346        if (cmd == FDGETPRM32)
347            break;
348        err = __get_user(f->size, &uf->size);
349        err |= __get_user(f->sect, &uf->sect);
350        err |= __get_user(f->head, &uf->head);
351        err |= __get_user(f->track, &uf->track);
352        err |= __get_user(f->stretch, &uf->stretch);
353        err |= __get_user(f->gap, &uf->gap);
354        err |= __get_user(f->rate, &uf->rate);
355        err |= __get_user(f->spec1, &uf->spec1);
356        err |= __get_user(f->fmt_gap, &uf->fmt_gap);
357        err |= __get_user(name, &uf->name);
358        f->name = compat_ptr(name);
359        if (err) {
360            err = -EFAULT;
361            goto out;
362        }
363        break;
364    }
365    case FDSETDRVPRM32:
366    case FDGETDRVPRM32:
367    {
368        struct compat_floppy_drive_params __user *uf;
369        struct floppy_drive_params *f;
370
371        uf = compat_ptr(arg);
372        f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
373        if (!karg)
374            return -ENOMEM;
375        if (cmd == FDGETDRVPRM32)
376            break;
377        err = __get_user(f->cmos, &uf->cmos);
378        err |= __get_user(f->max_dtr, &uf->max_dtr);
379        err |= __get_user(f->hlt, &uf->hlt);
380        err |= __get_user(f->hut, &uf->hut);
381        err |= __get_user(f->srt, &uf->srt);
382        err |= __get_user(f->spinup, &uf->spinup);
383        err |= __get_user(f->spindown, &uf->spindown);
384        err |= __get_user(f->spindown_offset, &uf->spindown_offset);
385        err |= __get_user(f->select_delay, &uf->select_delay);
386        err |= __get_user(f->rps, &uf->rps);
387        err |= __get_user(f->tracks, &uf->tracks);
388        err |= __get_user(f->timeout, &uf->timeout);
389        err |= __get_user(f->interleave_sect, &uf->interleave_sect);
390        err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
391        err |= __get_user(f->flags, &uf->flags);
392        err |= __get_user(f->read_track, &uf->read_track);
393        err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
394        err |= __get_user(f->checkfreq, &uf->checkfreq);
395        err |= __get_user(f->native_format, &uf->native_format);
396        if (err) {
397            err = -EFAULT;
398            goto out;
399        }
400        break;
401    }
402    case FDGETDRVSTAT32:
403    case FDPOLLDRVSTAT32:
404        karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
405        if (!karg)
406            return -ENOMEM;
407        break;
408    case FDGETFDCSTAT32:
409        karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
410        if (!karg)
411            return -ENOMEM;
412        break;
413    case FDWERRORGET32:
414        karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
415        if (!karg)
416            return -ENOMEM;
417        break;
418    default:
419        return -EINVAL;
420    }
421    set_fs(KERNEL_DS);
422    err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
423    set_fs(old_fs);
424    if (err)
425        goto out;
426    switch (cmd) {
427    case FDGETPRM32:
428    {
429        struct floppy_struct *f = karg;
430        struct compat_floppy_struct __user *uf = compat_ptr(arg);
431
432        err = __put_user(f->size, &uf->size);
433        err |= __put_user(f->sect, &uf->sect);
434        err |= __put_user(f->head, &uf->head);
435        err |= __put_user(f->track, &uf->track);
436        err |= __put_user(f->stretch, &uf->stretch);
437        err |= __put_user(f->gap, &uf->gap);
438        err |= __put_user(f->rate, &uf->rate);
439        err |= __put_user(f->spec1, &uf->spec1);
440        err |= __put_user(f->fmt_gap, &uf->fmt_gap);
441        err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
442        break;
443    }
444    case FDGETDRVPRM32:
445    {
446        struct compat_floppy_drive_params __user *uf;
447        struct floppy_drive_params *f = karg;
448
449        uf = compat_ptr(arg);
450        err = __put_user(f->cmos, &uf->cmos);
451        err |= __put_user(f->max_dtr, &uf->max_dtr);
452        err |= __put_user(f->hlt, &uf->hlt);
453        err |= __put_user(f->hut, &uf->hut);
454        err |= __put_user(f->srt, &uf->srt);
455        err |= __put_user(f->spinup, &uf->spinup);
456        err |= __put_user(f->spindown, &uf->spindown);
457        err |= __put_user(f->spindown_offset, &uf->spindown_offset);
458        err |= __put_user(f->select_delay, &uf->select_delay);
459        err |= __put_user(f->rps, &uf->rps);
460        err |= __put_user(f->tracks, &uf->tracks);
461        err |= __put_user(f->timeout, &uf->timeout);
462        err |= __put_user(f->interleave_sect, &uf->interleave_sect);
463        err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
464        err |= __put_user(f->flags, &uf->flags);
465        err |= __put_user(f->read_track, &uf->read_track);
466        err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
467        err |= __put_user(f->checkfreq, &uf->checkfreq);
468        err |= __put_user(f->native_format, &uf->native_format);
469        break;
470    }
471    case FDGETDRVSTAT32:
472    case FDPOLLDRVSTAT32:
473    {
474        struct compat_floppy_drive_struct __user *uf;
475        struct floppy_drive_struct *f = karg;
476
477        uf = compat_ptr(arg);
478        err = __put_user(f->flags, &uf->flags);
479        err |= __put_user(f->spinup_date, &uf->spinup_date);
480        err |= __put_user(f->select_date, &uf->select_date);
481        err |= __put_user(f->first_read_date, &uf->first_read_date);
482        err |= __put_user(f->probed_format, &uf->probed_format);
483        err |= __put_user(f->track, &uf->track);
484        err |= __put_user(f->maxblock, &uf->maxblock);
485        err |= __put_user(f->maxtrack, &uf->maxtrack);
486        err |= __put_user(f->generation, &uf->generation);
487        err |= __put_user(f->keep_data, &uf->keep_data);
488        err |= __put_user(f->fd_ref, &uf->fd_ref);
489        err |= __put_user(f->fd_device, &uf->fd_device);
490        err |= __put_user(f->last_checked, &uf->last_checked);
491        err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
492        err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
493        break;
494    }
495    case FDGETFDCSTAT32:
496    {
497        struct compat_floppy_fdc_state __user *uf;
498        struct floppy_fdc_state *f = karg;
499
500        uf = compat_ptr(arg);
501        err = __put_user(f->spec1, &uf->spec1);
502        err |= __put_user(f->spec2, &uf->spec2);
503        err |= __put_user(f->dtr, &uf->dtr);
504        err |= __put_user(f->version, &uf->version);
505        err |= __put_user(f->dor, &uf->dor);
506        err |= __put_user(f->address, &uf->address);
507        err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
508                   (char *)&f->address + sizeof(f->address), sizeof(int));
509        err |= __put_user(f->driver_version, &uf->driver_version);
510        err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
511        break;
512    }
513    case FDWERRORGET32:
514    {
515        struct compat_floppy_write_errors __user *uf;
516        struct floppy_write_errors *f = karg;
517
518        uf = compat_ptr(arg);
519        err = __put_user(f->write_errors, &uf->write_errors);
520        err |= __put_user(f->first_error_sector, &uf->first_error_sector);
521        err |= __put_user(f->first_error_generation, &uf->first_error_generation);
522        err |= __put_user(f->last_error_sector, &uf->last_error_sector);
523        err |= __put_user(f->last_error_generation, &uf->last_error_generation);
524        err |= __put_user(f->badness, &uf->badness);
525        break;
526    }
527    default:
528        break;
529    }
530    if (err)
531        err = -EFAULT;
532
533out:
534    kfree(karg);
535    return err;
536}
537
538struct compat_blk_user_trace_setup {
539    char name[32];
540    u16 act_mask;
541    u32 buf_size;
542    u32 buf_nr;
543    compat_u64 start_lba;
544    compat_u64 end_lba;
545    u32 pid;
546};
547#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup)
548
549static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
550{
551    struct blk_user_trace_setup buts;
552    struct compat_blk_user_trace_setup cbuts;
553    struct request_queue *q;
554    char b[BDEVNAME_SIZE];
555    int ret;
556
557    q = bdev_get_queue(bdev);
558    if (!q)
559        return -ENXIO;
560
561    if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
562        return -EFAULT;
563
564    bdevname(bdev, b);
565
566    buts = (struct blk_user_trace_setup) {
567        .act_mask = cbuts.act_mask,
568        .buf_size = cbuts.buf_size,
569        .buf_nr = cbuts.buf_nr,
570        .start_lba = cbuts.start_lba,
571        .end_lba = cbuts.end_lba,
572        .pid = cbuts.pid,
573    };
574    memcpy(&buts.name, &cbuts.name, 32);
575
576    mutex_lock(&bdev->bd_mutex);
577    ret = do_blk_trace_setup(q, b, bdev->bd_dev, bdev, &buts);
578    mutex_unlock(&bdev->bd_mutex);
579    if (ret)
580        return ret;
581
582    if (copy_to_user(arg, &buts.name, 32))
583        return -EFAULT;
584
585    return 0;
586}
587
588static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
589            unsigned cmd, unsigned long arg)
590{
591    switch (cmd) {
592    case HDIO_GET_UNMASKINTR:
593    case HDIO_GET_MULTCOUNT:
594    case HDIO_GET_KEEPSETTINGS:
595    case HDIO_GET_32BIT:
596    case HDIO_GET_NOWERR:
597    case HDIO_GET_DMA:
598    case HDIO_GET_NICE:
599    case HDIO_GET_WCACHE:
600    case HDIO_GET_ACOUSTIC:
601    case HDIO_GET_ADDRESS:
602    case HDIO_GET_BUSSTATE:
603        return compat_hdio_ioctl(bdev, mode, cmd, arg);
604    case FDSETPRM32:
605    case FDDEFPRM32:
606    case FDGETPRM32:
607    case FDSETDRVPRM32:
608    case FDGETDRVPRM32:
609    case FDGETDRVSTAT32:
610    case FDPOLLDRVSTAT32:
611    case FDGETFDCSTAT32:
612    case FDWERRORGET32:
613        return compat_fd_ioctl(bdev, mode, cmd, arg);
614    case CDROMREADAUDIO:
615        return compat_cdrom_read_audio(bdev, mode, cmd, arg);
616    case CDROM_SEND_PACKET:
617        return compat_cdrom_generic_command(bdev, mode, cmd, arg);
618
619    /*
620     * No handler required for the ones below, we just need to
621     * convert arg to a 64 bit pointer.
622     */
623    case BLKSECTSET:
624    /*
625     * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
626     * Some need translations, these do not.
627     */
628    case HDIO_GET_IDENTITY:
629    case HDIO_DRIVE_TASK:
630    case HDIO_DRIVE_CMD:
631    /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
632    case 0x330:
633    /* 0x02 -- Floppy ioctls */
634    case FDMSGON:
635    case FDMSGOFF:
636    case FDSETEMSGTRESH:
637    case FDFLUSH:
638    case FDWERRORCLR:
639    case FDSETMAXERRS:
640    case FDGETMAXERRS:
641    case FDGETDRVTYP:
642    case FDEJECT:
643    case FDCLRPRM:
644    case FDFMTBEG:
645    case FDFMTEND:
646    case FDRESET:
647    case FDTWADDLE:
648    case FDFMTTRK:
649    case FDRAWCMD:
650    /* CDROM stuff */
651    case CDROMPAUSE:
652    case CDROMRESUME:
653    case CDROMPLAYMSF:
654    case CDROMPLAYTRKIND:
655    case CDROMREADTOCHDR:
656    case CDROMREADTOCENTRY:
657    case CDROMSTOP:
658    case CDROMSTART:
659    case CDROMEJECT:
660    case CDROMVOLCTRL:
661    case CDROMSUBCHNL:
662    case CDROMMULTISESSION:
663    case CDROM_GET_MCN:
664    case CDROMRESET:
665    case CDROMVOLREAD:
666    case CDROMSEEK:
667    case CDROMPLAYBLK:
668    case CDROMCLOSETRAY:
669    case CDROM_DISC_STATUS:
670    case CDROM_CHANGER_NSLOTS:
671    case CDROM_GET_CAPABILITY:
672    /* Ignore cdrom.h about these next 5 ioctls, they absolutely do
673     * not take a struct cdrom_read, instead they take a struct cdrom_msf
674     * which is compatible.
675     */
676    case CDROMREADMODE2:
677    case CDROMREADMODE1:
678    case CDROMREADRAW:
679    case CDROMREADCOOKED:
680    case CDROMREADALL:
681    /* DVD ioctls */
682    case DVD_READ_STRUCT:
683    case DVD_WRITE_STRUCT:
684    case DVD_AUTH:
685        arg = (unsigned long)compat_ptr(arg);
686    /* These intepret arg as an unsigned long, not as a pointer,
687     * so we must not do compat_ptr() conversion. */
688    case HDIO_SET_MULTCOUNT:
689    case HDIO_SET_UNMASKINTR:
690    case HDIO_SET_KEEPSETTINGS:
691    case HDIO_SET_32BIT:
692    case HDIO_SET_NOWERR:
693    case HDIO_SET_DMA:
694    case HDIO_SET_PIO_MODE:
695    case HDIO_SET_NICE:
696    case HDIO_SET_WCACHE:
697    case HDIO_SET_ACOUSTIC:
698    case HDIO_SET_BUSSTATE:
699    case HDIO_SET_ADDRESS:
700    case CDROMEJECT_SW:
701    case CDROM_SET_OPTIONS:
702    case CDROM_CLEAR_OPTIONS:
703    case CDROM_SELECT_SPEED:
704    case CDROM_SELECT_DISC:
705    case CDROM_MEDIA_CHANGED:
706    case CDROM_DRIVE_STATUS:
707    case CDROM_LOCKDOOR:
708    case CDROM_DEBUG:
709        break;
710    default:
711        /* unknown ioctl number */
712        return -ENOIOCTLCMD;
713    }
714
715    return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
716}
717
718/* Most of the generic ioctls are handled in the normal fallback path.
719   This assumes the blkdev's low level compat_ioctl always returns
720   ENOIOCTLCMD for unknown ioctls. */
721long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
722{
723    int ret = -ENOIOCTLCMD;
724    struct inode *inode = file->f_mapping->host;
725    struct block_device *bdev = inode->i_bdev;
726    struct gendisk *disk = bdev->bd_disk;
727    fmode_t mode = file->f_mode;
728    struct backing_dev_info *bdi;
729    loff_t size;
730
731    /*
732     * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
733     * to updated it before every ioctl.
734     */
735    if (file->f_flags & O_NDELAY)
736        mode |= FMODE_NDELAY;
737    else
738        mode &= ~FMODE_NDELAY;
739
740    switch (cmd) {
741    case HDIO_GETGEO:
742        return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
743    case BLKPBSZGET:
744        return compat_put_uint(arg, bdev_physical_block_size(bdev));
745    case BLKIOMIN:
746        return compat_put_uint(arg, bdev_io_min(bdev));
747    case BLKIOOPT:
748        return compat_put_uint(arg, bdev_io_opt(bdev));
749    case BLKALIGNOFF:
750        return compat_put_int(arg, bdev_alignment_offset(bdev));
751    case BLKDISCARDZEROES:
752        return compat_put_uint(arg, bdev_discard_zeroes_data(bdev));
753    case BLKFLSBUF:
754    case BLKROSET:
755    case BLKDISCARD:
756    /*
757     * the ones below are implemented in blkdev_locked_ioctl,
758     * but we call blkdev_ioctl, which gets the lock for us
759     */
760    case BLKRRPART:
761        return blkdev_ioctl(bdev, mode, cmd,
762                (unsigned long)compat_ptr(arg));
763    case BLKBSZSET_32:
764        return blkdev_ioctl(bdev, mode, BLKBSZSET,
765                (unsigned long)compat_ptr(arg));
766    case BLKPG:
767        return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
768    case BLKRAGET:
769    case BLKFRAGET:
770        if (!arg)
771            return -EINVAL;
772        bdi = blk_get_backing_dev_info(bdev);
773        if (bdi == NULL)
774            return -ENOTTY;
775        return compat_put_long(arg,
776                       (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
777    case BLKROGET: /* compatible */
778        return compat_put_int(arg, bdev_read_only(bdev) != 0);
779    case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
780        return compat_put_int(arg, block_size(bdev));
781    case BLKSSZGET: /* get block device hardware sector size */
782        return compat_put_int(arg, bdev_logical_block_size(bdev));
783    case BLKSECTGET:
784        return compat_put_ushort(arg,
785                     queue_max_sectors(bdev_get_queue(bdev)));
786    case BLKRASET: /* compatible, but no compat_ptr (!) */
787    case BLKFRASET:
788        if (!capable(CAP_SYS_ADMIN))
789            return -EACCES;
790        bdi = blk_get_backing_dev_info(bdev);
791        if (bdi == NULL)
792            return -ENOTTY;
793        bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
794        return 0;
795    case BLKGETSIZE:
796        size = bdev->bd_inode->i_size;
797        if ((size >> 9) > ~0UL)
798            return -EFBIG;
799        return compat_put_ulong(arg, size >> 9);
800
801    case BLKGETSIZE64_32:
802        return compat_put_u64(arg, bdev->bd_inode->i_size);
803
804    case BLKTRACESETUP32:
805        lock_kernel();
806        ret = compat_blk_trace_setup(bdev, compat_ptr(arg));
807        unlock_kernel();
808        return ret;
809    case BLKTRACESTART: /* compatible */
810    case BLKTRACESTOP: /* compatible */
811    case BLKTRACETEARDOWN: /* compatible */
812        lock_kernel();
813        ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
814        unlock_kernel();
815        return ret;
816    default:
817        if (disk->fops->compat_ioctl)
818            ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
819        if (ret == -ENOIOCTLCMD)
820            ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
821        return ret;
822    }
823}
824

Archive Download this file



interactive