Commit fdf631ac authored by Jens Wiklander's avatar Jens Wiklander
Browse files

tee: refactor params_from_user()



Break out the memref handling into a separate helper function.
No change in behavior.

Reviewed-by: default avatarSumit Garg <sumit.garg@oss.qualcomm.com>
Signed-off-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
parent c924c65f
Loading
Loading
Loading
Loading
+54 −40
Original line number Diff line number Diff line
@@ -354,43 +354,18 @@ tee_ioctl_shm_register(struct tee_context *ctx,
	return ret;
}

static int params_from_user(struct tee_context *ctx, struct tee_param *params,
			    size_t num_params,
			    struct tee_ioctl_param __user *uparams)
static int param_from_user_memref(struct tee_context *ctx,
				  struct tee_param_memref *memref,
				  struct tee_ioctl_param *ip)
{
	size_t n;

	for (n = 0; n < num_params; n++) {
	struct tee_shm *shm;
		struct tee_ioctl_param ip;

		if (copy_from_user(&ip, uparams + n, sizeof(ip)))
			return -EFAULT;

		/* All unused attribute bits has to be zero */
		if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
			return -EINVAL;

		params[n].attr = ip.attr;
		switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
			break;
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
			params[n].u.value.a = ip.a;
			params[n].u.value.b = ip.b;
			params[n].u.value.c = ip.c;
			break;
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
	/*
	 * If a NULL pointer is passed to a TA in the TEE,
	 * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
	 * indicating a NULL memory reference.
	 */
			if (ip.c != TEE_MEMREF_NULL) {
	if (ip->c != TEE_MEMREF_NULL) {
		/*
		 * If we fail to get a pointer to a shared
		 * memory object (and increase the ref count)
@@ -400,7 +375,7 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
		 * responibility to do tee_shm_put() on all
		 * resolved pointers.
		 */
				shm = tee_shm_get_from_id(ctx, ip.c);
		shm = tee_shm_get_from_id(ctx, ip->c);
		if (IS_ERR(shm))
			return PTR_ERR(shm);

@@ -409,8 +384,8 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
		 * offset and does not overflow the size of
		 * the referred shared memory object.
		 */
				if ((ip.a + ip.b) < ip.a ||
				    (ip.a + ip.b) > shm->size) {
		if ((ip->a + ip->b) < ip->a ||
		    (ip->a + ip->b) > shm->size) {
			tee_shm_put(shm);
			return -EINVAL;
		}
@@ -421,9 +396,48 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
		return -EINVAL;
	}

			params[n].u.memref.shm_offs = ip.a;
			params[n].u.memref.size = ip.b;
			params[n].u.memref.shm = shm;
	memref->shm_offs = ip->a;
	memref->size = ip->b;
	memref->shm = shm;

	return 0;
}

static int params_from_user(struct tee_context *ctx, struct tee_param *params,
			    size_t num_params,
			    struct tee_ioctl_param __user *uparams)
{
	size_t n;

	for (n = 0; n < num_params; n++) {
		struct tee_ioctl_param ip;
		int rc;

		if (copy_from_user(&ip, uparams + n, sizeof(ip)))
			return -EFAULT;

		/* All unused attribute bits has to be zero */
		if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
			return -EINVAL;

		params[n].attr = ip.attr;
		switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
			break;
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
			params[n].u.value.a = ip.a;
			params[n].u.value.b = ip.b;
			params[n].u.value.c = ip.c;
			break;
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
			rc = param_from_user_memref(ctx, &params[n].u.memref,
						    &ip);
			if (rc)
				return rc;
			break;
		default:
			/* Unknown attribute */