mirror of https://gitee.com/openkylin/linux.git
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:
parent
cb17c1b69b
commit
10100ffd5f
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue