Skip to content

Commit a2264d2

Browse files
etienne-lmsfourmone
authored andcommitted
tee: OCALL support for kernel TEE client drivers
Enable Trusted Applications (TAs) to invoke functions on their corresponding client in Linux kernel driver during both both session open and command invocation. These function invocations from TA to client are referred to as "Out Calls", or OCALLs for short. The fundamental mechanism is one whereby upon a function invocation from the client to the TA, the TEE returns prematurely from the invocation with an RPC. This RPC is generated after a TA calls a TEEC_InvokeCommand() equivalent function in secure world. The RPC carries information describing the OCALL as well as its parameters. When this happens, the driver saves the state of the current call and returns to user-mode. The TEE kernel client API has to call tee_client_open_session() or tee_client_invoke_command() with a special parameter that carries OCALL information. When the function returns prematurely, this parameter includes information about what the client is expected to do on behalf of the TA along with data to be used to reply to the request. Once that is done, TEE kernel client API calls tee_client_open_session() (respectively tee_client_invoke_command()) again with the modified OCALL parameter and associated information (such as the result of the OCALL and the output parameters as requested by the TA). The driver notices that this invocation is in fact a resumption as opposed to a brand-new invocation, and resumes the secure world thread that sent the RPC in the first place. The same mechanism applies to OCALLs during session open. This patch also minimally updates the OP-TEE and AMD TEE drivers to match the new signatures for session open and invoke. If an OCALL is specified by the CA, EOPNOTSUPP is returned. This change it based on the OCALL implementation proposal from Hernan Gatta posted in [1] with few modifications to remove changes in shared memory from/to sequence since OCALL is not yet available to user client application, and to remove TEE drivers pre-release handler that are not needed when supporting OCalls only in Linux kernel TEE client drivers. Link: [1] linaro-swg/linux#72 Co-developed-by: Hernan Gatta <[email protected]> Signed-off-by: Hernan Gatta <[email protected]> Signed-off-by: Etienne Carriere <[email protected]> Change-Id: I95b35e2447bfb24b729d7bf1d3dec4cc620100e6
1 parent 9061b6f commit a2264d2

File tree

8 files changed

+165
-22
lines changed

8 files changed

+165
-22
lines changed

drivers/tee/amdtee/amdtee_private.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,17 @@ static inline u32 get_session_index(u32 session)
135135

136136
int amdtee_open_session(struct tee_context *ctx,
137137
struct tee_ioctl_open_session_arg *arg,
138-
struct tee_param *param);
138+
struct tee_param *normal_param,
139+
u32 num_normal_params,
140+
struct tee_param *ocall_param);
139141

140142
int amdtee_close_session(struct tee_context *ctx, u32 session);
141143

142144
int amdtee_invoke_func(struct tee_context *ctx,
143145
struct tee_ioctl_invoke_arg *arg,
144-
struct tee_param *param);
146+
struct tee_param *normal_param,
147+
u32 num_normal_params,
148+
struct tee_param *ocall_param);
145149

146150
int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
147151

drivers/tee/amdtee/core.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ static void destroy_session(struct kref *ref)
230230

