Re: [PATCH v2 3/6] tee: qcomtee: Allow object invokes from kernel clients
Amirreza Zarrabi via OP-TEE <[email protected]> Wed, 29 Jul 2026 17:06:02 +1000
| Newsgroups | org.trustedfirmware.lists.op-tee,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi Harshal, On 7/22/2026 4:59 PM, Harshal Dev wrote: > From: Amirreza Zarrabi <[email protected]> > > QCOMTEE currently treats UBUF parameters as userspace addresses and > applies userspace restrictions when invoking the root object. This is > not suitable for object invocation requests issued by kernel clients. > > Use the kernel_ctx flag to distinguish kernel client requests from > userspace requests. For kernel contexts, do not mark UBUF parameters as > user addresses, and allow permitted root-object operations to proceed > without applying the userspace-only checks. > > This allows in-kernel users of tee_client_object_invoke_func() to issue > object invocation requests through the qcomtee backend. > > Co-developed-by: Harshal Dev <[email protected]> > Signed-off-by: Harshal Dev <[email protected]> > Signed-off-by: Amirreza Zarrabi <[email protected]> > --- > drivers/tee/qcomtee/call.c | 34 +++++++++++++++++++++++----------- > drivers/tee/qcomtee/qcomtee_object.h | 5 +++-- > include/linux/tee_drv.h | 5 ++++- > 3 files changed, 30 insertions(+), 14 deletions(-) > > diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c > index 03d33b118f6d..c1bba5fbfa3e 100644 > --- a/drivers/tee/qcomtee/call.c > +++ b/drivers/tee/qcomtee/call.c > @@ -202,7 +202,7 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg, > */ > static int qcomtee_params_to_args(struct qcomtee_arg *u, > struct tee_param *params, int num_params, > - struct tee_context *ctx) > + struct qcomtee_object_invoke_ctx *oic) > { > int i; > > @@ -210,8 +210,14 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, > switch (params[i].attr) { > case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT: > case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT: > - u[i].flags = QCOMTEE_ARG_FLAGS_UADDR; > - u[i].b.uaddr = params[i].u.ubuf.uaddr; > + u[i].flags = oic->kernel_ctx ? 0 : > + QCOMTEE_ARG_FLAGS_UADDR; > + > + if (u[i].flags && QCOMTEE_ARG_FLAGS_UADDR) > + u[i].b.uaddr = params[i].u.ubuf.uaddr; > + else > + u[i].b.addr = params[i].u.ubuf.addr; > + it is & not &&. Rather than ?:, can you have single if and update both flags and addr/uaddr. - Amir > u[i].b.size = params[i].u.ubuf.size; > > if (params[i].attr == > @@ -223,7 +229,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, > break; > case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: > u[i].type = QCOMTEE_ARG_TYPE_IO; > - if (qcomtee_objref_to_arg(&u[i], ¶ms[i], ctx)) > + if (qcomtee_objref_to_arg(&u[i], ¶ms[i], oic->ctx)) > goto out_failed; > > break; > @@ -270,7 +276,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, > */ > static int qcomtee_params_from_args(struct tee_param *params, > struct qcomtee_arg *u, int num_params, > - struct tee_context *ctx) > + struct qcomtee_object_invoke_ctx *oic) > { > int i, np; > > @@ -288,7 +294,8 @@ static int qcomtee_params_from_args(struct tee_param *params, > break; > case QCOMTEE_ARG_TYPE_OO: > /* TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT */ > - if (qcomtee_objref_from_arg(¶ms[np], &u[np], ctx)) > + if (qcomtee_objref_from_arg(¶ms[np], &u[np], > + oic->ctx)) > goto out_failed; > > break; > @@ -304,7 +311,7 @@ static int qcomtee_params_from_args(struct tee_param *params, > /* Undo qcomtee_objref_from_arg(). */ > for (i = 0; i < np; i++) { > if (params[i].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT) > - qcomtee_context_del_qtee_object(¶ms[i], ctx); > + qcomtee_context_del_qtee_object(¶ms[i], oic->ctx); > } > > /* Release any IO and OO objects not processed. */ > @@ -357,7 +364,8 @@ static int qcomtee_params_check(struct tee_param *params, int num_params) > } > > /* Check if an operation on ROOT_QCOMTEE_OBJECT from userspace is permitted. */ > -static int qcomtee_root_object_check(u32 op, struct tee_param *params, > +static int qcomtee_root_object_check(struct qcomtee_object_invoke_ctx *oic, > + u32 op, struct tee_param *params, > int num_params) > { > /* Some privileged operations recognized by QTEE. */ > @@ -366,6 +374,9 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params, > op == QCOMTEE_ROOT_OP_ADCI_SHUTDOWN) > return -EINVAL; > > + if (oic->kernel_ctx) > + return 0; > + > /* > * QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS is to register with QTEE > * by passing a credential object as input OBJREF. TEE_OBJREF_NULL as a > @@ -429,7 +440,8 @@ static int qcomtee_object_invoke(struct tee_context *ctx, > /* Get an object to invoke. */ > if (arg->id == TEE_OBJREF_NULL) { > /* Use ROOT if TEE_OBJREF_NULL is invoked. */ > - if (qcomtee_root_object_check(arg->op, params, arg->num_params)) > + if (qcomtee_root_object_check(oic, arg->op, params, > + arg->num_params)) > return -EINVAL; > > object = ROOT_QCOMTEE_OBJECT; > @@ -437,7 +449,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx, > return -EINVAL; > } > > - ret = qcomtee_params_to_args(u, params, arg->num_params, ctx); > + ret = qcomtee_params_to_args(u, params, arg->num_params, oic); > if (ret) > goto out; > > @@ -455,7 +467,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx, > > if (!result) { > /* Assume service is UNAVAIL if unable to process the result. */ > - if (qcomtee_params_from_args(params, u, arg->num_params, ctx)) > + if (qcomtee_params_from_args(params, u, arg->num_params, oic)) > result = QCOMTEE_MSG_ERROR_UNAVAIL; > } else { > /* > diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h > index 2528d07e4576..7bd6e23b038c 100644 > --- a/drivers/tee/qcomtee/qcomtee_object.h > +++ b/drivers/tee/qcomtee/qcomtee_object.h > @@ -112,8 +112,9 @@ struct qcomtee_buffer { > * @b: address and size if the type of argument is a buffer. > * @o: object instance if the type of argument is an object. > * > - * &qcomtee_arg.flags only accepts %QCOMTEE_ARG_FLAGS_UADDR for now, which > - * states that &qcomtee_arg.b contains a userspace address in uaddr. > ++ * If %QCOMTEE_ARG_FLAGS_UADDR is set in &qcomtee_arg.flags then it implies > ++ * that &qcomtee_arg.b contains a userspace address in uaddr. > ++ * Otherwise, &qcomtee_arg.b contains a kernel address in addr. > */ > struct qcomtee_arg { > enum qcomtee_arg_type type; > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h > index ca99c6b747a8..71d0536db60e 100644 > --- a/include/linux/tee_drv.h > +++ b/include/linux/tee_drv.h > @@ -83,7 +83,10 @@ struct tee_param_memref { > }; > > struct tee_param_ubuf { > - void __user *uaddr; > + union { > + void *addr; > + void __user *uaddr; > + }; > size_t size; > }; > >