1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2018-2019, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <crypto/crypto.h> 8 #include <kernel/handle.h> 9 #include <kernel/huk_subkey.h> 10 #include <kernel/misc.h> 11 #include <kernel/msg_param.h> 12 #include <kernel/pseudo_ta.h> 13 #include <kernel/user_ta.h> 14 #include <kernel/user_ta_store.h> 15 #include <ldelf.h> 16 #include <mm/file.h> 17 #include <mm/fobj.h> 18 #include <mm/tee_mmu.h> 19 #include <pta_system.h> 20 #include <string.h> 21 #include <tee_api_defines_extensions.h> 22 #include <tee_api_defines.h> 23 #include <util.h> 24 25 #define MAX_ENTROPY_IN 32u 26 27 struct bin_handle { 28 const struct user_ta_store_ops *op; 29 struct user_ta_store_handle *h; 30 struct file *f; 31 size_t offs_bytes; 32 size_t size_bytes; 33 }; 34 35 struct system_ctx { 36 struct handle_db db; 37 const struct user_ta_store_ops *store_op; 38 }; 39 40 static unsigned int system_pnum; 41 42 static TEE_Result system_rng_reseed(struct tee_ta_session *s __unused, 43 uint32_t param_types, 44 TEE_Param params[TEE_NUM_PARAMS]) 45 { 46 size_t entropy_sz; 47 uint8_t *entropy_input; 48 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 49 TEE_PARAM_TYPE_NONE, 50 TEE_PARAM_TYPE_NONE, 51 TEE_PARAM_TYPE_NONE); 52 53 if (exp_pt != param_types) 54 return TEE_ERROR_BAD_PARAMETERS; 55 entropy_input = params[0].memref.buffer; 56 entropy_sz = params[0].memref.size; 57 58 /* Fortuna PRNG requires seed <= 32 bytes */ 59 if (!entropy_sz) 60 return TEE_ERROR_BAD_PARAMETERS; 61 62 entropy_sz = MIN(entropy_sz, MAX_ENTROPY_IN); 63 64 crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, 65 entropy_input, entropy_sz); 66 return TEE_SUCCESS; 67 } 68 69 static TEE_Result system_derive_ta_unique_key(struct tee_ta_session *s, 70 uint32_t param_types, 71 TEE_Param params[TEE_NUM_PARAMS]) 72 { 73 size_t data_len = sizeof(TEE_UUID); 74 TEE_Result res = TEE_ERROR_GENERIC; 75 uint8_t *data = NULL; 76 uint32_t access_flags = 0; 77 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 78 TEE_PARAM_TYPE_MEMREF_OUTPUT, 79 TEE_PARAM_TYPE_NONE, 80 TEE_PARAM_TYPE_NONE); 81 struct user_ta_ctx *utc = NULL; 82 83 if (exp_pt != param_types) 84 return TEE_ERROR_BAD_PARAMETERS; 85 86 if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE || 87 params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE || 88 params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE) 89 return TEE_ERROR_BAD_PARAMETERS; 90 91 utc = to_user_ta_ctx(s->ctx); 92 93 /* 94 * The derived key shall not end up in non-secure memory by 95 * mistake. 96 * 97 * Note that we're allowing shared memory as long as it's 98 * secure. This is needed because a TA always uses shared memory 99 * when communicating with another TA. 100 */ 101 access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER | 102 TEE_MEMORY_ACCESS_SECURE; 103 res = tee_mmu_check_access_rights(utc, access_flags, 104 (uaddr_t)params[1].memref.buffer, 105 params[1].memref.size); 106 if (res != TEE_SUCCESS) 107 return TEE_ERROR_SECURITY; 108 109 /* Take extra data into account. */ 110 if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len)) 111 return TEE_ERROR_SECURITY; 112 113 data = calloc(data_len, 1); 114 if (!data) 115 return TEE_ERROR_OUT_OF_MEMORY; 116 117 memcpy(data, &s->ctx->uuid, sizeof(TEE_UUID)); 118 119 /* Append the user provided data */ 120 memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer, 121 params[0].memref.size); 122 123 res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, 124 params[1].memref.buffer, 125 params[1].memref.size); 126 free(data); 127 128 return res; 129 } 130 131 static TEE_Result system_map_zi(struct tee_ta_session *s, uint32_t param_types, 132 TEE_Param params[TEE_NUM_PARAMS]) 133 { 134 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 135 TEE_PARAM_TYPE_VALUE_INOUT, 136 TEE_PARAM_TYPE_VALUE_INPUT, 137 TEE_PARAM_TYPE_NONE); 138 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 139 uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; 140 uint32_t vm_flags = VM_FLAG_EXCLUSIVE_MOBJ; 141 TEE_Result res = TEE_ERROR_GENERIC; 142 struct mobj *mobj = NULL; 143 uint32_t pad_begin = 0; 144 struct fobj *f = NULL; 145 uint32_t pad_end = 0; 146 size_t num_bytes = 0; 147 vaddr_t va = 0; 148 149 if (exp_pt != param_types) 150 return TEE_ERROR_BAD_PARAMETERS; 151 if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE) 152 return TEE_ERROR_BAD_PARAMETERS; 153 154 if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE) 155 vm_flags |= VM_FLAG_SHAREABLE; 156 157 num_bytes = params[0].value.a; 158 va = reg_pair_to_64(params[1].value.a, params[1].value.b); 159 pad_begin = params[2].value.a; 160 pad_end = params[2].value.b; 161 162 f = fobj_ta_mem_alloc(ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / 163 SMALL_PAGE_SIZE); 164 if (!f) 165 return TEE_ERROR_OUT_OF_MEMORY; 166 mobj = mobj_with_fobj_alloc(f, NULL); 167 fobj_put(f); 168 if (!mobj) 169 return TEE_ERROR_OUT_OF_MEMORY; 170 res = vm_map_pad(utc, &va, num_bytes, prot, vm_flags, 171 mobj, 0, pad_begin, pad_end); 172 if (res) 173 mobj_free(mobj); 174 else 175 reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); 176 177 return res; 178 } 179 180 static TEE_Result system_unmap(struct tee_ta_session *s, uint32_t param_types, 181 TEE_Param params[TEE_NUM_PARAMS]) 182 { 183 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 184 TEE_PARAM_TYPE_VALUE_INPUT, 185 TEE_PARAM_TYPE_NONE, 186 TEE_PARAM_TYPE_NONE); 187 188 if (exp_pt != param_types) 189 return TEE_ERROR_BAD_PARAMETERS; 190 191 if (params[0].value.b) 192 return TEE_ERROR_BAD_PARAMETERS; 193 194 return vm_unmap(to_user_ta_ctx(s->ctx), 195 reg_pair_to_64(params[1].value.a, params[1].value.b), 196 ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE)); 197 } 198 199 static void ta_bin_close(void *ptr) 200 { 201 struct bin_handle *binh = ptr; 202 203 if (binh) { 204 if (binh->op && binh->h) 205 binh->op->close(binh->h); 206 file_put(binh->f); 207 } 208 free(binh); 209 } 210 211 static TEE_Result system_open_ta_binary(struct system_ctx *ctx, 212 uint32_t param_types, 213 TEE_Param params[TEE_NUM_PARAMS]) 214 { 215 TEE_Result res = TEE_SUCCESS; 216 struct bin_handle *binh = NULL; 217 int h = 0; 218 TEE_UUID *uuid = NULL; 219 uint8_t tag[FILE_TAG_SIZE] = { 0 }; 220 unsigned int tag_len = sizeof(tag); 221 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 222 TEE_PARAM_TYPE_VALUE_OUTPUT, 223 TEE_PARAM_TYPE_NONE, 224 TEE_PARAM_TYPE_NONE); 225 226 if (exp_pt != param_types) 227 return TEE_ERROR_BAD_PARAMETERS; 228 if (params[0].memref.size != sizeof(*uuid)) 229 return TEE_ERROR_BAD_PARAMETERS; 230 231 uuid = params[0].memref.buffer; 232 233 binh = calloc(1, sizeof(*binh)); 234 if (!binh) 235 return TEE_ERROR_OUT_OF_MEMORY; 236 237 SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, struct user_ta_store_ops) { 238 DMSG("Lookup user TA ELF %pUl (%s)", 239 (void *)uuid, binh->op->description); 240 241 res = binh->op->open(uuid, &binh->h); 242 DMSG("res=0x%x", res); 243 if (res != TEE_ERROR_ITEM_NOT_FOUND && 244 res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 245 break; 246 } 247 if (res) 248 goto err; 249 250 res = binh->op->get_size(binh->h, &binh->size_bytes); 251 if (res) 252 goto err; 253 res = binh->op->get_tag(binh->h, tag, &tag_len); 254 if (res) 255 goto err; 256 binh->f = file_get_by_tag(tag, tag_len); 257 if (!binh->f) 258 goto err_oom; 259 260 h = handle_get(&ctx->db, binh); 261 if (h < 0) 262 goto err_oom; 263 264 return TEE_SUCCESS; 265 err_oom: 266 res = TEE_ERROR_OUT_OF_MEMORY; 267 err: 268 ta_bin_close(binh); 269 return res; 270 } 271 272 static TEE_Result system_close_ta_binary(struct system_ctx *ctx, 273 uint32_t param_types, 274 TEE_Param params[TEE_NUM_PARAMS]) 275 { 276 TEE_Result res = TEE_SUCCESS; 277 struct bin_handle *binh = NULL; 278 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 279 TEE_PARAM_TYPE_NONE, 280 TEE_PARAM_TYPE_NONE, 281 TEE_PARAM_TYPE_NONE); 282 283 if (exp_pt != param_types) 284 return TEE_ERROR_BAD_PARAMETERS; 285 286 if (params[0].value.b) 287 return TEE_ERROR_BAD_PARAMETERS; 288 289 binh = handle_put(&ctx->db, params[0].value.a); 290 if (!binh) 291 return TEE_ERROR_BAD_PARAMETERS; 292 293 if (binh->offs_bytes < binh->size_bytes) 294 res = binh->op->read(binh->h, NULL, 295 binh->size_bytes - binh->offs_bytes); 296 297 ta_bin_close(binh); 298 return res; 299 } 300 301 static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va, 302 size_t offs_bytes, size_t num_bytes) 303 { 304 TEE_Result res = TEE_SUCCESS; 305 size_t l = num_bytes; 306 307 if (offs_bytes < binh->offs_bytes) 308 return TEE_ERROR_BAD_STATE; 309 if (offs_bytes > binh->offs_bytes) { 310 res = binh->op->read(binh->h, NULL, 311 offs_bytes - binh->offs_bytes); 312 if (res) 313 return res; 314 binh->offs_bytes = offs_bytes; 315 } 316 317 if (binh->offs_bytes + l > binh->size_bytes) { 318 size_t rb = binh->size_bytes - binh->offs_bytes; 319 320 res = binh->op->read(binh->h, (void *)va, rb); 321 if (res) 322 return res; 323 memset((uint8_t *)va + rb, 0, l - rb); 324 binh->offs_bytes = binh->size_bytes; 325 } else { 326 res = binh->op->read(binh->h, (void *)va, l); 327 if (res) 328 return res; 329 binh->offs_bytes += l; 330 } 331 332 return TEE_SUCCESS; 333 } 334 335 static TEE_Result system_map_ta_binary(struct system_ctx *ctx, 336 struct tee_ta_session *s, 337 uint32_t param_types, 338 TEE_Param params[TEE_NUM_PARAMS]) 339 { 340 const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_SHAREABLE | 341 PTA_SYSTEM_MAP_FLAG_WRITEABLE | 342 PTA_SYSTEM_MAP_FLAG_EXECUTABLE; 343 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 344 TEE_PARAM_TYPE_VALUE_INPUT, 345 TEE_PARAM_TYPE_VALUE_INOUT, 346 TEE_PARAM_TYPE_VALUE_INPUT); 347 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 348 struct bin_handle *binh = NULL; 349 TEE_Result res = TEE_SUCCESS; 350 struct file_slice *fs = NULL; 351 bool file_is_locked = false; 352 struct mobj *mobj = NULL; 353 uint32_t offs_bytes = 0; 354 uint32_t offs_pages = 0; 355 uint32_t num_bytes = 0; 356 uint32_t pad_begin = 0; 357 uint32_t pad_end = 0; 358 size_t num_pages = 0; 359 uint32_t flags = 0; 360 uint32_t prot = 0; 361 vaddr_t va = 0; 362 363 if (exp_pt != param_types) 364 return TEE_ERROR_BAD_PARAMETERS; 365 366 binh = handle_lookup(&ctx->db, params[0].value.a); 367 if (!binh) 368 return TEE_ERROR_BAD_PARAMETERS; 369 flags = params[0].value.b; 370 offs_bytes = params[1].value.a; 371 num_bytes = params[1].value.b; 372 va = reg_pair_to_64(params[2].value.a, params[2].value.b); 373 pad_begin = params[3].value.a; 374 pad_end = params[3].value.b; 375 376 if ((flags & accept_flags) != flags) 377 return TEE_ERROR_BAD_PARAMETERS; 378 379 if ((flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE) && 380 (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 381 return TEE_ERROR_BAD_PARAMETERS; 382 383 if ((flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) && 384 (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 385 return TEE_ERROR_BAD_PARAMETERS; 386 387 if (offs_bytes & SMALL_PAGE_MASK) 388 return TEE_ERROR_BAD_PARAMETERS; 389 390 prot = TEE_MATTR_UR | TEE_MATTR_PR; 391 if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE) 392 prot |= TEE_MATTR_UW | TEE_MATTR_PW; 393 if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) 394 prot |= TEE_MATTR_UX; 395 396 offs_pages = offs_bytes >> SMALL_PAGE_SHIFT; 397 num_pages = ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; 398 399 if (!file_trylock(binh->f)) { 400 /* 401 * Before we can block on the file lock we must make all 402 * our page tables available for reclaiming in order to 403 * avoid a dead-lock with the other thread (which already 404 * is holding the file lock) mapping lots of memory below. 405 */ 406 tee_mmu_set_ctx(NULL); 407 file_lock(binh->f); 408 tee_mmu_set_ctx(s->ctx); 409 } 410 file_is_locked = true; 411 fs = file_find_slice(binh->f, offs_pages); 412 if (fs) { 413 /* If there's registered slice it has to match */ 414 if (fs->page_offset != offs_pages || 415 num_pages > fs->fobj->num_pages) { 416 res = TEE_ERROR_BAD_PARAMETERS; 417 goto err; 418 } 419 420 /* If there's a slice we must be mapping shareable */ 421 if (!(flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE)) { 422 res = TEE_ERROR_BAD_PARAMETERS; 423 goto err; 424 } 425 426 mobj = mobj_with_fobj_alloc(fs->fobj, binh->f); 427 if (!mobj) { 428 res = TEE_ERROR_OUT_OF_MEMORY; 429 goto err; 430 } 431 res = vm_map_pad(utc, &va, num_pages * SMALL_PAGE_SIZE, prot, 432 VM_FLAG_READONLY | VM_FLAG_EXCLUSIVE_MOBJ, 433 mobj, 0, pad_begin, pad_end); 434 if (res) 435 goto err; 436 } else { 437 struct fobj *f = fobj_ta_mem_alloc(num_pages); 438 struct file *file = NULL; 439 uint32_t vm_flags = VM_FLAG_EXCLUSIVE_MOBJ; 440 441 if (!f) { 442 res = TEE_ERROR_OUT_OF_MEMORY; 443 goto err; 444 } 445 if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) { 446 file = binh->f; 447 vm_flags |= VM_FLAG_READONLY; 448 } 449 450 mobj = mobj_with_fobj_alloc(f, file); 451 fobj_put(f); 452 if (!mobj) { 453 res = TEE_ERROR_OUT_OF_MEMORY; 454 goto err; 455 } 456 res = vm_map_pad(utc, &va, num_pages * SMALL_PAGE_SIZE, 457 TEE_MATTR_PRW, vm_flags, mobj, 0, 458 pad_begin, pad_end); 459 if (res) 460 goto err; 461 res = binh_copy_to(binh, va, offs_bytes, num_bytes); 462 if (res) 463 goto err_unmap_va; 464 res = vm_set_prot(utc, va, num_pages * SMALL_PAGE_SIZE, prot); 465 if (res) 466 goto err_unmap_va; 467 468 /* 469 * The context currently is active set it again to update 470 * the mapping. 471 */ 472 tee_mmu_set_ctx(s->ctx); 473 474 if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) { 475 res = file_add_slice(binh->f, f, offs_pages); 476 if (res) 477 goto err_unmap_va; 478 } 479 } 480 481 file_unlock(binh->f); 482 483 reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 484 return TEE_SUCCESS; 485 486 err_unmap_va: 487 if (vm_unmap(utc, va, num_pages * SMALL_PAGE_SIZE)) 488 panic(); 489 490 /* 491 * The context currently is active set it again to update 492 * the mapping. 493 */ 494 tee_mmu_set_ctx(s->ctx); 495 496 err: 497 mobj_free(mobj); 498 if (file_is_locked) 499 file_unlock(binh->f); 500 501 return res; 502 } 503 504 static TEE_Result system_copy_from_ta_binary(struct system_ctx *ctx, 505 uint32_t param_types, 506 TEE_Param params[TEE_NUM_PARAMS]) 507 { 508 struct bin_handle *binh = NULL; 509 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 510 TEE_PARAM_TYPE_MEMREF_OUTPUT, 511 TEE_PARAM_TYPE_NONE, 512 TEE_PARAM_TYPE_NONE); 513 514 if (exp_pt != param_types) 515 return TEE_ERROR_BAD_PARAMETERS; 516 517 binh = handle_lookup(&ctx->db, params[0].value.a); 518 if (!binh) 519 return TEE_ERROR_BAD_PARAMETERS; 520 521 return binh_copy_to(binh, (vaddr_t)params[1].memref.buffer, 522 params[0].value.b, params[1].memref.size); 523 } 524 525 static TEE_Result system_set_prot(struct tee_ta_session *s, 526 uint32_t param_types, 527 TEE_Param params[TEE_NUM_PARAMS]) 528 { 529 const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_WRITEABLE | 530 PTA_SYSTEM_MAP_FLAG_EXECUTABLE; 531 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 532 TEE_PARAM_TYPE_VALUE_INPUT, 533 TEE_PARAM_TYPE_NONE, 534 TEE_PARAM_TYPE_NONE); 535 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 536 uint32_t prot = TEE_MATTR_UR | TEE_MATTR_PR; 537 TEE_Result res = TEE_SUCCESS; 538 uint32_t vm_flags = 0; 539 uint32_t flags = 0; 540 vaddr_t va = 0; 541 size_t sz = 0; 542 543 if (exp_pt != param_types) 544 return TEE_ERROR_BAD_PARAMETERS; 545 546 flags = params[0].value.b; 547 548 if ((flags & accept_flags) != flags) 549 return TEE_ERROR_BAD_PARAMETERS; 550 if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE) 551 prot |= TEE_MATTR_UW | TEE_MATTR_PW; 552 if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) 553 prot |= TEE_MATTR_UX; 554 555 va = reg_pair_to_64(params[1].value.a, params[1].value.b), 556 sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE); 557 558 res = vm_get_flags(utc, va, sz, &vm_flags); 559 if (res) 560 return res; 561 562 /* 563 * If the segment is a mapping of a part of a file (vm_flags & 564 * VM_FLAG_READONLY) it cannot be made writeable as all mapped 565 * files are mapped read-only. 566 */ 567 if ((vm_flags & VM_FLAG_READONLY) && 568 (prot & (TEE_MATTR_UW | TEE_MATTR_PW))) 569 return TEE_ERROR_ACCESS_DENIED; 570 571 return vm_set_prot(utc, va, sz, prot); 572 } 573 574 static TEE_Result system_remap(struct tee_ta_session *s, uint32_t param_types, 575 TEE_Param params[TEE_NUM_PARAMS]) 576 { 577 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 578 TEE_PARAM_TYPE_VALUE_INPUT, 579 TEE_PARAM_TYPE_VALUE_INOUT, 580 TEE_PARAM_TYPE_VALUE_INPUT); 581 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 582 TEE_Result res = TEE_SUCCESS; 583 uint32_t num_bytes = 0; 584 uint32_t pad_begin = 0; 585 uint32_t pad_end = 0; 586 vaddr_t old_va = 0; 587 vaddr_t new_va = 0; 588 589 if (exp_pt != param_types) 590 return TEE_ERROR_BAD_PARAMETERS; 591 592 num_bytes = params[0].value.a; 593 old_va = reg_pair_to_64(params[1].value.a, params[1].value.b); 594 new_va = reg_pair_to_64(params[2].value.a, params[2].value.b); 595 pad_begin = params[3].value.a; 596 pad_end = params[3].value.b; 597 598 res = vm_remap(utc, &new_va, old_va, num_bytes, pad_begin, pad_end); 599 if (!res) 600 reg_pair_from_64(new_va, ¶ms[2].value.a, 601 ¶ms[2].value.b); 602 603 return res; 604 } 605 606 /* ldelf has the same architecture/register width as the kernel */ 607 #ifdef ARM32 608 static const bool is_arm32 = true; 609 #else 610 static const bool is_arm32; 611 #endif 612 613 static TEE_Result call_ldelf_dlopen(struct user_ta_ctx *utc, TEE_UUID *uuid, 614 uint32_t flags) 615 { 616 uaddr_t usr_stack = utc->ldelf_stack_ptr; 617 TEE_Result res = TEE_ERROR_GENERIC; 618 struct dl_entry_arg *arg = NULL; 619 uint32_t panic_code = 0; 620 uint32_t panicked = 0; 621 622 assert(uuid); 623 624 usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); 625 arg = (struct dl_entry_arg *)usr_stack; 626 627 res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ | 628 TEE_MEMORY_ACCESS_WRITE | 629 TEE_MEMORY_ACCESS_ANY_OWNER, 630 (uaddr_t)arg, sizeof(*arg)); 631 if (res) { 632 EMSG("ldelf stack is inaccessible!"); 633 return res; 634 } 635 636 memset(arg, 0, sizeof(*arg)); 637 arg->cmd = LDELF_DL_ENTRY_DLOPEN; 638 arg->dlopen.uuid = *uuid; 639 arg->dlopen.flags = flags; 640 641 res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 642 usr_stack, utc->dl_entry_func, 643 is_arm32, &panicked, &panic_code); 644 if (panicked) { 645 EMSG("ldelf dl_entry function panicked"); 646 abort_print_current_ta(); 647 res = TEE_ERROR_TARGET_DEAD; 648 } 649 if (!res) 650 res = arg->ret; 651 652 return res; 653 } 654 655 static TEE_Result call_ldelf_dlsym(struct user_ta_ctx *utc, TEE_UUID *uuid, 656 const char *sym, size_t maxlen, vaddr_t *val) 657 { 658 uaddr_t usr_stack = utc->ldelf_stack_ptr; 659 TEE_Result res = TEE_ERROR_GENERIC; 660 struct dl_entry_arg *arg = NULL; 661 uint32_t panic_code = 0; 662 uint32_t panicked = 0; 663 size_t len = strnlen(sym, maxlen); 664 665 if (len == maxlen) 666 return TEE_ERROR_BAD_PARAMETERS; 667 668 usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT); 669 arg = (struct dl_entry_arg *)usr_stack; 670 671 res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ | 672 TEE_MEMORY_ACCESS_WRITE | 673 TEE_MEMORY_ACCESS_ANY_OWNER, 674 (uaddr_t)arg, 675 sizeof(*arg) + len + 1); 676 if (res) { 677 EMSG("ldelf stack is inaccessible!"); 678 return res; 679 } 680 681 memset(arg, 0, sizeof(*arg)); 682 arg->cmd = LDELF_DL_ENTRY_DLSYM; 683 arg->dlsym.uuid = *uuid; 684 memcpy(arg->dlsym.symbol, sym, len); 685 arg->dlsym.symbol[len + 1] = '\0'; 686 687 res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 688 usr_stack, utc->dl_entry_func, 689 is_arm32, &panicked, &panic_code); 690 if (panicked) { 691 EMSG("ldelf dl_entry function panicked"); 692 abort_print_current_ta(); 693 res = TEE_ERROR_TARGET_DEAD; 694 } 695 if (!res) { 696 res = arg->ret; 697 if (!res) 698 *val = arg->dlsym.val; 699 } 700 701 return res; 702 } 703 704 static TEE_Result system_dlopen(struct tee_ta_session *cs, uint32_t param_types, 705 TEE_Param params[TEE_NUM_PARAMS]) 706 { 707 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 708 TEE_PARAM_TYPE_VALUE_INPUT, 709 TEE_PARAM_TYPE_NONE, 710 TEE_PARAM_TYPE_NONE); 711 TEE_Result res = TEE_ERROR_GENERIC; 712 struct tee_ta_session *s = NULL; 713 struct user_ta_ctx *utc = NULL; 714 TEE_UUID *uuid = NULL; 715 uint32_t flags = 0; 716 717 if (exp_pt != param_types) 718 return TEE_ERROR_BAD_PARAMETERS; 719 720 uuid = params[0].memref.buffer; 721 if (!uuid || params[0].memref.size != sizeof(*uuid)) 722 return TEE_ERROR_BAD_PARAMETERS; 723 724 flags = params[1].value.a; 725 726 utc = to_user_ta_ctx(cs->ctx); 727 728 s = tee_ta_pop_current_session(); 729 res = call_ldelf_dlopen(utc, uuid, flags); 730 tee_ta_push_current_session(s); 731 732 return res; 733 } 734 735 static TEE_Result system_dlsym(struct tee_ta_session *cs, uint32_t param_types, 736 TEE_Param params[TEE_NUM_PARAMS]) 737 { 738 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 739 TEE_PARAM_TYPE_MEMREF_INPUT, 740 TEE_PARAM_TYPE_VALUE_OUTPUT, 741 TEE_PARAM_TYPE_NONE); 742 TEE_Result res = TEE_ERROR_GENERIC; 743 struct tee_ta_session *s = NULL; 744 struct user_ta_ctx *utc = NULL; 745 const char *sym = NULL; 746 TEE_UUID *uuid = NULL; 747 size_t maxlen = 0; 748 vaddr_t va = 0; 749 750 if (exp_pt != param_types) 751 return TEE_ERROR_BAD_PARAMETERS; 752 753 uuid = params[0].memref.buffer; 754 if (uuid && params[0].memref.size != sizeof(*uuid)) 755 return TEE_ERROR_BAD_PARAMETERS; 756 757 sym = params[1].memref.buffer; 758 if (!sym) 759 return TEE_ERROR_BAD_PARAMETERS; 760 maxlen = params[1].memref.size; 761 762 utc = to_user_ta_ctx(cs->ctx); 763 764 s = tee_ta_pop_current_session(); 765 res = call_ldelf_dlsym(utc, uuid, sym, maxlen, &va); 766 tee_ta_push_current_session(s); 767 768 if (!res) 769 reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 770 771 return res; 772 } 773 774 static TEE_Result open_session(uint32_t param_types __unused, 775 TEE_Param params[TEE_NUM_PARAMS] __unused, 776 void **sess_ctx) 777 { 778 struct tee_ta_session *s = NULL; 779 struct system_ctx *ctx = NULL; 780 781 /* Check that we're called from a user TA */ 782 s = tee_ta_get_calling_session(); 783 if (!s) 784 return TEE_ERROR_ACCESS_DENIED; 785 if (!is_user_ta_ctx(s->ctx)) 786 return TEE_ERROR_ACCESS_DENIED; 787 788 ctx = calloc(1, sizeof(*ctx)); 789 if (!ctx) 790 return TEE_ERROR_OUT_OF_MEMORY; 791 792 *sess_ctx = ctx; 793 794 return TEE_SUCCESS; 795 } 796 797 static void close_session(void *sess_ctx) 798 { 799 struct system_ctx *ctx = sess_ctx; 800 801 handle_db_destroy(&ctx->db, ta_bin_close); 802 free(ctx); 803 } 804 805 static TEE_Result invoke_command(void *sess_ctx, uint32_t cmd_id, 806 uint32_t param_types, 807 TEE_Param params[TEE_NUM_PARAMS]) 808 { 809 struct tee_ta_session *s = tee_ta_get_calling_session(); 810 811 switch (cmd_id) { 812 case PTA_SYSTEM_ADD_RNG_ENTROPY: 813 return system_rng_reseed(s, param_types, params); 814 case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY: 815 return system_derive_ta_unique_key(s, param_types, params); 816 case PTA_SYSTEM_MAP_ZI: 817 return system_map_zi(s, param_types, params); 818 case PTA_SYSTEM_UNMAP: 819 return system_unmap(s, param_types, params); 820 case PTA_SYSTEM_OPEN_TA_BINARY: 821 return system_open_ta_binary(sess_ctx, param_types, params); 822 case PTA_SYSTEM_CLOSE_TA_BINARY: 823 return system_close_ta_binary(sess_ctx, param_types, params); 824 case PTA_SYSTEM_MAP_TA_BINARY: 825 return system_map_ta_binary(sess_ctx, s, param_types, params); 826 case PTA_SYSTEM_COPY_FROM_TA_BINARY: 827 return system_copy_from_ta_binary(sess_ctx, param_types, 828 params); 829 case PTA_SYSTEM_SET_PROT: 830 return system_set_prot(s, param_types, params); 831 case PTA_SYSTEM_REMAP: 832 return system_remap(s, param_types, params); 833 case PTA_SYSTEM_DLOPEN: 834 return system_dlopen(s, param_types, params); 835 case PTA_SYSTEM_DLSYM: 836 return system_dlsym(s, param_types, params); 837 default: 838 break; 839 } 840 841 return TEE_ERROR_NOT_IMPLEMENTED; 842 } 843 844 pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta", 845 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 846 .open_session_entry_point = open_session, 847 .close_session_entry_point = close_session, 848 .invoke_command_entry_point = invoke_command); 849