231231
int amdtee_open_session(struct tee_context *ctx,
232232
struct tee_ioctl_open_session_arg *arg,
233-
struct tee_param *param)
233+
struct tee_param *normal_param,
234+
u32 num_normal_params,
235+
struct tee_param *ocall_param)
234236
{
235237
struct amdtee_context_data *ctxdata = ctx->data;
236238
struct amdtee_session *sess = NULL;
@@ -239,6 +241,11 @@ int amdtee_open_session(struct tee_context *ctx,
239241
int rc, i;
240242
void *ta;
241243

244+
if (ocall_param) {
245+
pr_err("OCALLs not supported\n");
246+
return -EOPNOTSUPP;
247+
}
248+
242249
if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {
243250
pr_err("unsupported client login method\n");
244251
return -EINVAL;
@@ -283,7 +290,7 @@ int amdtee_open_session(struct tee_context *ctx,
283290
}
284291

285292
/* Open session with loaded TA */
286-
handle_open_session(arg, &session_info, param);
293+
handle_open_session(arg, &session_info, normal_param);
287294
if (arg->ret != TEEC_SUCCESS) {
288295
pr_err("open_session failed %d\n", arg->ret);
289296
spin_lock(&sess->lock);
@@ -405,12 +412,19 @@ void amdtee_unmap_shmem(struct tee_shm *shm)
405412

406413
int amdtee_invoke_func(struct tee_context *ctx,
407414
struct tee_ioctl_invoke_arg *arg,
408-
struct tee_param *param)
415+
struct tee_param *normal_param,
416+
u32 num_normal_params,
417+
struct tee_param *ocall_param)
409418
{
410419
struct amdtee_context_data *ctxdata = ctx->data;
411420
struct amdtee_session *sess;
412421
u32 i, session_info;
413422

423+
if (ocall_param) {
424+
pr_err("OCALLs not supported\n");
425+
return -EOPNOTSUPP;
426+
}
427+
414428
/* Check that the session is valid */
415429
mutex_lock(&session_list_mutex);
416430
sess = find_session(ctxdata, arg->session);
@@ -423,7 +437,7 @@ int amdtee_invoke_func(struct tee_context *ctx,
423437
if (!sess)
424438
return -EINVAL;
425439

426-
handle_invoke_cmd(arg, session_info, param);
440+
handle_invoke_cmd(arg, session_info, normal_param);
427441

428442
return 0;
429443
}

drivers/tee/optee/call.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
127127

128128
int optee_open_session(struct tee_context *ctx,
129129
struct tee_ioctl_open_session_arg *arg,
130-
struct tee_param *param)
130+
struct tee_param *normal_param,
131+
u32 num_normal_params,
132+
struct tee_param *ocall_param)
131133
{
132134
struct optee_context_data *ctxdata = ctx->data;
133135
int rc;
@@ -137,6 +139,11 @@ int optee_open_session(struct tee_context *ctx,
137139
struct optee_session *sess = NULL;
138140
uuid_t client_uuid;
139141

142+
if (ocall_param) {
143+
pr_err("OCALLs not supported\n");
144+
return -EOPNOTSUPP;
145+
}
146+
140147
/* +2 for the meta parameters added below */
141148
shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
142149
if (IS_ERR(shm))
@@ -162,7 +169,8 @@ int optee_open_session(struct tee_context *ctx,
162169
goto out;
163170
export_uuid(msg_arg->params[1].u.octets, &client_uuid);
164171

165-
rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
172+
rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params,
173+
normal_param);
166174
if (rc)
167175
goto out;
168176

@@ -187,7 +195,8 @@ int optee_open_session(struct tee_context *ctx,
187195
kfree(sess);
188196
}
189197

190-
if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
198+
if (optee_from_msg_param(normal_param, arg->num_params,
199+
msg_arg->params + 2)) {
191200
arg->ret = TEEC_ERROR_COMMUNICATION;
192201
arg->ret_origin = TEEC_ORIGIN_COMMS;
193202
/* Close session again to avoid leakage */
@@ -234,7 +243,8 @@ int optee_close_session(struct tee_context *ctx, u32 session)
234243
}
235244

236245
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
237-
struct tee_param *param)
246+
struct tee_param *normal_param, u32 num_normal_params,
247+
struct tee_param *ocall_param)
238248
{
239249
struct optee_context_data *ctxdata = ctx->data;
240250
struct tee_shm *shm;
@@ -243,6 +253,11 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
243253
struct optee_session *sess;
244254
int rc;
245255

256+
if (ocall_param) {
257+
pr_err("OCALLs not supported\n");
258+
return -EOPNOTSUPP;
259+
}
260+
246261
/* Check that the session is valid */
247262
mutex_lock(&ctxdata->mutex);
248263
sess = find_session(ctxdata, arg->session);
@@ -258,7 +273,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
258273
msg_arg->session = arg->session;
259274
msg_arg->cancel_id = arg->cancel_id;
260275

261-
rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
276+
rc = optee_to_msg_param(msg_arg->params, arg->num_params, normal_param);
262277
if (rc)
263278
goto out;
264279

@@ -267,7 +282,8 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
267282
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
268283
}
269284

270-
if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
285+
if (optee_from_msg_param(normal_param, arg->num_params,
286+
msg_arg->params)) {
271287
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
272288
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
273289
}

drivers/tee/optee/optee_private.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,12 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
156156
u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
157157
int optee_open_session(struct tee_context *ctx,
158158
struct tee_ioctl_open_session_arg *arg,
159-
struct tee_param *param);
159+
struct tee_param *normal_param, u32 num_normal_params,
160+
struct tee_param *ocall_param);
160161
int optee_close_session(struct tee_context *ctx, u32 session);
161162
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
162-
struct tee_param *param);
163+
struct tee_param *normal_param, u32 num_normal_params,
164+
struct tee_param *ocall_param);
163165
int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
164166

165167
void optee_enable_shm_cache(struct optee *optee);

drivers/tee/tee_core.c

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ tee_ioctl_shm_register(struct tee_context *ctx,
352352
return ret;
353353
}
354354

355+
static bool param_is_ocall(struct tee_param *param)
356+
{
357+
u64 type = param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK;
358+
359+
return param->attr & TEE_IOCTL_PARAM_ATTR_OCALL &&
360+
type == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
361+
}
362+
355363
static int params_from_user(struct tee_context *ctx, struct tee_param *params,
356364
size_t num_params,
357365
struct tee_ioctl_param __user *uparams)
@@ -460,6 +468,33 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
460468
return 0;
461469
}
462470

