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 538static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, 539 unsigned cmd, unsigned long arg) 540{ 541 switch (cmd) { 542 case HDIO_GET_UNMASKINTR: 543 case HDIO_GET_MULTCOUNT: 544 case HDIO_GET_KEEPSETTINGS: 545 case HDIO_GET_32BIT: 546 case HDIO_GET_NOWERR: 547 case HDIO_GET_DMA: 548 case HDIO_GET_NICE: 549 case HDIO_GET_WCACHE: 550 case HDIO_GET_ACOUSTIC: 551 case HDIO_GET_ADDRESS: 552 case HDIO_GET_BUSSTATE: 553 return compat_hdio_ioctl(bdev, mode, cmd, arg); 554 case FDSETPRM32: 555 case FDDEFPRM32: 556 case FDGETPRM32: 557 case FDSETDRVPRM32: 558 case FDGETDRVPRM32: 559 case FDGETDRVSTAT32: 560 case FDPOLLDRVSTAT32: 561 case FDGETFDCSTAT32: 562 case FDWERRORGET32: 563 return compat_fd_ioctl(bdev, mode, cmd, arg); 564 case CDROMREADAUDIO: 565 return compat_cdrom_read_audio(bdev, mode, cmd, arg); 566 case CDROM_SEND_PACKET: 567 return compat_cdrom_generic_command(bdev, mode, cmd, arg); 568 569 /* 570 * No handler required for the ones below, we just need to 571 * convert arg to a 64 bit pointer. 572 */ 573 case BLKSECTSET: 574 /* 575 * 0x03 -- HD/IDE ioctl's used by hdparm and friends. 576 * Some need translations, these do not. 577 */ 578 case HDIO_GET_IDENTITY: 579 case HDIO_DRIVE_TASK: 580 case HDIO_DRIVE_CMD: 581 /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ 582 case 0x330: 583 /* 0x02 -- Floppy ioctls */ 584 case FDMSGON: 585 case FDMSGOFF: 586 case FDSETEMSGTRESH: 587 case FDFLUSH: 588 case FDWERRORCLR: 589 case FDSETMAXERRS: 590 case FDGETMAXERRS: 591 case FDGETDRVTYP: 592 case FDEJECT: 593 case FDCLRPRM: 594 case FDFMTBEG: 595 case FDFMTEND: 596 case FDRESET: 597 case FDTWADDLE: 598 case FDFMTTRK: 599 case FDRAWCMD: 600 /* CDROM stuff */ 601 case CDROMPAUSE: 602 case CDROMRESUME: 603 case CDROMPLAYMSF: 604 case CDROMPLAYTRKIND: 605 case CDROMREADTOCHDR: 606 case CDROMREADTOCENTRY: 607 case CDROMSTOP: 608 case CDROMSTART: 609 case CDROMEJECT: 610 case CDROMVOLCTRL: 611 case CDROMSUBCHNL: 612 case CDROMMULTISESSION: 613 case CDROM_GET_MCN: 614 case CDROMRESET: 615 case CDROMVOLREAD: 616 case CDROMSEEK: 617 case CDROMPLAYBLK: 618 case CDROMCLOSETRAY: 619 case CDROM_DISC_STATUS: 620 case CDROM_CHANGER_NSLOTS: 621 case CDROM_GET_CAPABILITY: 622 /* Ignore cdrom.h about these next 5 ioctls, they absolutely do 623 * not take a struct cdrom_read, instead they take a struct cdrom_msf 624 * which is compatible. 625 */ 626 case CDROMREADMODE2: 627 case CDROMREADMODE1: 628 case CDROMREADRAW: 629 case CDROMREADCOOKED: 630 case CDROMREADALL: 631 /* DVD ioctls */ 632 case DVD_READ_STRUCT: 633 case DVD_WRITE_STRUCT: 634 case DVD_AUTH: 635 arg = (unsigned long)compat_ptr(arg); 636 /* These intepret arg as an unsigned long, not as a pointer, 637 * so we must not do compat_ptr() conversion. */ 638 case HDIO_SET_MULTCOUNT: 639 case HDIO_SET_UNMASKINTR: 640 case HDIO_SET_KEEPSETTINGS: 641 case HDIO_SET_32BIT: 642 case HDIO_SET_NOWERR: 643 case HDIO_SET_DMA: 644 case HDIO_SET_PIO_MODE: 645 case HDIO_SET_NICE: 646 case HDIO_SET_WCACHE: 647 case HDIO_SET_ACOUSTIC: 648 case HDIO_SET_BUSSTATE: 649 case HDIO_SET_ADDRESS: 650 case CDROMEJECT_SW: 651 case CDROM_SET_OPTIONS: 652 case CDROM_CLEAR_OPTIONS: 653 case CDROM_SELECT_SPEED: 654 case CDROM_SELECT_DISC: 655 case CDROM_MEDIA_CHANGED: 656 case CDROM_DRIVE_STATUS: 657 case CDROM_LOCKDOOR: 658 case CDROM_DEBUG: 659 break; 660 default: 661 /* unknown ioctl number */ 662 return -ENOIOCTLCMD; 663 } 664 665 return __blkdev_driver_ioctl(bdev, mode, cmd, arg); 666} 667 668/* Most of the generic ioctls are handled in the normal fallback path. 669 This assumes the blkdev's low level compat_ioctl always returns 670 ENOIOCTLCMD for unknown ioctls. */ 671long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 672{ 673 int ret = -ENOIOCTLCMD; 674 struct inode *inode = file->f_mapping->host; 675 struct block_device *bdev = inode->i_bdev; 676 struct gendisk *disk = bdev->bd_disk; 677 fmode_t mode = file->f_mode; 678 struct backing_dev_info *bdi; 679 loff_t size; 680 681 /* 682 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have 683 * to updated it before every ioctl. 684 */ 685 if (file->f_flags & O_NDELAY) 686 mode |= FMODE_NDELAY; 687 else 688 mode &= ~FMODE_NDELAY; 689 690 switch (cmd) { 691 case HDIO_GETGEO: 692 return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); 693 case BLKPBSZGET: 694 return compat_put_uint(arg, bdev_physical_block_size(bdev)); 695 case BLKIOMIN: 696 return compat_put_uint(arg, bdev_io_min(bdev)); 697 case BLKIOOPT: 698 return compat_put_uint(arg, bdev_io_opt(bdev)); 699 case BLKALIGNOFF: 700 return compat_put_int(arg, bdev_alignment_offset(bdev)); 701 case BLKDISCARDZEROES: 702 return compat_put_uint(arg, bdev_discard_zeroes_data(bdev)); 703 case BLKFLSBUF: 704 case BLKROSET: 705 case BLKDISCARD: 706 case BLKSECDISCARD: 707 /* 708 * the ones below are implemented in blkdev_locked_ioctl, 709 * but we call blkdev_ioctl, which gets the lock for us 710 */ 711 case BLKRRPART: 712 return blkdev_ioctl(bdev, mode, cmd, 713 (unsigned long)compat_ptr(arg)); 714 case BLKBSZSET_32: 715 return blkdev_ioctl(bdev, mode, BLKBSZSET, 716 (unsigned long)compat_ptr(arg)); 717 case BLKPG: 718 return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); 719 case BLKRAGET: 720 case BLKFRAGET: 721 if (!arg) 722 return -EINVAL; 723 bdi = blk_get_backing_dev_info(bdev); 724 if (bdi == NULL) 725 return -ENOTTY; 726 return compat_put_long(arg, 727 (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); 728 case BLKROGET: /* compatible */ 729 return compat_put_int(arg, bdev_read_only(bdev) != 0); 730 case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ 731 return compat_put_int(arg, block_size(bdev)); 732 case BLKSSZGET: /* get block device hardware sector size */ 733 return compat_put_int(arg, bdev_logical_block_size(bdev)); 734 case BLKSECTGET: 735 return compat_put_ushort(arg, 736 queue_max_sectors(bdev_get_queue(bdev))); 737 case BLKRASET: /* compatible, but no compat_ptr (!) */ 738 case BLKFRASET: 739 if (!capable(CAP_SYS_ADMIN)) 740 return -EACCES; 741 bdi = blk_get_backing_dev_info(bdev); 742 if (bdi == NULL) 743 return -ENOTTY; 744 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; 745 return 0; 746 case BLKGETSIZE: 747 size = bdev->bd_inode->i_size; 748 if ((size >> 9) > ~0UL) 749 return -EFBIG; 750 return compat_put_ulong(arg, size >> 9); 751 752 case BLKGETSIZE64_32: 753 return compat_put_u64(arg, bdev->bd_inode->i_size); 754 755 case BLKTRACESETUP32: 756 case BLKTRACESTART: /* compatible */ 757 case BLKTRACESTOP: /* compatible */ 758 case BLKTRACETEARDOWN: /* compatible */ 759 ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); 760 return ret; 761 default: 762 if (disk->fops->compat_ioctl) 763 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); 764 if (ret == -ENOIOCTLCMD) 765 ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); 766 return ret; 767 } 768} 769