1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * Copyright (c) 2020, Arm Limited 5 */ 6 7 #include <arm.h> 8 #include <assert.h> 9 #include <kernel/mutex.h> 10 #include <kernel/panic.h> 11 #include <kernel/pseudo_ta.h> 12 #include <kernel/stmm_sp.h> 13 #include <kernel/tee_common.h> 14 #include <kernel/tee_misc.h> 15 #include <kernel/tee_ta_manager.h> 16 #include <kernel/tee_time.h> 17 #include <kernel/thread.h> 18 #include <kernel/user_mode_ctx.h> 19 #include <kernel/user_ta.h> 20 #include <mm/core_memprot.h> 21 #include <mm/core_mmu.h> 22 #include <mm/mobj.h> 23 #include <mm/vm.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <tee_api_types.h> 28 #include <tee/entry_std.h> 29 #include <tee/tee_obj.h> 30 #include <tee/tee_svc_cryp.h> 31 #include <tee/tee_svc_storage.h> 32 #include <trace.h> 33 #include <types_ext.h> 34 #include <user_ta_header.h> 35 #include <utee_types.h> 36 #include <util.h> 37 38 /* This mutex protects the critical section in tee_ta_init_session */ 39 struct mutex tee_ta_mutex = MUTEX_INITIALIZER; 40 /* This condvar is used when waiting for a TA context to become initialized */ 41 struct condvar tee_ta_init_cv = CONDVAR_INITIALIZER; 42 struct tee_ta_ctx_head tee_ctxes = TAILQ_HEAD_INITIALIZER(tee_ctxes); 43 44 #ifndef CFG_CONCURRENT_SINGLE_INSTANCE_TA 45 static struct condvar tee_ta_cv = CONDVAR_INITIALIZER; 46 static short int tee_ta_single_instance_thread = THREAD_ID_INVALID; 47 static size_t tee_ta_single_instance_count; 48 #endif 49 50 #ifdef CFG_CONCURRENT_SINGLE_INSTANCE_TA 51 static void lock_single_instance(void) 52 { 53 } 54 55 static void unlock_single_instance(void) 56 { 57 } 58 59 static bool has_single_instance_lock(void) 60 { 61 return false; 62 } 63 #else 64 static void lock_single_instance(void) 65 { 66 /* Requires tee_ta_mutex to be held */ 67 if (tee_ta_single_instance_thread != thread_get_id()) { 68 /* Wait until the single-instance lock is available. */ 69 while (tee_ta_single_instance_thread != THREAD_ID_INVALID) 70 condvar_wait(&tee_ta_cv, &tee_ta_mutex); 71 72 tee_ta_single_instance_thread = thread_get_id(); 73 assert(tee_ta_single_instance_count == 0); 74 } 75 76 tee_ta_single_instance_count++; 77 } 78 79 static void unlock_single_instance(void) 80 { 81 /* Requires tee_ta_mutex to be held */ 82 assert(tee_ta_single_instance_thread == thread_get_id()); 83 assert(tee_ta_single_instance_count > 0); 84 85 tee_ta_single_instance_count--; 86 if (tee_ta_single_instance_count == 0) { 87 tee_ta_single_instance_thread = THREAD_ID_INVALID; 88 condvar_signal(&tee_ta_cv); 89 } 90 } 91 92 static bool has_single_instance_lock(void) 93 { 94 /* Requires tee_ta_mutex to be held */ 95 return tee_ta_single_instance_thread == thread_get_id(); 96 } 97 #endif 98 99 struct tee_ta_session *__noprof to_ta_session(struct ts_session *sess) 100 { 101 assert(is_ta_ctx(sess->ctx) || is_stmm_ctx(sess->ctx)); 102 return container_of(sess, struct tee_ta_session, ts_sess); 103 } 104 105 static struct tee_ta_ctx *ts_to_ta_ctx(struct ts_ctx *ctx) 106 { 107 if (is_ta_ctx(ctx)) 108 return to_ta_ctx(ctx); 109 110 if (is_stmm_ctx(ctx)) 111 return &(to_stmm_ctx(ctx)->ta_ctx); 112 113 panic("bad context"); 114 } 115 116 static bool tee_ta_try_set_busy(struct tee_ta_ctx *ctx) 117 { 118 bool rc = true; 119 120 if (ctx->flags & TA_FLAG_CONCURRENT) 121 return true; 122 123 mutex_lock(&tee_ta_mutex); 124 125 if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) 126 lock_single_instance(); 127 128 if (has_single_instance_lock()) { 129 if (ctx->busy) { 130 /* 131 * We're holding the single-instance lock and the 132 * TA is busy, as waiting now would only cause a 133 * dead-lock, we release the lock and return false. 134 */ 135 rc = false; 136 if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) 137 unlock_single_instance(); 138 } 139 } else { 140 /* 141 * We're not holding the single-instance lock, we're free to 142 * wait for the TA to become available. 143 */ 144 while (ctx->busy) 145 condvar_wait(&ctx->busy_cv, &tee_ta_mutex); 146 } 147 148 /* Either it's already true or we should set it to true */ 149 ctx->busy = true; 150 151 mutex_unlock(&tee_ta_mutex); 152 return rc; 153 } 154 155 static void tee_ta_set_busy(struct tee_ta_ctx *ctx) 156 { 157 if (!tee_ta_try_set_busy(ctx)) 158 panic(); 159 } 160 161 static void tee_ta_clear_busy(struct tee_ta_ctx *ctx) 162 { 163 if (ctx->flags & TA_FLAG_CONCURRENT) 164 return; 165 166 mutex_lock(&tee_ta_mutex); 167 168 assert(ctx->busy); 169 ctx->busy = false; 170 condvar_signal(&ctx->busy_cv); 171 172 if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) 173 unlock_single_instance(); 174 175 mutex_unlock(&tee_ta_mutex); 176 } 177 178 static void dec_session_ref_count(struct tee_ta_session *s) 179 { 180 assert(s->ref_count > 0); 181 s->ref_count--; 182 if (s->ref_count == 1) 183 condvar_signal(&s->refc_cv); 184 } 185 186 void tee_ta_put_session(struct tee_ta_session *s) 187 { 188 mutex_lock(&tee_ta_mutex); 189 190 if (s->lock_thread == thread_get_id()) { 191 s->lock_thread = THREAD_ID_INVALID; 192 condvar_signal(&s->lock_cv); 193 } 194 dec_session_ref_count(s); 195 196 mutex_unlock(&tee_ta_mutex); 197 } 198 199 static struct tee_ta_session *tee_ta_find_session_nolock(uint32_t id, 200 struct tee_ta_session_head *open_sessions) 201 { 202 struct tee_ta_session *s = NULL; 203 struct tee_ta_session *found = NULL; 204 205 TAILQ_FOREACH(s, open_sessions, link) { 206 if (s->id == id) { 207 found = s; 208 break; 209 } 210 } 211 212 return found; 213 } 214 215 struct tee_ta_session *tee_ta_find_session(uint32_t id, 216 struct tee_ta_session_head *open_sessions) 217 { 218 struct tee_ta_session *s = NULL; 219 220 mutex_lock(&tee_ta_mutex); 221 222 s = tee_ta_find_session_nolock(id, open_sessions); 223 224 mutex_unlock(&tee_ta_mutex); 225 226 return s; 227 } 228 229 struct tee_ta_session *tee_ta_get_session(uint32_t id, bool exclusive, 230 struct tee_ta_session_head *open_sessions) 231 { 232 struct tee_ta_session *s; 233 234 mutex_lock(&tee_ta_mutex); 235 236 while (true) { 237 s = tee_ta_find_session_nolock(id, open_sessions); 238 if (!s) 239 break; 240 if (s->unlink) { 241 s = NULL; 242 break; 243 } 244 s->ref_count++; 245 if (!exclusive) 246 break; 247 248 assert(s->lock_thread != thread_get_id()); 249 250 while (s->lock_thread != THREAD_ID_INVALID && !s->unlink) 251 condvar_wait(&s->lock_cv, &tee_ta_mutex); 252 253 if (s->unlink) { 254 dec_session_ref_count(s); 255 s = NULL; 256 break; 257 } 258 259 s->lock_thread = thread_get_id(); 260 break; 261 } 262 263 mutex_unlock(&tee_ta_mutex); 264 return s; 265 } 266 267 static void tee_ta_unlink_session(struct tee_ta_session *s, 268 struct tee_ta_session_head *open_sessions) 269 { 270 mutex_lock(&tee_ta_mutex); 271 272 assert(s->ref_count >= 1); 273 assert(s->lock_thread == thread_get_id()); 274 assert(!s->unlink); 275 276 s->unlink = true; 277 condvar_broadcast(&s->lock_cv); 278 279 while (s->ref_count != 1) 280 condvar_wait(&s->refc_cv, &tee_ta_mutex); 281 282 TAILQ_REMOVE(open_sessions, s, link); 283 284 mutex_unlock(&tee_ta_mutex); 285 } 286 287 static void destroy_session(struct tee_ta_session *s, 288 struct tee_ta_session_head *open_sessions) 289 { 290 #if defined(CFG_FTRACE_SUPPORT) 291 if (s->ts_sess.ctx && s->ts_sess.ctx->ops->dump_ftrace) { 292 ts_push_current_session(&s->ts_sess); 293 s->ts_sess.fbuf = NULL; 294 s->ts_sess.ctx->ops->dump_ftrace(s->ts_sess.ctx); 295 ts_pop_current_session(); 296 } 297 #endif 298 299 tee_ta_unlink_session(s, open_sessions); 300 #if defined(CFG_TA_GPROF_SUPPORT) 301 free(s->ts_sess.sbuf); 302 #endif 303 free(s); 304 } 305 306 static void destroy_context(struct tee_ta_ctx *ctx) 307 { 308 DMSG("Destroy TA ctx (0x%" PRIxVA ")", (vaddr_t)ctx); 309 310 condvar_destroy(&ctx->busy_cv); 311 pgt_flush_ctx(&ctx->ts_ctx); 312 ctx->ts_ctx.ops->destroy(&ctx->ts_ctx); 313 } 314 315 static void destroy_ta_ctx_from_session(struct tee_ta_session *s) 316 { 317 struct tee_ta_session *sess = NULL; 318 struct tee_ta_session_head *open_sessions = NULL; 319 struct tee_ta_ctx *ctx = NULL; 320 struct user_ta_ctx *utc = NULL; 321 struct ts_ctx *ts_ctx = s->ts_sess.ctx; 322 size_t count = 1; /* start counting the references to the context */ 323 324 DMSG("Remove references to context (%#"PRIxVA")", (vaddr_t)ts_ctx); 325 326 mutex_lock(&tee_ta_mutex); 327 nsec_sessions_list_head(&open_sessions); 328 329 /* 330 * Next two loops will remove all references to the context which is 331 * about to be destroyed, but avoiding such operation to the current 332 * session. That will be done later in this function, only after 333 * the context will be properly destroyed. 334 */ 335 336 /* 337 * Scan the entire list of opened sessions by the clients from 338 * non-secure world. 339 */ 340 TAILQ_FOREACH(sess, open_sessions, link) { 341 if (sess->ts_sess.ctx == ts_ctx && sess != s) { 342 sess->ts_sess.ctx = NULL; 343 count++; 344 } 345 } 346 347 /* 348 * Scan all sessions opened from secure side by searching through 349 * all available TA instances and for each context, scan all opened 350 * sessions. 351 */ 352 TAILQ_FOREACH(ctx, &tee_ctxes, link) { 353 if (is_user_ta_ctx(&ctx->ts_ctx)) { 354 utc = to_user_ta_ctx(&ctx->ts_ctx); 355 356 TAILQ_FOREACH(sess, &utc->open_sessions, link) { 357 if (sess->ts_sess.ctx == ts_ctx && 358 sess != s) { 359 sess->ts_sess.ctx = NULL; 360 count++; 361 } 362 } 363 } 364 } 365 366 ctx = ts_to_ta_ctx(ts_ctx); 367 assert(count == ctx->ref_count); 368 369 TAILQ_REMOVE(&tee_ctxes, ctx, link); 370 mutex_unlock(&tee_ta_mutex); 371 372 destroy_context(ctx); 373 s->ts_sess.ctx = NULL; 374 } 375 376 /* 377 * tee_ta_context_find - Find TA in session list based on a UUID (input) 378 * Returns a pointer to the session 379 */ 380 static struct tee_ta_ctx *tee_ta_context_find(const TEE_UUID *uuid) 381 { 382 struct tee_ta_ctx *ctx; 383 384 TAILQ_FOREACH(ctx, &tee_ctxes, link) { 385 if (memcmp(&ctx->ts_ctx.uuid, uuid, sizeof(TEE_UUID)) == 0) 386 return ctx; 387 } 388 389 return NULL; 390 } 391 392 /* check if requester (client ID) matches session initial client */ 393 static TEE_Result check_client(struct tee_ta_session *s, const TEE_Identity *id) 394 { 395 if (id == KERN_IDENTITY) 396 return TEE_SUCCESS; 397 398 if (id == NSAPP_IDENTITY) { 399 if (s->clnt_id.login == TEE_LOGIN_TRUSTED_APP) { 400 DMSG("nsec tries to hijack TA session"); 401 return TEE_ERROR_ACCESS_DENIED; 402 } 403 return TEE_SUCCESS; 404 } 405 406 if (memcmp(&s->clnt_id, id, sizeof(TEE_Identity)) != 0) { 407 DMSG("client id mismatch"); 408 return TEE_ERROR_ACCESS_DENIED; 409 } 410 return TEE_SUCCESS; 411 } 412 413 /* 414 * Check if invocation parameters matches TA properties 415 * 416 * @s - current session handle 417 * @param - already identified memory references hold a valid 'mobj'. 418 * 419 * Policy: 420 * - All TAs can access 'non-secure' shared memory. 421 * - All TAs can access TEE private memory (seccpy) 422 * - Only SDP flagged TAs can accept SDP memory references. 423 */ 424 #ifndef CFG_SECURE_DATA_PATH 425 static bool check_params(struct tee_ta_session *sess __unused, 426 struct tee_ta_param *param __unused) 427 { 428 /* 429 * When CFG_SECURE_DATA_PATH is not enabled, SDP memory references 430 * are rejected at OP-TEE core entry. Hence here all TAs have same 431 * permissions regarding memory reference parameters. 432 */ 433 return true; 434 } 435 #else 436 static bool check_params(struct tee_ta_session *sess, 437 struct tee_ta_param *param) 438 { 439 int n; 440 441 /* 442 * When CFG_SECURE_DATA_PATH is enabled, OP-TEE entry allows SHM and 443 * SDP memory references. Only TAs flagged SDP can access SDP memory. 444 */ 445 if (sess->ts_sess.ctx && 446 ts_to_ta_ctx(sess->ts_sess.ctx)->flags & TA_FLAG_SECURE_DATA_PATH) 447 return true; 448 449 for (n = 0; n < TEE_NUM_PARAMS; n++) { 450 uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); 451 struct param_mem *mem = ¶m->u[n].mem; 452 453 if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && 454 param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && 455 param_type != TEE_PARAM_TYPE_MEMREF_INOUT) 456 continue; 457 if (!mem->size) 458 continue; 459 if (mobj_is_sdp_mem(mem->mobj)) 460 return false; 461 } 462 return true; 463 } 464 #endif 465 466 static void set_invoke_timeout(struct tee_ta_session *sess, 467 uint32_t cancel_req_to) 468 { 469 TEE_Time current_time; 470 TEE_Time cancel_time; 471 472 if (cancel_req_to == TEE_TIMEOUT_INFINITE) 473 goto infinite; 474 475 if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) 476 goto infinite; 477 478 if (ADD_OVERFLOW(current_time.seconds, cancel_req_to / 1000, 479 &cancel_time.seconds)) 480 goto infinite; 481 482 cancel_time.millis = current_time.millis + cancel_req_to % 1000; 483 if (cancel_time.millis > 1000) { 484 if (ADD_OVERFLOW(current_time.seconds, 1, 485 &cancel_time.seconds)) 486 goto infinite; 487 488 cancel_time.seconds++; 489 cancel_time.millis -= 1000; 490 } 491 492 sess->cancel_time = cancel_time; 493 return; 494 495 infinite: 496 sess->cancel_time.seconds = UINT32_MAX; 497 sess->cancel_time.millis = UINT32_MAX; 498 } 499 500 /*----------------------------------------------------------------------------- 501 * Close a Trusted Application and free available resources 502 *---------------------------------------------------------------------------*/ 503 TEE_Result tee_ta_close_session(struct tee_ta_session *csess, 504 struct tee_ta_session_head *open_sessions, 505 const TEE_Identity *clnt_id) 506 { 507 struct tee_ta_session *sess = NULL; 508 struct tee_ta_ctx *ctx = NULL; 509 struct ts_ctx *ts_ctx = NULL; 510 bool keep_alive = false; 511 512 DMSG("csess 0x%" PRIxVA " id %u", 513 (vaddr_t)csess, csess ? csess->id : UINT_MAX); 514 515 if (!csess) 516 return TEE_ERROR_ITEM_NOT_FOUND; 517 518 sess = tee_ta_get_session(csess->id, true, open_sessions); 519 520 if (!sess) { 521 EMSG("session 0x%" PRIxVA " to be removed is not found", 522 (vaddr_t)csess); 523 return TEE_ERROR_ITEM_NOT_FOUND; 524 } 525 526 if (check_client(sess, clnt_id) != TEE_SUCCESS) { 527 tee_ta_put_session(sess); 528 return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ 529 } 530 531 DMSG("Destroy session"); 532 533 ts_ctx = sess->ts_sess.ctx; 534 if (!ts_ctx) { 535 destroy_session(sess, open_sessions); 536 return TEE_SUCCESS; 537 } 538 539 ctx = ts_to_ta_ctx(ts_ctx); 540 if (ctx->panicked) { 541 destroy_session(sess, open_sessions); 542 } else { 543 tee_ta_set_busy(ctx); 544 set_invoke_timeout(sess, TEE_TIMEOUT_INFINITE); 545 ts_ctx->ops->enter_close_session(&sess->ts_sess); 546 destroy_session(sess, open_sessions); 547 tee_ta_clear_busy(ctx); 548 } 549 550 mutex_lock(&tee_ta_mutex); 551 552 if (ctx->ref_count <= 0) 553 panic(); 554 555 ctx->ref_count--; 556 keep_alive = (ctx->flags & TA_FLAG_INSTANCE_KEEP_ALIVE) && 557 (ctx->flags & TA_FLAG_SINGLE_INSTANCE); 558 if (!ctx->ref_count && !keep_alive) { 559 TAILQ_REMOVE(&tee_ctxes, ctx, link); 560 mutex_unlock(&tee_ta_mutex); 561 562 destroy_context(ctx); 563 } else 564 mutex_unlock(&tee_ta_mutex); 565 566 return TEE_SUCCESS; 567 } 568 569 static TEE_Result tee_ta_init_session_with_context(struct tee_ta_session *s, 570 const TEE_UUID *uuid) 571 { 572 struct tee_ta_ctx *ctx = NULL; 573 574 while (true) { 575 ctx = tee_ta_context_find(uuid); 576 if (!ctx) 577 return TEE_ERROR_ITEM_NOT_FOUND; 578 579 if (!is_user_ta_ctx(&ctx->ts_ctx) || 580 !to_user_ta_ctx(&ctx->ts_ctx)->uctx.is_initializing) 581 break; 582 /* 583 * Context is still initializing, wait here until it's 584 * fully initialized. Note that we're searching for the 585 * context again since it may have been removed while we 586 * where sleeping. 587 */ 588 condvar_wait(&tee_ta_init_cv, &tee_ta_mutex); 589 } 590 591 /* 592 * If TA isn't single instance it should be loaded as new 593 * instance instead of doing anything with this instance. 594 * So tell the caller that we didn't find the TA it the 595 * caller will load a new instance. 596 */ 597 if ((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) 598 return TEE_ERROR_ITEM_NOT_FOUND; 599 600 /* 601 * The TA is single instance, if it isn't multi session we 602 * can't create another session unless its reference is zero 603 */ 604 if (!(ctx->flags & TA_FLAG_MULTI_SESSION) && ctx->ref_count) 605 return TEE_ERROR_BUSY; 606 607 DMSG("Re-open TA %pUl", (void *)&ctx->ts_ctx.uuid); 608 609 ctx->ref_count++; 610 s->ts_sess.ctx = &ctx->ts_ctx; 611 s->ts_sess.handle_svc = s->ts_sess.ctx->ops->handle_svc; 612 return TEE_SUCCESS; 613 } 614 615 static uint32_t new_session_id(struct tee_ta_session_head *open_sessions) 616 { 617 struct tee_ta_session *last = NULL; 618 uint32_t saved = 0; 619 uint32_t id = 1; 620 621 last = TAILQ_LAST(open_sessions, tee_ta_session_head); 622 if (last) { 623 /* This value is less likely to be already used */ 624 id = last->id + 1; 625 if (!id) 626 id++; /* 0 is not valid */ 627 } 628 629 saved = id; 630 do { 631 if (!tee_ta_find_session_nolock(id, open_sessions)) 632 return id; 633 id++; 634 if (!id) 635 id++; 636 } while (id != saved); 637 638 return 0; 639 } 640 641 static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, 642 struct tee_ta_session_head *open_sessions, 643 const TEE_UUID *uuid, 644 struct tee_ta_session **sess) 645 { 646 TEE_Result res; 647 struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session)); 648 649 *err = TEE_ORIGIN_TEE; 650 if (!s) 651 return TEE_ERROR_OUT_OF_MEMORY; 652 653 s->cancel_mask = true; 654 condvar_init(&s->refc_cv); 655 condvar_init(&s->lock_cv); 656 s->lock_thread = THREAD_ID_INVALID; 657 s->ref_count = 1; 658 659 mutex_lock(&tee_ta_mutex); 660 s->id = new_session_id(open_sessions); 661 if (!s->id) { 662 res = TEE_ERROR_OVERFLOW; 663 goto err_mutex_unlock; 664 } 665 666 TAILQ_INSERT_TAIL(open_sessions, s, link); 667 668 /* Look for already loaded TA */ 669 res = tee_ta_init_session_with_context(s, uuid); 670 mutex_unlock(&tee_ta_mutex); 671 if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) 672 goto out; 673 674 /* Look for secure partition */ 675 res = stmm_init_session(uuid, s); 676 if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) 677 goto out; 678 679 /* Look for pseudo TA */ 680 res = tee_ta_init_pseudo_ta_session(uuid, s); 681 if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) 682 goto out; 683 684 /* Look for user TA */ 685 res = tee_ta_init_user_ta_session(uuid, s); 686 687 out: 688 if (!res) { 689 *sess = s; 690 return TEE_SUCCESS; 691 } 692 693 mutex_lock(&tee_ta_mutex); 694 TAILQ_REMOVE(open_sessions, s, link); 695 err_mutex_unlock: 696 mutex_unlock(&tee_ta_mutex); 697 free(s); 698 return res; 699 } 700 701 TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, 702 struct tee_ta_session **sess, 703 struct tee_ta_session_head *open_sessions, 704 const TEE_UUID *uuid, 705 const TEE_Identity *clnt_id, 706 uint32_t cancel_req_to, 707 struct tee_ta_param *param) 708 { 709 TEE_Result res = TEE_SUCCESS; 710 struct tee_ta_session *s = NULL; 711 struct tee_ta_ctx *ctx = NULL; 712 struct ts_ctx *ts_ctx = NULL; 713 bool panicked = false; 714 bool was_busy = false; 715 716 res = tee_ta_init_session(err, open_sessions, uuid, &s); 717 if (res != TEE_SUCCESS) { 718 DMSG("init session failed 0x%x", res); 719 return res; 720 } 721 722 if (!check_params(s, param)) 723 return TEE_ERROR_BAD_PARAMETERS; 724 725 ts_ctx = s->ts_sess.ctx; 726 if (ts_ctx) 727 ctx = ts_to_ta_ctx(ts_ctx); 728 729 if (!ctx || ctx->panicked) { 730 DMSG("panicked, call tee_ta_close_session()"); 731 tee_ta_close_session(s, open_sessions, KERN_IDENTITY); 732 *err = TEE_ORIGIN_TEE; 733 return TEE_ERROR_TARGET_DEAD; 734 } 735 736 *sess = s; 737 /* Save identity of the owner of the session */ 738 s->clnt_id = *clnt_id; 739 740 if (tee_ta_try_set_busy(ctx)) { 741 s->param = param; 742 set_invoke_timeout(s, cancel_req_to); 743 res = ts_ctx->ops->enter_open_session(&s->ts_sess); 744 tee_ta_clear_busy(ctx); 745 } else { 746 /* Deadlock avoided */ 747 res = TEE_ERROR_BUSY; 748 was_busy = true; 749 } 750 751 panicked = ctx->panicked; 752 s->param = NULL; 753 754 tee_ta_put_session(s); 755 if (panicked || (res != TEE_SUCCESS)) 756 tee_ta_close_session(s, open_sessions, KERN_IDENTITY); 757 758 /* 759 * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, 760 * apart from panicking. 761 */ 762 if (panicked || was_busy) 763 *err = TEE_ORIGIN_TEE; 764 else 765 *err = s->err_origin; 766 767 if (res != TEE_SUCCESS) 768 EMSG("Failed. Return error 0x%x", res); 769 770 return res; 771 } 772 773 TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err, 774 struct tee_ta_session *sess, 775 const TEE_Identity *clnt_id, 776 uint32_t cancel_req_to, uint32_t cmd, 777 struct tee_ta_param *param) 778 { 779 struct tee_ta_ctx *ta_ctx = NULL; 780 struct ts_ctx *ts_ctx = NULL; 781 TEE_Result res = TEE_SUCCESS; 782 783 if (check_client(sess, clnt_id) != TEE_SUCCESS) 784 return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ 785 786 if (!check_params(sess, param)) 787 return TEE_ERROR_BAD_PARAMETERS; 788 789 ts_ctx = sess->ts_sess.ctx; 790 if (!ts_ctx) { 791 /* The context has been already destroyed */ 792 *err = TEE_ORIGIN_TEE; 793 return TEE_ERROR_TARGET_DEAD; 794 } 795 796 ta_ctx = ts_to_ta_ctx(ts_ctx); 797 if (ta_ctx->panicked) { 798 DMSG("Panicked !"); 799 destroy_ta_ctx_from_session(sess); 800 *err = TEE_ORIGIN_TEE; 801 return TEE_ERROR_TARGET_DEAD; 802 } 803 804 tee_ta_set_busy(ta_ctx); 805 806 sess->param = param; 807 set_invoke_timeout(sess, cancel_req_to); 808 res = ts_ctx->ops->enter_invoke_cmd(&sess->ts_sess, cmd); 809 810 sess->param = NULL; 811 tee_ta_clear_busy(ta_ctx); 812 813 if (ta_ctx->panicked) { 814 destroy_ta_ctx_from_session(sess); 815 *err = TEE_ORIGIN_TEE; 816 return TEE_ERROR_TARGET_DEAD; 817 } 818 819 *err = sess->err_origin; 820 821 /* Short buffer is not an effective error case */ 822 if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) 823 DMSG("Error: %x of %d", res, *err); 824 825 return res; 826 } 827 828 TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, 829 struct tee_ta_session *sess, 830 const TEE_Identity *clnt_id) 831 { 832 *err = TEE_ORIGIN_TEE; 833 834 if (check_client(sess, clnt_id) != TEE_SUCCESS) 835 return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ 836 837 sess->cancel = true; 838 return TEE_SUCCESS; 839 } 840 841 bool tee_ta_session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time) 842 { 843 TEE_Time current_time; 844 845 if (s->cancel_mask) 846 return false; 847 848 if (s->cancel) 849 return true; 850 851 if (s->cancel_time.seconds == UINT32_MAX) 852 return false; 853 854 if (curr_time != NULL) 855 current_time = *curr_time; 856 else if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) 857 return false; 858 859 if (current_time.seconds > s->cancel_time.seconds || 860 (current_time.seconds == s->cancel_time.seconds && 861 current_time.millis >= s->cancel_time.millis)) { 862 return true; 863 } 864 865 return false; 866 } 867 868 #if defined(CFG_TA_GPROF_SUPPORT) 869 void tee_ta_gprof_sample_pc(vaddr_t pc) 870 { 871 struct ts_session *s = ts_get_current_session(); 872 struct user_ta_ctx *utc = NULL; 873 struct sample_buf *sbuf = NULL; 874 TEE_Result res = 0; 875 size_t idx = 0; 876 877 sbuf = s->sbuf; 878 if (!sbuf || !sbuf->enabled) 879 return; /* PC sampling is not enabled */ 880 881 idx = (((uint64_t)pc - sbuf->offset)/2 * sbuf->scale)/65536; 882 if (idx < sbuf->nsamples) { 883 utc = to_user_ta_ctx(s->ctx); 884 res = vm_check_access_rights(&utc->uctx, 885 TEE_MEMORY_ACCESS_READ | 886 TEE_MEMORY_ACCESS_WRITE | 887 TEE_MEMORY_ACCESS_ANY_OWNER, 888 (uaddr_t)&sbuf->samples[idx], 889 sizeof(*sbuf->samples)); 890 if (res != TEE_SUCCESS) 891 return; 892 sbuf->samples[idx]++; 893 } 894 sbuf->count++; 895 } 896 897 static void gprof_update_session_utime(bool suspend, struct ts_session *s, 898 uint64_t now) 899 { 900 struct sample_buf *sbuf = s->sbuf; 901 902 if (!sbuf) 903 return; 904 905 if (suspend) { 906 assert(sbuf->usr_entered); 907 sbuf->usr += now - sbuf->usr_entered; 908 sbuf->usr_entered = 0; 909 } else { 910 assert(!sbuf->usr_entered); 911 if (!now) 912 now++; /* 0 is reserved */ 913 sbuf->usr_entered = now; 914 } 915 } 916 917 /* 918 * Update user-mode CPU time for the current session 919 * @suspend: true if session is being suspended (leaving user mode), false if 920 * it is resumed (entering user mode) 921 */ 922 static void tee_ta_update_session_utime(bool suspend) 923 { 924 struct ts_session *s = ts_get_current_session(); 925 uint64_t now = barrier_read_cntpct(); 926 927 gprof_update_session_utime(suspend, s, now); 928 } 929 930 void tee_ta_update_session_utime_suspend(void) 931 { 932 tee_ta_update_session_utime(true); 933 } 934 935 void tee_ta_update_session_utime_resume(void) 936 { 937 tee_ta_update_session_utime(false); 938 } 939 #endif 940 941 #if defined(CFG_FTRACE_SUPPORT) 942 static void ftrace_update_times(bool suspend) 943 { 944 struct ts_session *s = ts_get_current_session_may_fail(); 945 struct ftrace_buf *fbuf = NULL; 946 uint64_t now = 0; 947 uint32_t i = 0; 948 949 if (!s) 950 return; 951 952 now = barrier_read_cntpct(); 953 954 fbuf = s->fbuf; 955 if (!fbuf) 956 return; 957 958 if (suspend) { 959 fbuf->suspend_time = now; 960 } else { 961 for (i = 0; i <= fbuf->ret_idx; i++) 962 fbuf->begin_time[i] += now - fbuf->suspend_time; 963 } 964 } 965 966 void tee_ta_ftrace_update_times_suspend(void) 967 { 968 ftrace_update_times(true); 969 } 970 971 void tee_ta_ftrace_update_times_resume(void) 972 { 973 ftrace_update_times(false); 974 } 975 #endif 976 977 bool is_ta_ctx(struct ts_ctx *ctx) 978 { 979 return is_user_ta_ctx(ctx) || is_pseudo_ta_ctx(ctx); 980 } 981