summaryrefslogtreecommitdiff
path: root/drivers/ide/ide-ioctls.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-ioctls.c')
-rw-r--r--drivers/ide/ide-ioctls.c47
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: