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 TEE_Result res = TEE_ERROR_GENERIC; 141 struct mobj *mobj = NULL; 142 uint32_t pad_begin = 0; 143 uint32_t vm_flags = 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 mobj_put(mobj); 173 if (!res) 174 reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); 175 176 return res; 177 } 178 179 static TEE_Result system_unmap(struct tee_ta_session *s, uint32_t param_types, 180 TEE_Param params[TEE_NUM_PARAMS]) 181 { 182 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 183 TEE_PARAM_TYPE_VALUE_INPUT, 184 TEE_PARAM_TYPE_NONE, 185 TEE_PARAM_TYPE_NONE); 186 187 if (exp_pt != param_types) 188 return TEE_ERROR_BAD_PARAMETERS; 189 190 if (params[0].value.b) 191 return TEE_ERROR_BAD_PARAMETERS; 192 193 return vm_unmap(to_user_ta_ctx(s->ctx), 194 reg_pair_to_64(params[1].value.a, params[1].value.b), 195 ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE)); 196 } 197 198 static void ta_bin_close(void *ptr) 199 { 200 struct bin_handle *binh = ptr; 201 202 if (binh) { 203 if (binh->op && binh->h) 204 binh->op->close(binh->h); 205 file_put(binh->f); 206 } 207 free(binh); 208 } 209 210 static TEE_Result system_open_ta_binary(struct system_ctx *ctx, 211 uint32_t param_types, 212 TEE_Param params[TEE_NUM_PARAMS]) 213 { 214 TEE_Result res = TEE_SUCCESS; 215 struct bin_handle *binh = NULL; 216 int h = 0; 217 TEE_UUID *uuid = NULL; 218 uint8_t tag[FILE_TAG_SIZE] = { 0 }; 219 unsigned int tag_len = sizeof(tag); 220 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 221 TEE_PARAM_TYPE_VALUE_OUTPUT, 222 TEE_PARAM_TYPE_NONE, 223 TEE_PARAM_TYPE_NONE); 224 225 if (exp_pt != param_types) 226 return TEE_ERROR_BAD_PARAMETERS; 227 if (params[0].memref.size != sizeof(*uuid)) 228 return TEE_ERROR_BAD_PARAMETERS; 229 230 uuid = params[0].memref.buffer; 231 232 binh = calloc(1, sizeof(*binh)); 233 if (!binh) 234 return TEE_ERROR_OUT_OF_MEMORY; 235 236 SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, struct user_ta_store_ops) { 237 DMSG("Lookup user TA ELF %pUl (%s)", 238 (void *)uuid, binh->op->description); 239 240 res = binh->op->open(uuid, &binh->h); 241 DMSG("res=0x%x", res); 242 if (res != TEE_ERROR_ITEM_NOT_FOUND && 243 res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 244 break; 245 } 246 if (res) 247 goto err; 248 249 res = binh->op->get_size(binh->h, &binh->size_bytes); 250 if (res) 251 goto err; 252 res = binh->op->get_tag(binh->h, tag, &tag_len); 253 if (res) 254 goto err; 255 binh->f = file_get_by_tag(tag, tag_len); 256 if (!binh->f) 257 goto err_oom; 258 259 h = handle_get(&ctx->db, binh); 260 if (h < 0) 261 goto err_oom; 262 263 return TEE_SUCCESS; 264 err_oom: 265 res = TEE_ERROR_OUT_OF_MEMORY; 266 err: 267 ta_bin_close(binh); 268 return res; 269 } 270 271 static TEE_Result system_close_ta_binary(struct system_ctx *ctx, 272 uint32_t param_types, 273 TEE_Param params[TEE_NUM_PARAMS]) 274 { 275 TEE_Result res = TEE_SUCCESS; 276 struct bin_handle *binh = NULL; 277 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 278 TEE_PARAM_TYPE_NONE, 279 TEE_PARAM_TYPE_NONE, 280 TEE_PARAM_TYPE_NONE); 281 282 if (exp_pt != param_types) 283 return TEE_ERROR_BAD_PARAMETERS; 284 285 if (params[0].value.b) 286 return TEE_ERROR_BAD_PARAMETERS; 287 288 binh = handle_put(&ctx->db, params[0].value.a); 289 if (!binh) 290 return TEE_ERROR_BAD_PARAMETERS; 291 292 if (binh->offs_bytes < binh->size_bytes) 293 res = binh->op->read(binh->h, NULL, 294 binh->size_bytes - binh->offs_bytes); 295 296 ta_bin_close(binh); 297 return res; 298 } 299 300 static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va, 301 size_t offs_bytes, size_t num_bytes) 302 { 303 TEE_Result res = TEE_SUCCESS; 304 size_t l = num_bytes; 305 306 if (offs_bytes < binh->offs_bytes) 307 return TEE_ERROR_BAD_STATE; 308 if (offs_bytes > binh->offs_bytes) { 309 res = binh->op->read(binh->h, NULL, 310 offs_bytes - binh->offs_bytes); 311 if (res) 312 return res; 313 binh->offs_bytes = offs_bytes; 314 } 315 316 if (binh->offs_bytes + l > binh->size_bytes) { 317 size_t rb = binh->size_bytes - binh->offs_bytes; 318 319 res = binh->op->read(binh->h, (void *)va, rb); 320 if (res) 321 return res; 322 memset((uint8_t *)va + rb, 0, l - rb); 323 binh->offs_bytes = binh->size_bytes; 324 } else { 325 res = binh->op->read(binh->h, (void *)va, l); 326 if (res) 327 return res; 328 binh->offs_bytes += l; 329 } 330 331 return TEE_SUCCESS; 332 } 333 334 static TEE_Result system_map_ta_binary(struct system_ctx *ctx, 335 struct tee_ta_session *s, 336 uint32_t param_types, 337 TEE_Param params[TEE_NUM_PARAMS]) 338 { 339 const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_SHAREABLE | 340 PTA_SYSTEM_MAP_FLAG_WRITEABLE | 341 PTA_SYSTEM_MAP_FLAG_EXECUTABLE; 342 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 343 TEE_PARAM_TYPE_VALUE_INPUT, 344 TEE_PARAM_TYPE_VALUE_INOUT, 345 TEE_PARAM_TYPE_VALUE_INPUT); 346 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 347 struct bin_handle *binh = NULL; 348 TEE_Result res = TEE_SUCCESS; 349 struct file_slice *fs = NULL; 350 bool file_is_locked = false; 351 struct mobj *mobj = NULL; 352 uint32_t offs_bytes = 0; 353 uint32_t offs_pages = 0; 354 uint32_t num_bytes = 0; 355 uint32_t pad_begin = 0; 356 uint32_t pad_end = 0; 357 size_t num_pages = 0; 358 uint32_t flags = 0; 359 uint32_t prot = 0; 360 vaddr_t va = 0; 361 362 if (exp_pt != param_types) 363 return TEE_ERROR_BAD_PARAMETERS; 364 365 binh = handle_lookup(&ctx->db, params[0].value.a); 366 if (!binh) 367 return TEE_ERROR_BAD_PARAMETERS; 368 flags = params[0].value.b; 369 offs_bytes = params[1].value.a; 370 num_bytes = params[1].value.b; 371 va = reg_pair_to_64(params[2].value.a, params[2].value.b); 372 pad_begin = params[3].value.a; 373 pad_end = params[3].value.b; 374 375 if ((flags & accept_flags) != flags) 376 return TEE_ERROR_BAD_PARAMETERS; 377 378 if ((flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE) && 379 (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 380 return TEE_ERROR_BAD_PARAMETERS; 381 382 if ((flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) && 383 (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 384 return TEE_ERROR_BAD_PARAMETERS; 385 386 if (offs_bytes & SMALL_PAGE_MASK) 387 return TEE_ERROR_BAD_PARAMETERS; 388 389 prot = TEE_MATTR_UR | TEE_MATTR_PR; 390 if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE) 391 prot |= TEE_MATTR_UW | TEE_MATTR_PW; 392 if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) 393 prot |= TEE_MATTR_UX; 394 395 offs_pages = offs_bytes >> SMALL_PAGE_SHIFT; 396 num_pages = ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; 397 398 if (!file_trylock(binh->f)) { 399 /* 400 * Before we can block on the file lock we must make all 401 * our page tables available for reclaiming in order to 402 * avoid a dead-lock with the other thread (which already 403 * is holding the file lock) mapping lots of memory below. 404 */ 405 tee_mmu_set_ctx(NULL); 406 file_lock(binh->f); 407 tee_mmu_set_ctx(s->ctx); 408 } 409 file_is_locked = true; 410 fs = file_find_slice(binh->f, offs_pages); 411 if (fs) { 412 /* If there's registered slice it has to match */ 413 if (fs->page_offset != offs_pages || 414 num_pages > fs->fobj->num_pages) { 415 res = TEE_ERROR_BAD_PARAMETERS; 416 goto err; 417 } 418 419 /* If there's a slice we must be mapping shareable */ 420 if (!(flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE)) { 421 res = TEE_ERROR_BAD_PARAMETERS; 422 goto err; 423 } 424 425 mobj = mobj_with_fobj_alloc(fs->fobj, binh->f); 426 if (!mobj) { 427 res = TEE_ERROR_OUT_OF_MEMORY; 428 goto err; 429 } 430 res = vm_map_pad(utc, &va, num_pages * SMALL_PAGE_SIZE, 431 prot, VM_FLAG_READONLY, 432 mobj, 0, pad_begin, pad_end); 433 mobj_put(mobj); 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 = 0; 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 mobj_put(mobj); 460 if (res) 461 goto err; 462 res = binh_copy_to(binh, va, offs_bytes, num_bytes); 463 if (res) 464 goto err_unmap_va; 465 res = vm_set_prot(utc, va, num_pages * SMALL_PAGE_SIZE, prot); 466 if (res) 467 goto err_unmap_va; 468 469 /* 470 * The context currently is active set it again to update 471 * the mapping. 472 */ 473 tee_mmu_set_ctx(s->ctx); 474 475 if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) { 476 res = file_add_slice(binh->f, f, offs_pages); 477 if (res) 478 goto err_unmap_va; 479 } 480 } 481 482 file_unlock(binh->f); 483 484 reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 485 return TEE_SUCCESS; 486 487 err_unmap_va: 488 if (vm_unmap(utc, va, num_pages * SMALL_PAGE_SIZE)) 489 panic(); 490 491 /* 492 * The context currently is active set it again to update 493 * the mapping. 494 */ 495 tee_mmu_set_ctx(s->ctx); 496 497 err: 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] = '\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