mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF
The TEE subsystem allows session-based access to trusted services, requiring a session to be established to receive a service. This is not suitable for an environment that represents services as objects. An object supports various operations that a client can invoke, potentially generating a result or a new object that can be invoked independently of the original object. Add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT/OUTPUT/INOUT to represent an object. Objects may reside in either TEE or userspace. To invoke an object in TEE, introduce a new ioctl. Use the existing SUPPL_RECV and SUPPL_SEND to invoke an object in userspace. Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com> Tested-by: Neil Armstrong <neil.armstrong@linaro.org> Tested-by: Harshal Dev <quic_hdev@quicinc.com> Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
This commit is contained in:
committed by
Jens Wiklander
parent
54a53e95a9
commit
d5b8b0fa17
@@ -487,6 +487,7 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
|
||||
switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT:
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
|
||||
@@ -505,6 +506,11 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
|
||||
return -EFAULT;
|
||||
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT:
|
||||
params[n].u.objref.id = ip.a;
|
||||
params[n].u.objref.flags = ip.b;
|
||||
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:
|
||||
@@ -543,6 +549,12 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
|
||||
if (put_user((u64)p->u.ubuf.size, &up->b))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT:
|
||||
if (put_user(p->u.objref.id, &up->a) ||
|
||||
put_user(p->u.objref.flags, &up->b))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
if (put_user((u64)p->u.memref.size, &up->b))
|
||||
@@ -695,6 +707,66 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tee_ioctl_object_invoke(struct tee_context *ctx,
|
||||
struct tee_ioctl_buf_data __user *ubuf)
|
||||
{
|
||||
int rc;
|
||||
size_t n;
|
||||
struct tee_ioctl_buf_data buf;
|
||||
struct tee_ioctl_object_invoke_arg __user *uarg;
|
||||
struct tee_ioctl_object_invoke_arg arg;
|
||||
struct tee_ioctl_param __user *uparams = NULL;
|
||||
struct tee_param *params = NULL;
|
||||
|
||||
if (!ctx->teedev->desc->ops->object_invoke_func)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&buf, ubuf, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (buf.buf_len > TEE_MAX_ARG_SIZE ||
|
||||
buf.buf_len < sizeof(struct tee_ioctl_object_invoke_arg))
|
||||
return -EINVAL;
|
||||
|
||||
uarg = u64_to_user_ptr(buf.buf_ptr);
|
||||
if (copy_from_user(&arg, uarg, sizeof(arg)))
|
||||
return -EFAULT;
|
||||
|
||||
if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (arg.num_params) {
|
||||
params = kcalloc(arg.num_params, sizeof(struct tee_param),
|
||||
GFP_KERNEL);
|
||||
if (!params)
|
||||
return -ENOMEM;
|
||||
uparams = uarg->params;
|
||||
rc = params_from_user(ctx, params, arg.num_params, uparams);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
if (put_user(arg.ret, &uarg->ret)) {
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
rc = params_to_user(uparams, arg.num_params, params);
|
||||
out:
|
||||
if (params) {
|
||||
/* Decrease ref count for all valid shared memory pointers */
|
||||
for (n = 0; n < arg.num_params; n++)
|
||||
if (tee_param_is_memref(params + n) &&
|
||||
params[n].u.memref.shm)
|
||||
tee_shm_put(params[n].u.memref.shm);
|
||||
kfree(params);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tee_ioctl_cancel(struct tee_context *ctx,
|
||||
struct tee_ioctl_cancel_arg __user *uarg)
|
||||
{
|
||||
@@ -750,6 +822,12 @@ static int params_to_supp(struct tee_context *ctx,
|
||||
ip.b = p->u.ubuf.size;
|
||||
ip.c = 0;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT:
|
||||
ip.a = p->u.objref.id;
|
||||
ip.b = p->u.objref.flags;
|
||||
ip.c = 0;
|
||||
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:
|
||||
@@ -862,6 +940,11 @@ static int params_from_supp(struct tee_param *params, size_t num_params,
|
||||
return -EFAULT;
|
||||
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT:
|
||||
p->u.objref.id = ip.a;
|
||||
p->u.objref.flags = ip.b;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
/*
|
||||
@@ -944,6 +1027,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
return tee_ioctl_open_session(ctx, uarg);
|
||||
case TEE_IOC_INVOKE:
|
||||
return tee_ioctl_invoke(ctx, uarg);
|
||||
case TEE_IOC_OBJECT_INVOKE:
|
||||
return tee_ioctl_object_invoke(ctx, uarg);
|
||||
case TEE_IOC_CANCEL:
|
||||
return tee_ioctl_cancel(ctx, uarg);
|
||||
case TEE_IOC_CLOSE_SESSION:
|
||||
|
||||
Reference in New Issue
Block a user