1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 */ 5 6 #include <kernel/mutex.h> 7 #include <kernel/tee_misc.h> 8 #include <kernel/tee_ta_manager.h> 9 #include <mm/tee_mmu.h> 10 #include <string.h> 11 #include <tee_api_defines_extensions.h> 12 #include <tee_api_defines.h> 13 #include <tee/fs_dirfile.h> 14 #include <tee/tee_fs.h> 15 #include <tee/tee_obj.h> 16 #include <tee/tee_pobj.h> 17 #include <tee/tee_svc_cryp.h> 18 #include <tee/tee_svc.h> 19 #include <tee/tee_svc_storage.h> 20 #include <trace.h> 21 22 const struct tee_file_operations *tee_svc_storage_file_ops(uint32_t storage_id) 23 { 24 25 switch (storage_id) { 26 case TEE_STORAGE_PRIVATE: 27 #if defined(CFG_REE_FS) 28 return &ree_fs_ops; 29 #elif defined(CFG_RPMB_FS) 30 return &rpmb_fs_ops; 31 #else 32 #error At least one filesystem must be enabled. 33 #endif 34 #ifdef CFG_REE_FS 35 case TEE_STORAGE_PRIVATE_REE: 36 return &ree_fs_ops; 37 #endif 38 #ifdef CFG_RPMB_FS 39 case TEE_STORAGE_PRIVATE_RPMB: 40 return &rpmb_fs_ops; 41 #endif 42 default: 43 return NULL; 44 } 45 } 46 47 /* Header of GP formated secure storage files */ 48 struct tee_svc_storage_head { 49 uint32_t attr_size; 50 uint32_t keySize; 51 uint32_t maxKeySize; 52 uint32_t objectUsage; 53 uint32_t objectType; 54 uint32_t have_attrs; 55 }; 56 57 struct tee_storage_enum { 58 TAILQ_ENTRY(tee_storage_enum) link; 59 struct tee_fs_dir *dir; 60 const struct tee_file_operations *fops; 61 }; 62 63 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, 64 uint32_t enum_id, 65 struct tee_storage_enum **e_out) 66 { 67 struct tee_storage_enum *e; 68 69 TAILQ_FOREACH(e, &utc->storage_enums, link) { 70 if (enum_id == (vaddr_t)e) { 71 *e_out = e; 72 return TEE_SUCCESS; 73 } 74 } 75 return TEE_ERROR_BAD_PARAMETERS; 76 } 77 78 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, 79 struct tee_storage_enum *e) 80 { 81 if (e == NULL || utc == NULL) 82 return TEE_ERROR_BAD_PARAMETERS; 83 84 TAILQ_REMOVE(&utc->storage_enums, e, link); 85 86 if (e->fops) 87 e->fops->closedir(e->dir); 88 89 e->dir = NULL; 90 e->fops = NULL; 91 92 free(e); 93 94 return TEE_SUCCESS; 95 } 96 97 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ 98 TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen, 99 struct tee_pobj *po, bool transient) 100 { 101 uint8_t *file = buf; 102 uint32_t pos = 0; 103 uint32_t hslen = 1 /* Leading slash */ 104 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) 105 + 1; /* Intermediate slash */ 106 107 /* +1 for the '.' (temporary persistent object) */ 108 if (transient) 109 hslen++; 110 111 if (blen < hslen) 112 return TEE_ERROR_SHORT_BUFFER; 113 114 file[pos++] = '/'; 115 pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], 116 sizeof(TEE_UUID), hslen); 117 file[pos++] = '/'; 118 119 if (transient) 120 file[pos++] = '.'; 121 122 tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); 123 124 return TEE_SUCCESS; 125 } 126 127 #ifdef CFG_REE_FS 128 /* "/dirf.db" or "/<file number>" */ 129 TEE_Result 130 tee_svc_storage_create_filename_dfh(void *buf, size_t blen, 131 const struct tee_fs_dirfile_fileh *dfh) 132 { 133 char *file = buf; 134 size_t pos = 0; 135 size_t l; 136 137 if (pos >= blen) 138 return TEE_ERROR_SHORT_BUFFER; 139 140 file[pos] = '/'; 141 pos++; 142 if (pos >= blen) 143 return TEE_ERROR_SHORT_BUFFER; 144 145 l = blen - pos; 146 return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l); 147 } 148 #endif 149 150 /* "/TA_uuid" */ 151 TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen, 152 const TEE_UUID *uuid) 153 { 154 uint8_t *dir = buf; 155 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; 156 157 if (blen < hslen) 158 return TEE_ERROR_SHORT_BUFFER; 159 160 dir[0] = '/'; 161 tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); 162 163 return TEE_SUCCESS; 164 } 165 166 static TEE_Result tee_svc_storage_remove_corrupt_obj( 167 struct tee_ta_session *sess, 168 struct tee_obj *o) 169 { 170 o->pobj->fops->remove(o->pobj); 171 tee_obj_close(to_user_ta_ctx(sess->ctx), o); 172 173 return TEE_SUCCESS; 174 } 175 176 static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) 177 { 178 TEE_Result res = TEE_SUCCESS; 179 size_t bytes; 180 struct tee_svc_storage_head head; 181 const struct tee_file_operations *fops = o->pobj->fops; 182 void *attr = NULL; 183 size_t size; 184 185 assert(!o->fh); 186 res = fops->open(o->pobj, &size, &o->fh); 187 if (res != TEE_SUCCESS) 188 goto exit; 189 190 /* read head */ 191 bytes = sizeof(struct tee_svc_storage_head); 192 res = fops->read(o->fh, 0, &head, &bytes); 193 if (res != TEE_SUCCESS) { 194 if (res == TEE_ERROR_CORRUPT_OBJECT) 195 EMSG("Head corrupt\n"); 196 goto exit; 197 } 198 199 if (bytes != sizeof(struct tee_svc_storage_head)) { 200 res = TEE_ERROR_BAD_FORMAT; 201 goto exit; 202 } 203 204 res = tee_obj_set_type(o, head.objectType, head.maxKeySize); 205 if (res != TEE_SUCCESS) 206 goto exit; 207 208 o->ds_pos = sizeof(struct tee_svc_storage_head) + head.attr_size; 209 if (head.attr_size) { 210 attr = malloc(head.attr_size); 211 if (!attr) { 212 res = TEE_ERROR_OUT_OF_MEMORY; 213 goto exit; 214 } 215 216 /* read meta */ 217 bytes = head.attr_size; 218 res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), 219 attr, &bytes); 220 if (res == TEE_ERROR_OUT_OF_MEMORY) 221 goto exit; 222 if (res != TEE_SUCCESS || bytes != head.attr_size) 223 res = TEE_ERROR_CORRUPT_OBJECT; 224 if (res) 225 goto exit; 226 } 227 228 res = tee_obj_attr_from_binary(o, attr, head.attr_size); 229 if (res != TEE_SUCCESS) 230 goto exit; 231 232 o->info.dataSize = size - sizeof(head) - head.attr_size; 233 o->info.keySize = head.keySize; 234 o->info.objectUsage = head.objectUsage; 235 o->info.objectType = head.objectType; 236 o->have_attrs = head.have_attrs; 237 238 exit: 239 free(attr); 240 241 return res; 242 } 243 244 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 245 size_t object_id_len, unsigned long flags, 246 uint32_t *obj) 247 { 248 TEE_Result res; 249 struct tee_ta_session *sess; 250 struct tee_obj *o = NULL; 251 char *file = NULL; 252 struct tee_pobj *po = NULL; 253 struct user_ta_ctx *utc; 254 size_t attr_size; 255 const struct tee_file_operations *fops = 256 tee_svc_storage_file_ops(storage_id); 257 258 if (!fops) { 259 res = TEE_ERROR_ITEM_NOT_FOUND; 260 goto exit; 261 } 262 263 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 264 res = TEE_ERROR_BAD_PARAMETERS; 265 goto exit; 266 } 267 268 res = tee_ta_get_current_session(&sess); 269 if (res != TEE_SUCCESS) 270 goto err; 271 utc = to_user_ta_ctx(sess->ctx); 272 273 res = tee_mmu_check_access_rights(utc, 274 TEE_MEMORY_ACCESS_READ, 275 (uaddr_t) object_id, 276 object_id_len); 277 if (res != TEE_SUCCESS) 278 goto err; 279 280 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 281 object_id_len, flags, false, fops, &po); 282 if (res != TEE_SUCCESS) 283 goto err; 284 285 o = tee_obj_alloc(); 286 if (o == NULL) { 287 tee_pobj_release(po); 288 res = TEE_ERROR_OUT_OF_MEMORY; 289 goto err; 290 } 291 292 o->info.handleFlags = 293 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 294 o->flags = flags; 295 o->pobj = po; 296 tee_obj_add(utc, o); 297 298 res = tee_svc_storage_read_head(o); 299 if (res != TEE_SUCCESS) { 300 if (res == TEE_ERROR_CORRUPT_OBJECT) { 301 EMSG("Object corrupt"); 302 goto err; 303 } 304 goto oclose; 305 } 306 307 res = tee_svc_copy_kaddr_to_uref(obj, o); 308 if (res != TEE_SUCCESS) 309 goto oclose; 310 311 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 312 if (res != TEE_SUCCESS) 313 goto oclose; 314 315 goto exit; 316 317 oclose: 318 tee_obj_close(utc, o); 319 o = NULL; 320 321 err: 322 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 323 res = TEE_ERROR_CORRUPT_OBJECT; 324 if (res == TEE_ERROR_CORRUPT_OBJECT && o) 325 tee_svc_storage_remove_corrupt_obj(sess, o); 326 327 exit: 328 free(file); 329 file = NULL; 330 return res; 331 } 332 333 static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, 334 struct tee_obj *attr_o, void *data, 335 uint32_t len) 336 { 337 TEE_Result res = TEE_SUCCESS; 338 struct tee_svc_storage_head head; 339 const struct tee_file_operations *fops = o->pobj->fops; 340 void *attr = NULL; 341 size_t attr_size = 0; 342 343 if (attr_o) { 344 res = tee_obj_set_type(o, attr_o->info.objectType, 345 attr_o->info.maxKeySize); 346 if (res) 347 return res; 348 res = tee_obj_attr_copy_from(o, attr_o); 349 if (res) 350 return res; 351 o->have_attrs = attr_o->have_attrs; 352 o->info.objectUsage = attr_o->info.objectUsage; 353 o->info.keySize = attr_o->info.keySize; 354 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 355 if (res) 356 return res; 357 if (attr_size) { 358 attr = malloc(attr_size); 359 if (!attr) 360 return TEE_ERROR_OUT_OF_MEMORY; 361 res = tee_obj_attr_to_binary(o, attr, &attr_size); 362 if (res != TEE_SUCCESS) 363 goto exit; 364 } 365 } else { 366 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 367 if (res != TEE_SUCCESS) 368 goto exit; 369 } 370 371 o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; 372 373 /* write head */ 374 head.attr_size = attr_size; 375 head.keySize = o->info.keySize; 376 head.maxKeySize = o->info.maxKeySize; 377 head.objectUsage = o->info.objectUsage; 378 head.objectType = o->info.objectType; 379 head.have_attrs = o->have_attrs; 380 381 res = fops->create(o->pobj, !!(o->flags & TEE_DATA_FLAG_OVERWRITE), 382 &head, sizeof(head), attr, attr_size, data, len, 383 &o->fh); 384 385 if (!res) 386 o->info.dataSize = len; 387 exit: 388 free(attr); 389 return res; 390 } 391 392 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 393 size_t object_id_len, unsigned long flags, 394 unsigned long attr, void *data, size_t len, 395 uint32_t *obj) 396 { 397 TEE_Result res; 398 struct tee_ta_session *sess; 399 struct tee_obj *o = NULL; 400 struct tee_obj *attr_o = NULL; 401 struct tee_pobj *po = NULL; 402 struct user_ta_ctx *utc; 403 const struct tee_file_operations *fops = 404 tee_svc_storage_file_ops(storage_id); 405 406 if (!fops) 407 return TEE_ERROR_ITEM_NOT_FOUND; 408 409 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 410 return TEE_ERROR_BAD_PARAMETERS; 411 412 res = tee_ta_get_current_session(&sess); 413 if (res != TEE_SUCCESS) 414 return res; 415 utc = to_user_ta_ctx(sess->ctx); 416 417 res = tee_mmu_check_access_rights(utc, 418 TEE_MEMORY_ACCESS_READ, 419 (uaddr_t) object_id, 420 object_id_len); 421 if (res != TEE_SUCCESS) 422 goto err; 423 424 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 425 object_id_len, flags, true, fops, &po); 426 if (res != TEE_SUCCESS) 427 goto err; 428 429 /* check rights of the provided buffer */ 430 if (data && len) { 431 res = tee_mmu_check_access_rights(utc, 432 TEE_MEMORY_ACCESS_READ | 433 TEE_MEMORY_ACCESS_ANY_OWNER, 434 (uaddr_t) data, len); 435 436 if (res != TEE_SUCCESS) 437 goto err; 438 } 439 440 o = tee_obj_alloc(); 441 if (o == NULL) { 442 res = TEE_ERROR_OUT_OF_MEMORY; 443 goto err; 444 } 445 446 o->info.handleFlags = 447 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 448 o->flags = flags; 449 o->pobj = po; 450 451 if (attr != TEE_HANDLE_NULL) { 452 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 453 &attr_o); 454 if (res != TEE_SUCCESS) 455 goto err; 456 } 457 458 res = tee_svc_storage_init_file(o, attr_o, data, len); 459 if (res != TEE_SUCCESS) 460 goto err; 461 462 po = NULL; /* o owns it from now on */ 463 tee_obj_add(utc, o); 464 465 res = tee_svc_copy_kaddr_to_uref(obj, o); 466 if (res != TEE_SUCCESS) 467 goto oclose; 468 469 return TEE_SUCCESS; 470 471 oclose: 472 tee_obj_close(utc, o); 473 return res; 474 475 err: 476 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 477 res = TEE_ERROR_CORRUPT_OBJECT; 478 if (res == TEE_ERROR_CORRUPT_OBJECT && po) 479 fops->remove(po); 480 if (o) 481 fops->close(&o->fh); 482 if (po) 483 tee_pobj_release(po); 484 free(o); 485 486 return res; 487 } 488 489 TEE_Result syscall_storage_obj_del(unsigned long obj) 490 { 491 TEE_Result res; 492 struct tee_ta_session *sess; 493 struct tee_obj *o; 494 struct user_ta_ctx *utc; 495 496 res = tee_ta_get_current_session(&sess); 497 if (res != TEE_SUCCESS) 498 return res; 499 utc = to_user_ta_ctx(sess->ctx); 500 501 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 502 if (res != TEE_SUCCESS) 503 return res; 504 505 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 506 return TEE_ERROR_ACCESS_CONFLICT; 507 508 if (o->pobj == NULL || o->pobj->obj_id == NULL) 509 return TEE_ERROR_BAD_STATE; 510 511 res = o->pobj->fops->remove(o->pobj); 512 tee_obj_close(utc, o); 513 514 return res; 515 } 516 517 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 518 size_t object_id_len) 519 { 520 TEE_Result res; 521 struct tee_ta_session *sess; 522 struct tee_obj *o; 523 struct tee_pobj *po = NULL; 524 char *new_file = NULL; 525 char *old_file = NULL; 526 struct user_ta_ctx *utc; 527 const struct tee_file_operations *fops; 528 529 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 530 return TEE_ERROR_BAD_PARAMETERS; 531 532 res = tee_ta_get_current_session(&sess); 533 if (res != TEE_SUCCESS) 534 return res; 535 utc = to_user_ta_ctx(sess->ctx); 536 537 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 538 if (res != TEE_SUCCESS) 539 return res; 540 541 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 542 res = TEE_ERROR_BAD_STATE; 543 goto exit; 544 } 545 546 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 547 res = TEE_ERROR_BAD_STATE; 548 goto exit; 549 } 550 551 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 552 res = TEE_ERROR_BAD_STATE; 553 goto exit; 554 } 555 556 res = tee_mmu_check_access_rights(utc, 557 TEE_MEMORY_ACCESS_READ, 558 (uaddr_t) object_id, object_id_len); 559 if (res != TEE_SUCCESS) 560 goto exit; 561 562 /* reserve dest name */ 563 fops = o->pobj->fops; 564 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 565 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 566 false, fops, &po); 567 if (res != TEE_SUCCESS) 568 goto exit; 569 570 /* move */ 571 res = fops->rename(o->pobj, po, false /* no overwrite */); 572 if (res == TEE_ERROR_GENERIC) 573 goto exit; 574 575 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 576 577 exit: 578 tee_pobj_release(po); 579 580 free(new_file); 581 free(old_file); 582 583 return res; 584 } 585 586 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 587 { 588 struct tee_storage_enum *e; 589 struct tee_ta_session *sess; 590 TEE_Result res; 591 struct user_ta_ctx *utc; 592 593 if (obj_enum == NULL) 594 return TEE_ERROR_BAD_PARAMETERS; 595 596 res = tee_ta_get_current_session(&sess); 597 if (res != TEE_SUCCESS) 598 return res; 599 utc = to_user_ta_ctx(sess->ctx); 600 601 e = malloc(sizeof(struct tee_storage_enum)); 602 if (e == NULL) 603 return TEE_ERROR_OUT_OF_MEMORY; 604 605 e->dir = NULL; 606 e->fops = NULL; 607 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 608 609 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 610 } 611 612 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 613 { 614 struct tee_storage_enum *e; 615 TEE_Result res; 616 struct tee_ta_session *sess; 617 struct user_ta_ctx *utc; 618 619 res = tee_ta_get_current_session(&sess); 620 if (res != TEE_SUCCESS) 621 return res; 622 utc = to_user_ta_ctx(sess->ctx); 623 624 res = tee_svc_storage_get_enum(utc, 625 tee_svc_uref_to_vaddr(obj_enum), &e); 626 if (res != TEE_SUCCESS) 627 return res; 628 629 return tee_svc_close_enum(utc, e); 630 } 631 632 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 633 { 634 struct tee_storage_enum *e; 635 TEE_Result res; 636 struct tee_ta_session *sess; 637 638 res = tee_ta_get_current_session(&sess); 639 if (res != TEE_SUCCESS) 640 return res; 641 642 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 643 tee_svc_uref_to_vaddr(obj_enum), &e); 644 if (res != TEE_SUCCESS) 645 return res; 646 647 if (e->fops) { 648 e->fops->closedir(e->dir); 649 e->fops = NULL; 650 e->dir = NULL; 651 } 652 assert(!e->dir); 653 654 return TEE_SUCCESS; 655 } 656 657 static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d, 658 const struct tee_file_operations *fops, 659 struct tee_obj *o) 660 { 661 o->info.handleFlags = 662 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 663 o->info.objectUsage = TEE_USAGE_DEFAULT; 664 665 o->pobj->obj_id = malloc(d->oidlen); 666 if (!o->pobj->obj_id) 667 return TEE_ERROR_OUT_OF_MEMORY; 668 669 memcpy(o->pobj->obj_id, d->oid, d->oidlen); 670 o->pobj->obj_id_len = d->oidlen; 671 o->pobj->fops = fops; 672 673 return TEE_SUCCESS; 674 } 675 676 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 677 unsigned long storage_id) 678 { 679 struct tee_storage_enum *e; 680 TEE_Result res; 681 struct tee_ta_session *sess; 682 const struct tee_file_operations *fops = 683 tee_svc_storage_file_ops(storage_id); 684 685 res = tee_ta_get_current_session(&sess); 686 if (res != TEE_SUCCESS) 687 return res; 688 689 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 690 tee_svc_uref_to_vaddr(obj_enum), &e); 691 if (res != TEE_SUCCESS) 692 return res; 693 694 if (!fops) 695 return TEE_ERROR_ITEM_NOT_FOUND; 696 697 e->fops = fops; 698 assert(!e->dir); 699 return fops->opendir(&sess->ctx->uuid, &e->dir); 700 } 701 702 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 703 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 704 { 705 struct tee_storage_enum *e; 706 struct tee_fs_dirent *d; 707 TEE_Result res = TEE_SUCCESS; 708 struct tee_ta_session *sess; 709 struct tee_obj *o = NULL; 710 uint64_t l; 711 struct user_ta_ctx *utc; 712 713 res = tee_ta_get_current_session(&sess); 714 if (res != TEE_SUCCESS) 715 goto exit; 716 utc = to_user_ta_ctx(sess->ctx); 717 718 res = tee_svc_storage_get_enum(utc, 719 tee_svc_uref_to_vaddr(obj_enum), &e); 720 if (res != TEE_SUCCESS) 721 goto exit; 722 723 /* check rights of the provided buffers */ 724 res = tee_mmu_check_access_rights(utc, 725 TEE_MEMORY_ACCESS_WRITE | 726 TEE_MEMORY_ACCESS_ANY_OWNER, 727 (uaddr_t) info, 728 sizeof(TEE_ObjectInfo)); 729 if (res != TEE_SUCCESS) 730 goto exit; 731 732 res = tee_mmu_check_access_rights(utc, 733 TEE_MEMORY_ACCESS_WRITE | 734 TEE_MEMORY_ACCESS_ANY_OWNER, 735 (uaddr_t) obj_id, 736 TEE_OBJECT_ID_MAX_LEN); 737 if (res != TEE_SUCCESS) 738 goto exit; 739 740 if (!e->fops) { 741 res = TEE_ERROR_ITEM_NOT_FOUND; 742 goto exit; 743 } 744 745 res = e->fops->readdir(e->dir, &d); 746 if (res != TEE_SUCCESS) 747 goto exit; 748 749 o = tee_obj_alloc(); 750 if (o == NULL) { 751 res = TEE_ERROR_OUT_OF_MEMORY; 752 goto exit; 753 } 754 o->flags = TEE_DATA_FLAG_SHARE_READ; 755 756 o->pobj = calloc(1, sizeof(struct tee_pobj)); 757 if (!o->pobj) { 758 res = TEE_ERROR_OUT_OF_MEMORY; 759 goto exit; 760 } 761 762 o->pobj->uuid = sess->ctx->uuid; 763 res = tee_svc_storage_set_enum(d, e->fops, o); 764 if (res != TEE_SUCCESS) 765 goto exit; 766 767 res = tee_svc_storage_read_head(o); 768 if (res != TEE_SUCCESS) 769 goto exit; 770 771 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 772 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 773 774 l = o->pobj->obj_id_len; 775 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 776 777 exit: 778 if (o) { 779 if (o->pobj) { 780 o->pobj->fops->close(&o->fh); 781 free(o->pobj->obj_id); 782 } 783 free(o->pobj); 784 tee_obj_free(o); 785 } 786 787 return res; 788 } 789 790 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 791 uint64_t *count) 792 { 793 TEE_Result res; 794 struct tee_ta_session *sess; 795 struct tee_obj *o; 796 uint64_t u_count; 797 struct user_ta_ctx *utc; 798 size_t bytes; 799 800 res = tee_ta_get_current_session(&sess); 801 if (res != TEE_SUCCESS) 802 goto exit; 803 utc = to_user_ta_ctx(sess->ctx); 804 805 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 806 if (res != TEE_SUCCESS) 807 goto exit; 808 809 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 810 res = TEE_ERROR_BAD_STATE; 811 goto exit; 812 } 813 814 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 815 res = TEE_ERROR_ACCESS_CONFLICT; 816 goto exit; 817 } 818 819 /* check rights of the provided buffer */ 820 res = tee_mmu_check_access_rights(utc, 821 TEE_MEMORY_ACCESS_WRITE | 822 TEE_MEMORY_ACCESS_ANY_OWNER, 823 (uaddr_t) data, len); 824 if (res != TEE_SUCCESS) 825 goto exit; 826 827 bytes = len; 828 res = o->pobj->fops->read(o->fh, o->ds_pos + o->info.dataPosition, 829 data, &bytes); 830 if (res != TEE_SUCCESS) { 831 EMSG("Error code=%x\n", (uint32_t)res); 832 if (res == TEE_ERROR_CORRUPT_OBJECT) { 833 EMSG("Object corrupt\n"); 834 tee_svc_storage_remove_corrupt_obj(sess, o); 835 } 836 goto exit; 837 } 838 839 o->info.dataPosition += bytes; 840 841 u_count = bytes; 842 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 843 exit: 844 return res; 845 } 846 847 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 848 { 849 TEE_Result res; 850 struct tee_ta_session *sess; 851 struct tee_obj *o; 852 struct user_ta_ctx *utc; 853 854 res = tee_ta_get_current_session(&sess); 855 if (res != TEE_SUCCESS) 856 goto exit; 857 utc = to_user_ta_ctx(sess->ctx); 858 859 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 860 if (res != TEE_SUCCESS) 861 goto exit; 862 863 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 864 res = TEE_ERROR_BAD_STATE; 865 goto exit; 866 } 867 868 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 869 res = TEE_ERROR_ACCESS_CONFLICT; 870 goto exit; 871 } 872 873 /* check rights of the provided buffer */ 874 res = tee_mmu_check_access_rights(utc, 875 TEE_MEMORY_ACCESS_READ | 876 TEE_MEMORY_ACCESS_ANY_OWNER, 877 (uaddr_t) data, len); 878 if (res != TEE_SUCCESS) 879 goto exit; 880 881 res = o->pobj->fops->write(o->fh, o->ds_pos + o->info.dataPosition, 882 data, len); 883 if (res != TEE_SUCCESS) 884 goto exit; 885 886 o->info.dataPosition += len; 887 if (o->info.dataPosition > o->info.dataSize) 888 o->info.dataSize = o->info.dataPosition; 889 890 exit: 891 return res; 892 } 893 894 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 895 { 896 TEE_Result res; 897 struct tee_ta_session *sess; 898 struct tee_obj *o; 899 size_t off; 900 size_t attr_size; 901 902 res = tee_ta_get_current_session(&sess); 903 if (res != TEE_SUCCESS) 904 goto exit; 905 906 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 907 tee_svc_uref_to_vaddr(obj), &o); 908 if (res != TEE_SUCCESS) 909 goto exit; 910 911 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 912 res = TEE_ERROR_BAD_STATE; 913 goto exit; 914 } 915 916 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 917 res = TEE_ERROR_ACCESS_CONFLICT; 918 goto exit; 919 } 920 921 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 922 if (res != TEE_SUCCESS) 923 goto exit; 924 925 off = sizeof(struct tee_svc_storage_head) + attr_size; 926 res = o->pobj->fops->truncate(o->fh, len + off); 927 if (res != TEE_SUCCESS) { 928 if (res == TEE_ERROR_CORRUPT_OBJECT) { 929 EMSG("Object corrupt\n"); 930 res = tee_svc_storage_remove_corrupt_obj(sess, o); 931 if (res != TEE_SUCCESS) 932 goto exit; 933 res = TEE_ERROR_CORRUPT_OBJECT; 934 goto exit; 935 } else 936 res = TEE_ERROR_GENERIC; 937 } 938 939 exit: 940 return res; 941 } 942 943 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 944 unsigned long whence) 945 { 946 TEE_Result res; 947 struct tee_ta_session *sess; 948 struct tee_obj *o; 949 size_t attr_size; 950 tee_fs_off_t new_pos; 951 952 res = tee_ta_get_current_session(&sess); 953 if (res != TEE_SUCCESS) 954 return res; 955 956 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 957 tee_svc_uref_to_vaddr(obj), &o); 958 if (res != TEE_SUCCESS) 959 return res; 960 961 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) 962 return TEE_ERROR_BAD_STATE; 963 964 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 965 if (res != TEE_SUCCESS) 966 return res; 967 968 switch (whence) { 969 case TEE_DATA_SEEK_SET: 970 new_pos = offset; 971 break; 972 case TEE_DATA_SEEK_CUR: 973 new_pos = o->info.dataPosition + offset; 974 break; 975 case TEE_DATA_SEEK_END: 976 new_pos = o->info.dataSize + offset; 977 break; 978 default: 979 return TEE_ERROR_BAD_PARAMETERS; 980 } 981 982 if (new_pos < 0) 983 new_pos = 0; 984 985 if (new_pos > TEE_DATA_MAX_POSITION) { 986 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 987 return TEE_ERROR_BAD_PARAMETERS; 988 } 989 990 o->info.dataPosition = new_pos; 991 992 return TEE_SUCCESS; 993 } 994 995 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 996 { 997 struct tee_storage_enum_head *eh = &utc->storage_enums; 998 999 /* disregard return value */ 1000 while (!TAILQ_EMPTY(eh)) 1001 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1002 } 1003