Re: [PATCH v2 3/6] tee: qcomtee: Allow object invokes from kernel clients
Harshal Dev via OP-TEE <[email protected]> Fri, 31 Jul 2026 13:08:56 +0530
| Newsgroups | org.trustedfirmware.lists.op-tee,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel |
|---|---|
| Organization | Qualcomm |
| Message-ID | <[email protected]> |
Hi Amir, On 29-07-2026 12:36 pm, Amirreza Zarrabi wrote: > 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. > Whoops, thank you for catching this. Ack, I will make this change. Regards, Harshal > - 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; >> }; >> >> >