1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * Copyright (c) 2015, Linaro Limited 5 * Copyright (c) 2020, Arm Limited 6 */ 7 #include <initcall.h> 8 #include <kernel/linker.h> 9 #include <kernel/panic.h> 10 #include <kernel/pseudo_ta.h> 11 #include <kernel/tee_ta_manager.h> 12 #include <kernel/user_access.h> 13 #include <mm/core_memprot.h> 14 #include <mm/mobj.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <trace.h> 18 #include <types_ext.h> 19 20 #ifdef CFG_SECURE_DATA_PATH 21 static bool client_is_secure(struct ts_session *s) 22 { 23 /* rely on core entry to have constrained client IDs */ 24 if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) 25 return true; 26 27 return false; 28 } 29 30 static bool validate_in_param(struct ts_session *s, struct mobj *mobj) 31 { 32 /* Supplying NULL to query buffer size is OK */ 33 if (!mobj) 34 return true; 35 36 /* for secure clients, core entry always holds valid memref objects */ 37 if (client_is_secure(s)) 38 return true; 39 40 /* all non-secure memory references are handled by PTAs */ 41 if (mobj_is_nonsec(mobj)) 42 return true; 43 44 return false; 45 } 46 #else 47 static bool validate_in_param(struct ts_session *s __unused, 48 struct mobj *mobj __unused) 49 { 50 /* At this point, core has filled only valid accessible memref mobj */ 51 return true; 52 } 53 #endif 54 55 /* Maps pseudo TA params */ 56 static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, 57 struct tee_ta_param *param, 58 TEE_Param tee_param[TEE_NUM_PARAMS], 59 bool did_map[TEE_NUM_PARAMS]) 60 { 61 size_t n; 62 void *va; 63 struct param_mem *mem; 64 65 for (n = 0; n < TEE_NUM_PARAMS; n++) { 66 switch (TEE_PARAM_TYPE_GET(param->types, n)) { 67 case TEE_PARAM_TYPE_VALUE_INPUT: 68 case TEE_PARAM_TYPE_VALUE_OUTPUT: 69 case TEE_PARAM_TYPE_VALUE_INOUT: 70 tee_param[n].value.a = param->u[n].val.a; 71 tee_param[n].value.b = param->u[n].val.b; 72 break; 73 case TEE_PARAM_TYPE_MEMREF_INPUT: 74 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 75 case TEE_PARAM_TYPE_MEMREF_INOUT: 76 mem = ¶m->u[n].mem; 77 if (!validate_in_param(s, mem->mobj)) 78 return TEE_ERROR_BAD_PARAMETERS; 79 if (mem->size) { 80 TEE_Result res = mobj_inc_map(mem->mobj); 81 82 if (res) 83 return res; 84 did_map[n] = true; 85 va = mobj_get_va(mem->mobj, mem->offs, 86 mem->size); 87 if (!va) 88 return TEE_ERROR_BAD_PARAMETERS; 89 } else { 90 va = NULL; 91 } 92 93 tee_param[n].memref.buffer = va; 94 tee_param[n].memref.size = mem->size; 95 break; 96 default: 97 memset(tee_param + n, 0, sizeof(TEE_Param)); 98 break; 99 } 100 } 101 102 return TEE_SUCCESS; 103 } 104 105 static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], 106 struct tee_ta_param *param) 107 { 108 size_t n; 109 110 for (n = 0; n < TEE_NUM_PARAMS; n++) { 111 switch (TEE_PARAM_TYPE_GET(param->types, n)) { 112 case TEE_PARAM_TYPE_VALUE_OUTPUT: 113 case TEE_PARAM_TYPE_VALUE_INOUT: 114 param->u[n].val.a = tee_param[n].value.a; 115 param->u[n].val.b = tee_param[n].value.b; 116 break; 117 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 118 case TEE_PARAM_TYPE_MEMREF_INOUT: 119 param->u[n].mem.size = tee_param[n].memref.size; 120 break; 121 default: 122 break; 123 } 124 } 125 } 126 127 static void unmap_mapped_param(struct tee_ta_param *param, 128 bool did_map[TEE_NUM_PARAMS]) 129 { 130 size_t n; 131 132 for (n = 0; n < TEE_NUM_PARAMS; n++) { 133 if (did_map[n]) { 134 TEE_Result res __maybe_unused; 135 136 res = mobj_dec_map(param->u[n].mem.mobj); 137 assert(!res); 138 } 139 } 140 } 141 142 static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) 143 { 144 TEE_Result res = TEE_SUCCESS; 145 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 146 struct tee_ta_session *ta_sess = to_ta_session(s); 147 TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 148 bool did_map[TEE_NUM_PARAMS] = { false }; 149 150 ts_push_current_session(s); 151 ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 152 153 if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { 154 res = stc->pseudo_ta->create_entry_point(); 155 if (res != TEE_SUCCESS) 156 goto out; 157 } 158 159 if (stc->pseudo_ta->open_session_entry_point) { 160 void **user_ctx = &s->user_ctx; 161 uint32_t param_types = 0; 162 163 if (ta_sess->param) { 164 res = copy_in_param(s, ta_sess->param, tee_param, 165 did_map); 166 if (res != TEE_SUCCESS) { 167 unmap_mapped_param(ta_sess->param, did_map); 168 ta_sess->err_origin = TEE_ORIGIN_TEE; 169 goto out; 170 } 171 param_types = ta_sess->param->types; 172 } 173 174 res = stc->pseudo_ta->open_session_entry_point(param_types, 175 tee_param, 176 user_ctx); 177 if (ta_sess->param) { 178 update_out_param(tee_param, ta_sess->param); 179 unmap_mapped_param(ta_sess->param, did_map); 180 } 181 } 182 183 out: 184 ts_pop_current_session(); 185 return res; 186 } 187 188 static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) 189 { 190 TEE_Result res = TEE_SUCCESS; 191 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 192 struct tee_ta_session *ta_sess = to_ta_session(s); 193 uint32_t param_types = 0; 194 TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 195 bool did_map[TEE_NUM_PARAMS] = { false }; 196 197 ts_push_current_session(s); 198 if (ta_sess->param) { 199 res = copy_in_param(s, ta_sess->param, tee_param, did_map); 200 if (res != TEE_SUCCESS) { 201 unmap_mapped_param(ta_sess->param, did_map); 202 ta_sess->err_origin = TEE_ORIGIN_TEE; 203 goto out; 204 } 205 param_types = ta_sess->param->types; 206 } 207 208 ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 209 res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, 210 param_types, 211 tee_param); 212 if (ta_sess->param) { 213 update_out_param(tee_param, ta_sess->param); 214 unmap_mapped_param(ta_sess->param, did_map); 215 } 216 out: 217 ts_pop_current_session(); 218 return res; 219 } 220 221 static void pseudo_ta_enter_close_session(struct ts_session *s) 222 { 223 struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 224 void *user_ctx = s->user_ctx; 225 226 ts_push_current_session(s); 227 228 if (stc->pseudo_ta->close_session_entry_point) 229 stc->pseudo_ta->close_session_entry_point(user_ctx); 230 231 if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) 232 stc->pseudo_ta->destroy_entry_point(); 233 234 ts_pop_current_session(); 235 } 236 237 static void pseudo_ta_destroy(struct ts_ctx *ctx) 238 { 239 free(to_pseudo_ta_ctx(ctx)); 240 } 241 242 static const struct ts_ops pseudo_ta_ops = { 243 .enter_open_session = pseudo_ta_enter_open_session, 244 .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, 245 .enter_close_session = pseudo_ta_enter_close_session, 246 .destroy = pseudo_ta_destroy, 247 }; 248 249 bool __noprof is_pseudo_ta_ctx(struct ts_ctx *ctx) 250 { 251 return ctx->ops == &pseudo_ta_ops; 252 } 253 254 /* Insures declared pseudo TAs conforms with core expectations */ 255 static TEE_Result verify_pseudo_tas_conformance(void) 256 { 257 const struct pseudo_ta_head *start = 258 SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 259 const struct pseudo_ta_head *end = 260 SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); 261 const struct pseudo_ta_head *pta; 262 263 for (pta = start; pta < end; pta++) { 264 const struct pseudo_ta_head *pta2; 265 266 /* PTAs must all have a specific UUID */ 267 for (pta2 = pta + 1; pta2 < end; pta2++) { 268 if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) 269 goto err; 270 } 271 272 if (!pta->name || 273 (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || 274 pta->flags & ~PTA_ALLOWED_FLAGS || 275 !pta->invoke_command_entry_point) 276 goto err; 277 } 278 return TEE_SUCCESS; 279 err: 280 DMSG("pseudo TA error at %p", (void *)pta); 281 panic("PTA"); 282 } 283 284 service_init(verify_pseudo_tas_conformance); 285 286 /*----------------------------------------------------------------------------- 287 * Initialises a session based on the UUID or ptr to the ta 288 * Returns ptr to the session (ta_session) and a TEE_Result 289 *---------------------------------------------------------------------------*/ 290 TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, 291 struct tee_ta_session *s) 292 { 293 struct pseudo_ta_ctx *stc = NULL; 294 struct tee_ta_ctx *ctx; 295 const struct pseudo_ta_head *ta; 296 297 /* 298 * Caller is expected to hold tee_ta_mutex for safe changes 299 * in @s and registering of the context in tee_ctxes list. 300 */ 301 assert(mutex_is_locked(&tee_ta_mutex)); 302 303 DMSG("Lookup pseudo TA %pUl", (void *)uuid); 304 305 ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 306 while (true) { 307 if (ta >= SCATTERED_ARRAY_END(pseudo_tas, 308 struct pseudo_ta_head)) 309 return TEE_ERROR_ITEM_NOT_FOUND; 310 if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) 311 break; 312 ta++; 313 } 314 315 DMSG("Open %s", ta->name); 316 stc = calloc(1, sizeof(struct pseudo_ta_ctx)); 317 if (!stc) 318 return TEE_ERROR_OUT_OF_MEMORY; 319 ctx = &stc->ctx; 320 321 ctx->ref_count = 1; 322 ctx->flags = ta->flags; 323 stc->pseudo_ta = ta; 324 ctx->ts_ctx.uuid = ta->uuid; 325 ctx->ts_ctx.ops = &pseudo_ta_ops; 326 327 s->ts_sess.ctx = &ctx->ts_ctx; 328 TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); 329 330 DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); 331 332 return TEE_SUCCESS; 333 } 334 335 TEE_Result to_bounce_params(uint32_t param_types, 336 TEE_Param params[TEE_NUM_PARAMS], 337 TEE_Param bparams[TEE_NUM_PARAMS], 338 TEE_Param **oparams) 339 { 340 TEE_Result res = TEE_ERROR_GENERIC; 341 void *kptr = NULL; 342 void *uptr = NULL; 343 size_t size = 0; 344 int i = 0; 345 346 if (!is_caller_ta_with_pan()) { 347 *oparams = params; 348 return TEE_SUCCESS; 349 } 350 351 for (i = 0; i < TEE_NUM_PARAMS; i++) { 352 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 353 case TEE_PARAM_TYPE_MEMREF_INPUT: 354 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 355 case TEE_PARAM_TYPE_MEMREF_INOUT: 356 size = params[i].memref.size; 357 uptr = params[i].memref.buffer; 358 kptr = bb_alloc(size); 359 if (!kptr) 360 return TEE_ERROR_OUT_OF_MEMORY; 361 bparams[i].memref.buffer = kptr; 362 bparams[i].memref.size = size; 363 break; 364 default: 365 break; 366 } 367 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 368 case TEE_PARAM_TYPE_MEMREF_INPUT: 369 case TEE_PARAM_TYPE_MEMREF_INOUT: 370 res = copy_from_user(kptr, uptr, size); 371 if (res) 372 return res; 373 break; 374 case TEE_PARAM_TYPE_VALUE_INPUT: 375 case TEE_PARAM_TYPE_VALUE_INOUT: 376 bparams[i].value.a = params[i].value.a; 377 bparams[i].value.b = params[i].value.b; 378 break; 379 default: 380 break; 381 } 382 } 383 *oparams = bparams; 384 385 return TEE_SUCCESS; 386 } 387 388 TEE_Result from_bounce_params(uint32_t param_types, 389 TEE_Param params[TEE_NUM_PARAMS], 390 TEE_Param bparams[TEE_NUM_PARAMS], 391 TEE_Param *eparams) 392 { 393 TEE_Result res = TEE_ERROR_GENERIC; 394 void *kptr = NULL; 395 void *uptr = NULL; 396 size_t size = 0; 397 int i = 0; 398 399 if (eparams == params) 400 return TEE_SUCCESS; 401 402 for (i = 0; i < TEE_NUM_PARAMS; i++) { 403 switch (TEE_PARAM_TYPE_GET(param_types, i)) { 404 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 405 case TEE_PARAM_TYPE_MEMREF_INOUT: 406 uptr = params[i].memref.buffer; 407 kptr = bparams[i].memref.buffer; 408 size = bparams[i].memref.size; 409 res = copy_to_user(uptr, kptr, size); 410 if (res) 411 return res; 412 params[i].memref.size = size; 413 break; 414 case TEE_PARAM_TYPE_VALUE_OUTPUT: 415 case TEE_PARAM_TYPE_VALUE_INOUT: 416 params[i].value.a = bparams[i].value.a; 417 params[i].value.b = bparams[i].value.b; 418 break; 419 default: 420 break; 421 } 422 } 423 424 return res; 425 } 426