~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to block/compat_ioctl.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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