scsi: hpsa: Get rid of compat_alloc_user_space()

No need for building a native struct on kernel stack, copying it to
userland one, then calling hpsa_ioctl() which copies it back into _another_
instance of the same struct.

Link: https://lore.kernel.org/r/20200529234028.46373-3-viro@ZenIV.linux.org.uk
Acked-by: Don Brace <don.brace@microsemi.com>
Tested-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Al Viro 2020-05-30 00:40:27 +01:00 committed by Martin K. Petersen
parent cb17c1b69b
commit 10100ffd5f
1 changed files with 36 additions and 44 deletions

View File

@ -254,6 +254,10 @@ static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd, static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd,
void __user *arg); void __user *arg);
static int hpsa_passthru_ioctl(struct ctlr_info *h,
IOCTL_Command_struct *iocommand);
static int hpsa_big_passthru_ioctl(struct ctlr_info *h,
BIG_IOCTL_Command_struct *ioc);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd, static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd,
@ -6217,75 +6221,63 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c)
static int hpsa_ioctl32_passthru(struct scsi_device *dev, unsigned int cmd, static int hpsa_ioctl32_passthru(struct scsi_device *dev, unsigned int cmd,
void __user *arg) void __user *arg)
{ {
IOCTL32_Command_struct __user *arg32 = struct ctlr_info *h = sdev_to_hba(dev);
(IOCTL32_Command_struct __user *) arg; IOCTL32_Command_struct __user *arg32 = arg;
IOCTL_Command_struct arg64; IOCTL_Command_struct arg64;
IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
int err; int err;
u32 cp; u32 cp;
if (!arg)
return -EINVAL;
memset(&arg64, 0, sizeof(arg64)); memset(&arg64, 0, sizeof(arg64));
err = 0; if (copy_from_user(&arg64, arg32, offsetof(IOCTL_Command_struct, buf)))
err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, return -EFAULT;
sizeof(arg64.LUN_info)); if (get_user(cp, &arg32->buf))
err |= copy_from_user(&arg64.Request, &arg32->Request, return -EFAULT;
sizeof(arg64.Request));
err |= copy_from_user(&arg64.error_info, &arg32->error_info,
sizeof(arg64.error_info));
err |= get_user(arg64.buf_size, &arg32->buf_size);
err |= get_user(cp, &arg32->buf);
arg64.buf = compat_ptr(cp); arg64.buf = compat_ptr(cp);
err |= copy_to_user(p, &arg64, sizeof(arg64));
if (err) if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
return -EFAULT; return -EAGAIN;
err = hpsa_passthru_ioctl(h, &arg64);
err = hpsa_ioctl(dev, CCISS_PASSTHRU, p); atomic_inc(&h->passthru_cmds_avail);
if (err) if (err)
return err; return err;
err |= copy_in_user(&arg32->error_info, &p->error_info, if (copy_to_user(&arg32->error_info, &arg64.error_info,
sizeof(arg32->error_info)); sizeof(arg32->error_info)))
if (err)
return -EFAULT; return -EFAULT;
return err; return 0;
} }
static int hpsa_ioctl32_big_passthru(struct scsi_device *dev, static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
unsigned int cmd, void __user *arg) unsigned int cmd, void __user *arg)
{ {
BIG_IOCTL32_Command_struct __user *arg32 = struct ctlr_info *h = sdev_to_hba(dev);
(BIG_IOCTL32_Command_struct __user *) arg; BIG_IOCTL32_Command_struct __user *arg32 = arg;
BIG_IOCTL_Command_struct arg64; BIG_IOCTL_Command_struct arg64;
BIG_IOCTL_Command_struct __user *p =
compat_alloc_user_space(sizeof(arg64));
int err; int err;
u32 cp; u32 cp;
if (!arg)
return -EINVAL;
memset(&arg64, 0, sizeof(arg64)); memset(&arg64, 0, sizeof(arg64));
err = 0; if (copy_from_user(&arg64, arg32,
err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, offsetof(BIG_IOCTL32_Command_struct, buf)))
sizeof(arg64.LUN_info)); return -EFAULT;
err |= copy_from_user(&arg64.Request, &arg32->Request, if (get_user(cp, &arg32->buf))
sizeof(arg64.Request)); return -EFAULT;
err |= copy_from_user(&arg64.error_info, &arg32->error_info,
sizeof(arg64.error_info));
err |= get_user(arg64.buf_size, &arg32->buf_size);
err |= get_user(arg64.malloc_size, &arg32->malloc_size);
err |= get_user(cp, &arg32->buf);
arg64.buf = compat_ptr(cp); arg64.buf = compat_ptr(cp);
err |= copy_to_user(p, &arg64, sizeof(arg64));
if (err) if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
return -EFAULT; return -EAGAIN;
err = hpsa_big_passthru_ioctl(h, &arg64);
err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, p); atomic_inc(&h->passthru_cmds_avail);
if (err) if (err)
return err; return err;
err |= copy_in_user(&arg32->error_info, &p->error_info, if (copy_to_user(&arg32->error_info, &arg64.error_info,
sizeof(arg32->error_info)); sizeof(arg32->error_info)))
if (err)
return -EFAULT; return -EFAULT;
return err; return 0;
} }
static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd, static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd,