Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

compat_ioctl: move HDIO ioctl handling into drivers/ide

Most of the HDIO ioctls are only used by the obsolete drivers/ide
subsystem, these can be handled by changing ide_cmd_ioctl() to be aware
of compat mode and doing the correct transformations in place and using
it as both native and compat handlers for all drivers.

The SCSI drivers implementing the same commands are already doing
this in the drivers, so the compat_blkdev_driver_ioctl() function
is no longer needed now.

The BLKSECTSET and HDIO_GETGEO_BIG ioctls are not implemented
in any driver any more and no longer need any conversion.

Reviewed-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+54 -102
-75
block/compat_ioctl.c
··· 78 78 return ret; 79 79 } 80 80 81 - static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, 82 - unsigned int cmd, unsigned long arg) 83 - { 84 - unsigned long __user *p; 85 - int error; 86 - 87 - p = compat_alloc_user_space(sizeof(unsigned long)); 88 - error = __blkdev_driver_ioctl(bdev, mode, 89 - cmd, (unsigned long)p); 90 - if (error == 0) { 91 - unsigned int __user *uvp = compat_ptr(arg); 92 - unsigned long v; 93 - if (get_user(v, p) || put_user(v, uvp)) 94 - error = -EFAULT; 95 - } 96 - return error; 97 - } 98 - 99 81 struct compat_blkpg_ioctl_arg { 100 82 compat_int_t op; 101 83 compat_int_t flags; ··· 110 128 #define BLKBSZGET_32 _IOR(0x12, 112, int) 111 129 #define BLKBSZSET_32 _IOW(0x12, 113, int) 112 130 #define BLKGETSIZE64_32 _IOR(0x12, 114, int) 113 - 114 - static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, 115 - unsigned cmd, unsigned long arg) 116 - { 117 - switch (cmd) { 118 - case HDIO_GET_UNMASKINTR: 119 - case HDIO_GET_MULTCOUNT: 120 - case HDIO_GET_KEEPSETTINGS: 121 - case HDIO_GET_32BIT: 122 - case HDIO_GET_NOWERR: 123 - case HDIO_GET_DMA: 124 - case HDIO_GET_NICE: 125 - case HDIO_GET_WCACHE: 126 - case HDIO_GET_ACOUSTIC: 127 - case HDIO_GET_ADDRESS: 128 - case HDIO_GET_BUSSTATE: 129 - return compat_hdio_ioctl(bdev, mode, cmd, arg); 130 - 131 - /* 132 - * No handler required for the ones below, we just need to 133 - * convert arg to a 64 bit pointer. 134 - */ 135 - case BLKSECTSET: 136 - /* 137 - * 0x03 -- HD/IDE ioctl's used by hdparm and friends. 138 - * Some need translations, these do not. 139 - */ 140 - case HDIO_GET_IDENTITY: 141 - case HDIO_DRIVE_TASK: 142 - case HDIO_DRIVE_CMD: 143 - /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ 144 - case 0x330: 145 - arg = (unsigned long)compat_ptr(arg); 146 - /* These intepret arg as an unsigned long, not as a pointer, 147 - * so we must not do compat_ptr() conversion. */ 148 - case HDIO_SET_MULTCOUNT: 149 - case HDIO_SET_UNMASKINTR: 150 - case HDIO_SET_KEEPSETTINGS: 151 - case HDIO_SET_32BIT: 152 - case HDIO_SET_NOWERR: 153 - case HDIO_SET_DMA: 154 - case HDIO_SET_PIO_MODE: 155 - case HDIO_SET_NICE: 156 - case HDIO_SET_WCACHE: 157 - case HDIO_SET_ACOUSTIC: 158 - case HDIO_SET_BUSSTATE: 159 - case HDIO_SET_ADDRESS: 160 - break; 161 - default: 162 - /* unknown ioctl number */ 163 - return -ENOIOCTLCMD; 164 - } 165 - 166 - return __blkdev_driver_ioctl(bdev, mode, cmd, arg); 167 - } 168 131 169 132 /* Most of the generic ioctls are handled in the normal fallback path. 170 133 This assumes the blkdev's low level compat_ioctl always returns ··· 221 294 default: 222 295 if (disk->fops->compat_ioctl) 223 296 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); 224 - if (ret == -ENOIOCTLCMD) 225 - ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); 226 297 return ret; 227 298 } 228 299 }
+8 -7
drivers/ide/ide-cd.c
··· 1711 1711 return ret; 1712 1712 } 1713 1713 1714 - #ifdef CONFIG_COMPAT 1715 1714 static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode, 1716 1715 unsigned int cmd, unsigned long arg) 1717 1716 { ··· 1727 1728 break; 1728 1729 } 1729 1730 1730 - return cdrom_ioctl(&info->devinfo, bdev, mode, cmd, 1731 - (unsigned long)argp); 1731 + err = generic_ide_ioctl(info->drive, bdev, cmd, arg); 1732 + if (err == -EINVAL) 1733 + err = cdrom_ioctl(&info->devinfo, bdev, mode, cmd, 1734 + (unsigned long)argp); 1735 + 1736 + return err; 1732 1737 } 1733 1738 1734 1739 static int idecd_compat_ioctl(struct block_device *bdev, fmode_t mode, ··· 1746 1743 1747 1744 return ret; 1748 1745 } 1749 - #endif 1750 1746 1751 1747 static unsigned int idecd_check_events(struct gendisk *disk, 1752 1748 unsigned int clearing) ··· 1768 1766 .open = idecd_open, 1769 1767 .release = idecd_release, 1770 1768 .ioctl = idecd_ioctl, 1771 - #ifdef CONFIG_COMPAT 1772 - .compat_ioctl = idecd_compat_ioctl, 1773 - #endif 1769 + .compat_ioctl = IS_ENABLED(CONFIG_COMPAT) ? 1770 + idecd_compat_ioctl : NULL, 1774 1771 .check_events = idecd_check_events, 1775 1772 .revalidate_disk = idecd_revalidate_disk 1776 1773 };
+1
drivers/ide/ide-disk.c
··· 794 794 .set_doorlock = ide_disk_set_doorlock, 795 795 .do_request = ide_do_rw_disk, 796 796 .ioctl = ide_disk_ioctl, 797 + .compat_ioctl = ide_disk_ioctl, 797 798 };
+3 -4
drivers/ide/ide-floppy_ioctl.c
··· 329 329 if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) 330 330 err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); 331 331 332 - /* 333 - * there is no generic_ide_compat_ioctl(), that is handled 334 - * through compat_blkdev_ioctl(). 335 - */ 332 + if (err == -ENOTTY) 333 + err = generic_ide_ioctl(drive, bdev, cmd, arg); 334 + 336 335 out: 337 336 mutex_unlock(&ide_floppy_ioctl_mutex); 338 337 return err;
+31 -16
drivers/ide/ide-ioctls.c
··· 3 3 * IDE ioctls handling. 4 4 */ 5 5 6 + #include <linux/compat.h> 6 7 #include <linux/export.h> 7 8 #include <linux/hdreg.h> 8 9 #include <linux/ide.h> 9 10 #include <linux/slab.h> 11 + 12 + static int put_user_long(long val, unsigned long arg) 13 + { 14 + if (in_compat_syscall()) 15 + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); 16 + 17 + return put_user(val, (long __user *)arg); 18 + } 10 19 11 20 static const struct ide_ioctl_devset ide_ioctl_settings[] = { 12 21 { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, ··· 46 37 mutex_lock(&ide_setting_mtx); 47 38 err = ds->get(drive); 48 39 mutex_unlock(&ide_setting_mtx); 49 - return err >= 0 ? put_user(err, (long __user *)arg) : err; 40 + return err >= 0 ? put_user_long(err, arg) : err; 50 41 51 42 set_val: 52 43 if (bdev != bdev->bd_contains) ··· 65 56 EXPORT_SYMBOL_GPL(ide_setting_ioctl); 66 57 67 58 static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, 68 - unsigned long arg) 59 + void __user *argp) 69 60 { 70 61 u16 *id = NULL; 71 62 int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; ··· 86 77 memcpy(id, drive->id, size); 87 78 ata_id_to_hd_driveid(id); 88 79 89 - if (copy_to_user((void __user *)arg, id, size)) 80 + if (copy_to_user(argp, id, size)) 90 81 rc = -EFAULT; 91 82 92 83 kfree(id); ··· 96 87 97 88 static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) 98 89 { 99 - return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) 90 + return put_user_long((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) 100 91 << IDE_NICE_DSC_OVERLAP) | 101 92 (!!(drive->dev_flags & IDE_DFLAG_NICE1) 102 - << IDE_NICE_1), (long __user *)arg); 93 + << IDE_NICE_1), arg); 103 94 } 104 95 105 96 static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) ··· 124 115 return 0; 125 116 } 126 117 127 - static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) 118 + static int ide_cmd_ioctl(ide_drive_t *drive, void __user *argp) 128 119 { 129 120 u8 *buf = NULL; 130 121 int bufsize = 0, err = 0; ··· 132 123 struct ide_cmd cmd; 133 124 struct ide_taskfile *tf = &cmd.tf; 134 125 135 - if (NULL == (void *) arg) { 126 + if (NULL == argp) { 136 127 struct request *rq; 137 128 138 129 rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0); ··· 144 135 return err; 145 136 } 146 137 147 - if (copy_from_user(args, (void __user *)arg, 4)) 138 + if (copy_from_user(args, argp, 4)) 148 139 return -EFAULT; 149 140 150 141 memset(&cmd, 0, sizeof(cmd)); ··· 190 181 args[1] = tf->error; 191 182 args[2] = tf->nsect; 192 183 abort: 193 - if (copy_to_user((void __user *)arg, &args, 4)) 184 + if (copy_to_user(argp, &args, 4)) 194 185 err = -EFAULT; 195 186 if (buf) { 196 - if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) 187 + if (copy_to_user((argp + 4), buf, bufsize)) 197 188 err = -EFAULT; 198 189 kfree(buf); 199 190 } 200 191 return err; 201 192 } 202 193 203 - static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) 194 + static int ide_task_ioctl(ide_drive_t *drive, void __user *p) 204 195 { 205 - void __user *p = (void __user *)arg; 206 196 int err = 0; 207 197 u8 args[7]; 208 198 struct ide_cmd cmd; ··· 245 237 unsigned int cmd, unsigned long arg) 246 238 { 247 239 int err; 240 + void __user *argp = (void __user *)arg; 241 + 242 + if (in_compat_syscall()) 243 + argp = compat_ptr(arg); 248 244 249 245 err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); 250 246 if (err != -EOPNOTSUPP) ··· 259 247 case HDIO_GET_IDENTITY: 260 248 if (bdev != bdev->bd_contains) 261 249 return -EINVAL; 262 - return ide_get_identity_ioctl(drive, cmd, arg); 250 + return ide_get_identity_ioctl(drive, cmd, argp); 263 251 case HDIO_GET_NICE: 264 252 return ide_get_nice_ioctl(drive, arg); 265 253 case HDIO_SET_NICE: ··· 270 258 case HDIO_DRIVE_TASKFILE: 271 259 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 272 260 return -EACCES; 261 + /* missing compat handler for HDIO_DRIVE_TASKFILE */ 262 + if (in_compat_syscall()) 263 + return -ENOTTY; 273 264 if (drive->media == ide_disk) 274 265 return ide_taskfile_ioctl(drive, arg); 275 266 return -ENOMSG; ··· 280 265 case HDIO_DRIVE_CMD: 281 266 if (!capable(CAP_SYS_RAWIO)) 282 267 return -EACCES; 283 - return ide_cmd_ioctl(drive, arg); 268 + return ide_cmd_ioctl(drive, argp); 284 269 case HDIO_DRIVE_TASK: 285 270 if (!capable(CAP_SYS_RAWIO)) 286 271 return -EACCES; 287 - return ide_task_ioctl(drive, arg); 272 + return ide_task_ioctl(drive, argp); 288 273 case HDIO_DRIVE_RESET: 289 274 if (!capable(CAP_SYS_ADMIN)) 290 275 return -EACCES; ··· 292 277 case HDIO_GET_BUSSTATE: 293 278 if (!capable(CAP_SYS_ADMIN)) 294 279 return -EACCES; 295 - if (put_user(BUSSTATE_ON, (long __user *)arg)) 280 + if (put_user_long(BUSSTATE_ON, arg)) 296 281 return -EFAULT; 297 282 return 0; 298 283 case HDIO_SET_BUSSTATE:
+11
drivers/ide/ide-tape.c
··· 1945 1945 return err; 1946 1946 } 1947 1947 1948 + static int idetape_compat_ioctl(struct block_device *bdev, fmode_t mode, 1949 + unsigned int cmd, unsigned long arg) 1950 + { 1951 + if (cmd == 0x0340 || cmd == 0x350) 1952 + arg = (unsigned long)compat_ptr(arg); 1953 + 1954 + return idetape_ioctl(bdev, mode, cmd, arg); 1955 + } 1956 + 1948 1957 static const struct block_device_operations idetape_block_ops = { 1949 1958 .owner = THIS_MODULE, 1950 1959 .open = idetape_open, 1951 1960 .release = idetape_release, 1952 1961 .ioctl = idetape_ioctl, 1962 + .compat_ioctl = IS_ENABLED(CONFIG_COMPAT) ? 1963 + idetape_compat_ioctl : NULL, 1953 1964 }; 1954 1965 1955 1966 static int ide_tape_probe(ide_drive_t *drive)