Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ade36fe5 authored by Pranav Patel's avatar Pranav Patel Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarPranav Patel <pranavp@codeaurora.org>
Signed-off-by: default avatarAkhil P Oommen <akhilpo@codeaurora.org>
parent 756bbb25
Loading
Loading
Loading
Loading
+29 −41
Original line number Diff line number Diff line
@@ -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,10 +2093,7 @@ 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;
@@ -2127,14 +2117,12 @@ long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv,
			u64_to_user_ptr(generic.priv), generic.size);
		if (ret)
			goto err;

	} else {
		ret = -EINVAL;
		goto err;
	}

		cmdlist += param->cmdsize;
	}

	ret = device->ftbl->queue_cmds(dev_priv, context,
		drawobjs, index, &param->timestamp);