471+
static inline int find_ocall_param(struct tee_param *params, u32 num_params,
472+
struct tee_param **normal_params,
473+
u32 *num_normal_params,
474+
struct tee_param **ocall_param)
475+
{
476+
size_t n;
477+
478+
for (n = 0; n < num_params; n++) {
479+
if (param_is_ocall(params + n)) {
480+
if (n == 0) {
481+
*normal_params = params + 1;
482+
*num_normal_params = num_params - 1;
483+
*ocall_param = params;
484+
return 0;
485+
} else {
486+
return -EINVAL;
487+
}
488+
}
489+
}
490+
491+
*normal_params = params;
492+
*num_normal_params = num_params;
493+
*ocall_param = NULL;
494+
495+
return 0;
496+
}
497+
463498
static int tee_ioctl_open_session(struct tee_context *ctx,
464499
struct tee_ioctl_buf_data __user *ubuf)
465500
{
@@ -507,7 +542,9 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
507542
goto out;
508543
}
509544

510-
rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params);
545+
rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params,
546+
arg.num_params,
547+
NULL /*ocall_param*/);
511548
if (rc)
512549
goto out;
513550
have_session = true;
@@ -578,7 +615,9 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
578615
goto out;
579616
}
580617

581-
rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params);
618+
rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params,
619+
arg.num_params,
620+
NULL /*ocall_param*/);
582621
if (rc)
583622
goto out;
584623

@@ -1155,9 +1194,22 @@ int tee_client_open_session(struct tee_context *ctx,
11551194
struct tee_ioctl_open_session_arg *arg,
11561195
struct tee_param *param)
11571196
{
1197+
struct tee_param *ocall_param = NULL;
1198+
struct tee_param *normal_params = NULL;
1199+
u32 num_normal_params = 0;
1200+
int rc;
1201+
11581202
if (!ctx->teedev->desc->ops->open_session)
11591203
return -EINVAL;
1160-
return ctx->teedev->desc->ops->open_session(ctx, arg, param);
1204+
1205+
rc = find_ocall_param(param, arg->num_params, &normal_params,
1206+
&num_normal_params, &ocall_param);
1207+
if (rc)
1208+
return rc;
1209+
1210+
return ctx->teedev->desc->ops->open_session(ctx, arg, normal_params,
1211+
num_normal_params,
1212+
ocall_param);
11611213
}
11621214
EXPORT_SYMBOL_GPL(tee_client_open_session);
11631215

@@ -1173,9 +1225,22 @@ int tee_client_invoke_func(struct tee_context *ctx,
11731225
struct tee_ioctl_invoke_arg *arg,
11741226
struct tee_param *param)
11751227
{
1228+
struct tee_param *ocall_param = NULL;
1229+
struct tee_param *normal_params = NULL;
1230+
u32 num_normal_params = 0;
1231+
int rc;
1232+
11761233
if (!ctx->teedev->desc->ops->invoke_func)
11771234
return -EINVAL;
1178-
return ctx->teedev->desc->ops->invoke_func(ctx, arg, param);
1235+
1236+
rc = find_ocall_param(param, arg->num_params, &normal_params,
1237+
&num_normal_params, &ocall_param);
1238+
if (rc)
1239+
return rc;
1240+
1241+
return ctx->teedev->desc->ops->invoke_func(ctx, arg, normal_params,
1242+
num_normal_params,
1243+
ocall_param);
11791244
}
11801245
EXPORT_SYMBOL_GPL(tee_client_invoke_func);
11811246

drivers/tee/tee_shm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
157157
int num_pages;
158158
unsigned long start;
159159

160-
if (flags != req_user_flags && flags != req_kernel_flags)
160+
if (((flags & req_user_flags) != req_user_flags) &&
161+
((flags & req_kernel_flags) != req_kernel_flags))
161162
return ERR_PTR(-ENOTSUPP);
162163

163164
if (!tee_device_get(teedev))

include/linux/tee_drv.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ struct tee_shm_pool;
5050
* non-blocking in nature.
5151
* @cap_memref_null: flag indicating if the TEE Client support shared
5252
* memory buffer with a NULL pointer.
53+
* @cap_ocall: flag indicating that OP-TEE supports OCALLs, allowing TAs
54+
* to invoke commands on their CA.
5355
*/
5456
struct tee_context {
5557
struct tee_device *teedev;
@@ -58,6 +60,7 @@ struct tee_context {
5860
bool releasing;
5961
bool supp_nowait;
6062
bool cap_memref_null;
63+
bool cap_ocall;
6164
};
6265

6366
struct tee_param_memref {
@@ -101,11 +104,15 @@ struct tee_driver_ops {
101104
void (*release)(struct tee_context *ctx);
102105
int (*open_session)(struct tee_context *ctx,
103106
struct tee_ioctl_open_session_arg *arg,
104-
struct tee_param *param);
107+
struct tee_param *normal_param,
108+
u32 num_normal_params,
109+
struct tee_param *ocall_param);
105110
int (*close_session)(struct tee_context *ctx, u32 session);
106111
int (*invoke_func)(struct tee_context *ctx,
107112
struct tee_ioctl_invoke_arg *arg,
108-
struct tee_param *param);
113+
struct tee_param *normal_param,
114+
u32 num_normal_params,
115+
struct tee_param *ocall_param);
109116
int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session);
110117
int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params,
111118
struct tee_param *param);

0 commit comments

Comments
 (0)