From ade36fe56383e46ba8aebd794e7fb624c03c838e Mon Sep 17 00:00:00 2001 From: Pranav Patel Date: Thu, 29 Apr 2021 19:45:24 +0530 Subject: [PATCH] msm: kgsl: check for number of commands in kgsl_ioctl_gpu_aux_command kgsl_ioctl_gpu_aux_command creates a separate drawobj for each command in numcmds sent from userspace. All drawbojs created will have same timestamp. We can not queue more than one drawobj with same timestamp. Each new drawobj must have timestamp greater than previously queued drawobjs. This results in failure of kgsl_ioctl_gpu_aux_command. Add proper check and return early when numcmds is invalid. Change-Id: I06413c16b0a21abcffb121b2e332752eb71e6be0 Signed-off-by: Pranav Patel Signed-off-by: Akhil P Oommen --- drivers/gpu/msm/kgsl.c | 70 +++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 4b0e1d13fa78..f932ae24d64c 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2025,34 +2025,27 @@ long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, u32 queued, count; int i, index = 0; long ret; + struct kgsl_gpu_aux_command_generic generic; - /* Aux commands don't make sense without commands */ - if (!param->numcmds) + /* We support only one aux command */ + if (param->numcmds != 1) return -EINVAL; if (!(param->flags & (KGSL_GPU_AUX_COMMAND_TIMELINE))) return -EINVAL; - /* - * Make sure we don't overflow count. Couple of drawobjs are reserved: - * One drawobj for timestamp sync and another for aux command sync. - */ - if (param->numcmds > (UINT_MAX - 2)) - return -EINVAL; - context = kgsl_context_get_owner(dev_priv, param->context_id); if (!context) return -EINVAL; /* - * We have one drawobj for the timestamp sync plus one for all of the - * commands + * param->numcmds is always one and we have one additional drawobj + * for the timestamp sync if KGSL_GPU_AUX_COMMAND_SYNC flag is passed. + * On top of that we make an implicit sync object for the last queued + * timestamp on this context. */ - count = param->numcmds + 1; - - if (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) - count++; + count = (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) ? 3 : 2; drawobjs = kvcalloc(count, sizeof(*drawobjs), GFP_KERNEL); @@ -2100,39 +2093,34 @@ long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, cmdlist = u64_to_user_ptr(param->cmdlist); - /* Create a draw object for each command */ - for (i = 0; i < param->numcmds; i++) { - struct kgsl_gpu_aux_command_generic generic; + /* Create a draw object for KGSL_GPU_AUX_COMMAND_TIMELINE */ + if (copy_struct_from_user(&generic, sizeof(generic), + cmdlist, param->cmdsize)) { + ret = -EFAULT; + goto err; + } - if (copy_struct_from_user(&generic, sizeof(generic), - cmdlist, param->cmdsize)) { - ret = -EFAULT; + if (generic.type == KGSL_GPU_AUX_COMMAND_TIMELINE) { + struct kgsl_drawobj_timeline *timelineobj; + + timelineobj = kgsl_drawobj_timeline_create(device, + context); + + if (IS_ERR(timelineobj)) { + ret = PTR_ERR(timelineobj); goto err; } - if (generic.type == KGSL_GPU_AUX_COMMAND_TIMELINE) { - struct kgsl_drawobj_timeline *timelineobj; + drawobjs[index++] = DRAWOBJ(timelineobj); - timelineobj = kgsl_drawobj_timeline_create(device, - context); - - if (IS_ERR(timelineobj)) { - ret = PTR_ERR(timelineobj); - goto err; - } - - drawobjs[index++] = DRAWOBJ(timelineobj); - - ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, - u64_to_user_ptr(generic.priv), generic.size); - if (ret) - goto err; - } else { - ret = -EINVAL; + ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, + u64_to_user_ptr(generic.priv), generic.size); + if (ret) goto err; - } - cmdlist += param->cmdsize; + } else { + ret = -EINVAL; + goto err; } ret = device->ftbl->queue_cmds(dev_priv, context,