On Thu, 18 Oct 2018, Christoph Hellwig wrote:

> +
> +static int ioc_general(void __user *arg, char *cmnd)
> +{
> +     gdth_ioctl_general gen;
> +     gdth_ha_str *ha;
> +     char *buf = NULL;
> +     u64 paddr;
> +     int rval;
> +
> +     if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)))
> +             return -EFAULT;
> +     ha = gdth_find_ha(gen.ionode);
> +     if (!ha)
> +             return -EFAULT;
> +
> +     if (gen.data_len > INT_MAX)
> +             return -EINVAL;
> +     if (gen.sense_len > INT_MAX)
> +             return -EINVAL;
> +     if (gen.data_len + gen.sense_len > INT_MAX)
> +             return -EINVAL;
> +
> +     if (gen.data_len + gen.sense_len == 0)
> +             goto execute;
> +
> +     buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, FALSE, &paddr);
> +     if (!buf)
> +             return -EFAULT;
> +
> +     rval = -EFAULT;
> +     if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general),
> +                        gen.data_len + gen.sense_len))
> +             goto out_free_buf;
> +
> +     switch (gen.command.OpCode) {
> +     case GDT_IOCTL:
> +             gen.command.u.ioctl.p_param = paddr;
> +             break;
> +     case CACHESERVICE:
> +             gdth_ioc_cacheservice(ha, &gen, paddr);
> +             break;
> +     case SCSIRAWSERVICE:
> +             gdth_ioc_scsiraw(ha, &gen, paddr);
> +             break;
> +     default:
> +             goto out_free_buf;
>          }
> -    }

AFAICT, CACHESERVICE never gets assigned to command.OpCode.

That means your switch() is not equivalent to the original construction --

        if (gen.command.OpCode == GDT_IOCTL) {

        } else if (gen.command.Service == CACHESERVICE) {

        } else if (gen.command.Service == SCSIRAWSERVICE) {

        } else {

        }

>  
> -    rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, 
> &gen.info);
> -    if (rval < 0) {
> +execute:
> +     rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout,
> +                     &gen.info);
> +     if (rval < 0)
> +             goto out_free_buf;
> +     gen.status = rval;
> +
> +     rval = -EFAULT;
> +     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf,
> +                      gen.data_len + gen.sense_len))
> +             goto out_free_buf;
> +     if (copy_to_user(arg, &gen,
> +                     sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str)))
> +             goto out_free_buf;
> +
> +     rval = 0;
> +out_free_buf:
>       gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
> -        return rval;
> -    }
> -    gen.status = rval;
> -
> -    if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
> -                     gen.data_len + gen.sense_len)) {
> -        gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
> -        return -EFAULT; 
> -    } 
> -    if (copy_to_user(arg, &gen, 
> -        sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
> -        gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
> -        return -EFAULT;
> -    }
> -    gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
> -    return 0;
> +     return 0;

This appears to be wrong also. I think you wanted,
        return rval;

-- 

>  }
>   
>  static int ioc_hdrlist(void __user *arg, char *cmnd)
> 

Reply via email to