diff options
Diffstat (limited to 'drivers/ide/ide-ioctls.c')
| -rw-r--r-- | drivers/ide/ide-ioctls.c | 47 | 
1 files changed, 31 insertions, 16 deletions
| diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index d48c17003874..09491098047b 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -3,11 +3,20 @@   * IDE ioctls handling.   */ +#include <linux/compat.h>  #include <linux/export.h>  #include <linux/hdreg.h>  #include <linux/ide.h>  #include <linux/slab.h> +static int put_user_long(long val, unsigned long arg) +{ +	if (in_compat_syscall()) +		return put_user(val, (compat_long_t __user *)compat_ptr(arg)); + +	return put_user(val, (long __user *)arg); +} +  static const struct ide_ioctl_devset ide_ioctl_settings[] = {  { HDIO_GET_32BIT,	 HDIO_SET_32BIT,	&ide_devset_io_32bit  },  { HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS,	&ide_devset_keepsettings }, @@ -37,7 +46,7 @@ read_val:  	mutex_lock(&ide_setting_mtx);  	err = ds->get(drive);  	mutex_unlock(&ide_setting_mtx); -	return err >= 0 ? put_user(err, (long __user *)arg) : err; +	return err >= 0 ? put_user_long(err, arg) : err;  set_val:  	if (bdev != bdev->bd_contains) @@ -56,7 +65,7 @@ set_val:  EXPORT_SYMBOL_GPL(ide_setting_ioctl);  static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, -				  unsigned long arg) +				  void __user *argp)  {  	u16 *id = NULL;  	int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; @@ -77,7 +86,7 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,  	memcpy(id, drive->id, size);  	ata_id_to_hd_driveid(id); -	if (copy_to_user((void __user *)arg, id, size)) +	if (copy_to_user(argp, id, size))  		rc = -EFAULT;  	kfree(id); @@ -87,10 +96,10 @@ out:  static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)  { -	return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) +	return put_user_long((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)  			 << IDE_NICE_DSC_OVERLAP) |  			(!!(drive->dev_flags & IDE_DFLAG_NICE1) -			 << IDE_NICE_1), (long __user *)arg); +			 << IDE_NICE_1), arg);  }  static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) @@ -115,7 +124,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)  	return 0;  } -static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) +static int ide_cmd_ioctl(ide_drive_t *drive, void __user *argp)  {  	u8 *buf = NULL;  	int bufsize = 0, err = 0; @@ -123,7 +132,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)  	struct ide_cmd cmd;  	struct ide_taskfile *tf = &cmd.tf; -	if (NULL == (void *) arg) { +	if (NULL == argp) {  		struct request *rq;  		rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0); @@ -135,7 +144,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)  		return err;  	} -	if (copy_from_user(args, (void __user *)arg, 4)) +	if (copy_from_user(args, argp, 4))  		return -EFAULT;  	memset(&cmd, 0, sizeof(cmd)); @@ -181,19 +190,18 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)  	args[1] = tf->error;  	args[2] = tf->nsect;  abort: -	if (copy_to_user((void __user *)arg, &args, 4)) +	if (copy_to_user(argp, &args, 4))  		err = -EFAULT;  	if (buf) { -		if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) +		if (copy_to_user((argp + 4), buf, bufsize))  			err = -EFAULT;  		kfree(buf);  	}  	return err;  } -static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) +static int ide_task_ioctl(ide_drive_t *drive, void __user *p)  { -	void __user *p = (void __user *)arg;  	int err = 0;  	u8 args[7];  	struct ide_cmd cmd; @@ -237,6 +245,10 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,  		      unsigned int cmd, unsigned long arg)  {  	int err; +	void __user *argp = (void __user *)arg; + +	if (in_compat_syscall()) +		argp = compat_ptr(arg);  	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);  	if (err != -EOPNOTSUPP) @@ -247,7 +259,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,  	case HDIO_GET_IDENTITY:  		if (bdev != bdev->bd_contains)  			return -EINVAL; -		return ide_get_identity_ioctl(drive, cmd, arg); +		return ide_get_identity_ioctl(drive, cmd, argp);  	case HDIO_GET_NICE:  		return ide_get_nice_ioctl(drive, arg);  	case HDIO_SET_NICE: @@ -258,6 +270,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,  	case HDIO_DRIVE_TASKFILE:  		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))  			return -EACCES; +		/* missing compat handler for HDIO_DRIVE_TASKFILE */ +		if (in_compat_syscall()) +			return -ENOTTY;  		if (drive->media == ide_disk)  			return ide_taskfile_ioctl(drive, arg);  		return -ENOMSG; @@ -265,11 +280,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,  	case HDIO_DRIVE_CMD:  		if (!capable(CAP_SYS_RAWIO))  			return -EACCES; -		return ide_cmd_ioctl(drive, arg); +		return ide_cmd_ioctl(drive, argp);  	case HDIO_DRIVE_TASK:  		if (!capable(CAP_SYS_RAWIO))  			return -EACCES; -		return ide_task_ioctl(drive, arg); +		return ide_task_ioctl(drive, argp);  	case HDIO_DRIVE_RESET:  		if (!capable(CAP_SYS_ADMIN))  			return -EACCES; @@ -277,7 +292,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,  	case HDIO_GET_BUSSTATE:  		if (!capable(CAP_SYS_ADMIN))  			return -EACCES; -		if (put_user(BUSSTATE_ON, (long __user *)arg)) +		if (put_user_long(BUSSTATE_ON, arg))  			return -EFAULT;  		return 0;  	case HDIO_SET_BUSSTATE: | 
