1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <kernel/mutex.h> 29 #include <kernel/tee_misc.h> 30 #include <kernel/tee_ta_manager.h> 31 #include <mm/tee_mmu.h> 32 #include <string.h> 33 #include <tee_api_defines_extensions.h> 34 #include <tee_api_defines.h> 35 #include <tee/tee_fs_defs.h> 36 #include <tee/tee_fs.h> 37 #include <tee/tee_obj.h> 38 #include <tee/tee_pobj.h> 39 #include <tee/tee_svc_cryp.h> 40 #include <tee/tee_svc.h> 41 #include <tee/tee_svc_storage.h> 42 #include <trace.h> 43 44 /* 45 * Returns the appropriate tee_file_operations for the specified storage ID. 46 * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise 47 * RPMB. 48 */ 49 static const struct tee_file_operations *file_ops(uint32_t storage_id) 50 { 51 52 switch (storage_id) { 53 case TEE_STORAGE_PRIVATE: 54 #if defined(CFG_REE_FS) 55 return &ree_fs_ops; 56 #elif defined(CFG_RPMB_FS) 57 return &rpmb_fs_ops; 58 #elif defined(CFG_SQL_FS) 59 return &sql_fs_ops; 60 #else 61 #error At least one filesystem must be enabled. 62 #endif 63 #ifdef CFG_REE_FS 64 case TEE_STORAGE_PRIVATE_REE: 65 return &ree_fs_ops; 66 #endif 67 #ifdef CFG_RPMB_FS 68 case TEE_STORAGE_PRIVATE_RPMB: 69 return &rpmb_fs_ops; 70 #endif 71 #ifdef CFG_SQL_FS 72 case TEE_STORAGE_PRIVATE_SQL: 73 return &sql_fs_ops; 74 #endif 75 default: 76 return NULL; 77 } 78 } 79 80 /* SSF (Secure Storage File version 00 */ 81 #define TEE_SVC_STORAGE_MAGIC 0x53534600; 82 83 /* Header of GP formated secure storage files */ 84 struct tee_svc_storage_head { 85 uint32_t magic; 86 uint32_t head_size; 87 uint32_t meta_size; 88 uint32_t ds_size; 89 uint32_t keySize; 90 uint32_t maxKeySize; 91 uint32_t objectUsage; 92 uint32_t objectType; 93 uint32_t have_attrs; 94 }; 95 96 struct tee_storage_enum { 97 TAILQ_ENTRY(tee_storage_enum) link; 98 struct tee_fs_dir *dir; 99 const struct tee_file_operations *fops; 100 }; 101 102 /* 103 * Protect TA storage directory: avoid race conditions between (create 104 * directory + create file) and (remove directory) 105 */ 106 static struct mutex ta_dir_mutex = MUTEX_INITIALIZER; 107 108 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, 109 uint32_t enum_id, 110 struct tee_storage_enum **e_out) 111 { 112 struct tee_storage_enum *e; 113 114 TAILQ_FOREACH(e, &utc->storage_enums, link) { 115 if (enum_id == (vaddr_t)e) { 116 *e_out = e; 117 return TEE_SUCCESS; 118 } 119 } 120 return TEE_ERROR_BAD_PARAMETERS; 121 } 122 123 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, 124 struct tee_storage_enum *e) 125 { 126 if (e == NULL || utc == NULL) 127 return TEE_ERROR_BAD_PARAMETERS; 128 129 TAILQ_REMOVE(&utc->storage_enums, e, link); 130 131 if (!e->fops) 132 return TEE_ERROR_ITEM_NOT_FOUND; 133 134 e->fops->closedir(e->dir); 135 e->dir = NULL; 136 e->fops = NULL; 137 138 free(e); 139 140 return TEE_SUCCESS; 141 } 142 143 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ 144 char *tee_svc_storage_create_filename(struct tee_ta_session *sess, 145 void *object_id, 146 uint32_t object_id_len, 147 bool transient) 148 { 149 uint8_t *file; 150 uint32_t pos = 0; 151 uint32_t hslen = 1 /* Leading slash */ 152 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) 153 + 1; /* Intermediate slash */ 154 155 /* +1 for the '.' (temporary persistent object) */ 156 if (transient) 157 hslen++; 158 159 file = malloc(hslen); 160 if (!file) 161 return NULL; 162 163 file[pos++] = '/'; 164 pos += tee_b2hs((uint8_t *)&sess->ctx->uuid, &file[pos], 165 sizeof(TEE_UUID), hslen); 166 file[pos++] = '/'; 167 168 if (transient) 169 file[pos++] = '.'; 170 171 tee_b2hs(object_id, file + pos, object_id_len, hslen - pos); 172 173 return (char *)file; 174 } 175 176 /* "/TA_uuid" */ 177 char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) 178 { 179 uint8_t *dir; 180 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; 181 182 dir = malloc(hslen); 183 if (!dir) 184 return NULL; 185 186 dir[0] = '/'; 187 tee_b2hs((uint8_t *)&sess->ctx->uuid, dir + 1, sizeof(TEE_UUID), 188 hslen); 189 190 return (char *)dir; 191 } 192 193 static TEE_Result tee_svc_storage_remove_corrupt_obj( 194 struct tee_ta_session *sess, 195 struct tee_obj *o) 196 { 197 TEE_Result res; 198 char *file = NULL; 199 const struct tee_file_operations *fops = o->pobj->fops; 200 201 file = tee_svc_storage_create_filename(sess, 202 o->pobj->obj_id, 203 o->pobj->obj_id_len, 204 false); 205 if (file == NULL) { 206 res = TEE_ERROR_OUT_OF_MEMORY; 207 goto exit; 208 } 209 210 tee_obj_close(to_user_ta_ctx(sess->ctx), o); 211 fops->remove(file); 212 free(file); 213 214 res = TEE_SUCCESS; 215 216 exit: 217 return res; 218 } 219 220 static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, 221 struct tee_obj *o) 222 { 223 TEE_Result res = TEE_SUCCESS; 224 size_t bytes; 225 struct tee_svc_storage_head head; 226 char *file = NULL; 227 const struct tee_file_operations *fops; 228 void *attr = NULL; 229 230 if (o == NULL || o->pobj == NULL) 231 return TEE_ERROR_BAD_PARAMETERS; 232 233 fops = o->pobj->fops; 234 235 file = tee_svc_storage_create_filename(sess, 236 o->pobj->obj_id, 237 o->pobj->obj_id_len, 238 false); 239 if (file == NULL) { 240 res = TEE_ERROR_OUT_OF_MEMORY; 241 goto exit; 242 } 243 244 assert(!o->fh); 245 res = fops->open(file, &o->fh); 246 if (res != TEE_SUCCESS) 247 goto exit; 248 249 /* read head */ 250 bytes = sizeof(struct tee_svc_storage_head); 251 res = fops->read(o->fh, &head, &bytes); 252 if (res != TEE_SUCCESS) { 253 if (res == TEE_ERROR_CORRUPT_OBJECT) 254 EMSG("Head corrupt\n"); 255 goto exit; 256 } 257 258 if (bytes != sizeof(struct tee_svc_storage_head)) { 259 res = TEE_ERROR_BAD_FORMAT; 260 goto exit; 261 } 262 263 res = tee_obj_set_type(o, head.objectType, head.maxKeySize); 264 if (res != TEE_SUCCESS) 265 goto exit; 266 267 if (head.meta_size) { 268 attr = malloc(head.meta_size); 269 if (!attr) { 270 res = TEE_ERROR_OUT_OF_MEMORY; 271 goto exit; 272 } 273 274 /* read meta */ 275 bytes = head.meta_size; 276 res = fops->read(o->fh, attr, &bytes); 277 if (res != TEE_SUCCESS || bytes != head.meta_size) { 278 res = TEE_ERROR_CORRUPT_OBJECT; 279 goto exit; 280 } 281 } 282 283 res = tee_obj_attr_from_binary(o, attr, head.meta_size); 284 if (res != TEE_SUCCESS) 285 goto exit; 286 287 o->info.dataSize = head.ds_size; 288 o->info.keySize = head.keySize; 289 o->info.objectUsage = head.objectUsage; 290 o->info.objectType = head.objectType; 291 o->have_attrs = head.have_attrs; 292 293 exit: 294 free(attr); 295 free(file); 296 297 return res; 298 } 299 300 301 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, 302 struct tee_obj *o, 303 struct tee_obj *attr_o, void *data, 304 uint32_t len) 305 { 306 TEE_Result res = TEE_SUCCESS; 307 struct tee_svc_storage_head head; 308 char *tmpfile = NULL; 309 const struct tee_file_operations *fops; 310 void *attr = NULL; 311 size_t attr_size = 0; 312 313 if (o == NULL || o->pobj == NULL) 314 return TEE_ERROR_BAD_PARAMETERS; 315 316 fops = o->pobj->fops; 317 318 /* create temporary persistent object filename */ 319 tmpfile = tee_svc_storage_create_filename(sess, 320 o->pobj->obj_id, 321 o->pobj->obj_id_len, 322 true); 323 324 if (tmpfile == NULL) { 325 res = TEE_ERROR_OUT_OF_MEMORY; 326 goto exit; 327 } 328 329 mutex_lock(&ta_dir_mutex); 330 res = fops->create(tmpfile, &o->fh); 331 mutex_unlock(&ta_dir_mutex); 332 if (res != TEE_SUCCESS) 333 goto exit; 334 335 if (attr_o) { 336 res = tee_obj_set_type(o, attr_o->info.objectType, 337 attr_o->info.maxKeySize); 338 if (res != TEE_SUCCESS) 339 goto exit; 340 res = tee_obj_attr_copy_from(o, attr_o); 341 if (res != TEE_SUCCESS) 342 goto exit; 343 o->have_attrs = attr_o->have_attrs; 344 o->info.objectUsage = attr_o->info.objectUsage; 345 o->info.keySize = attr_o->info.keySize; 346 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 347 if (res != TEE_SUCCESS) 348 goto exit; 349 if (attr_size) { 350 attr = malloc(attr_size); 351 if (!attr) { 352 res = TEE_ERROR_OUT_OF_MEMORY; 353 goto exit; 354 } 355 res = tee_obj_attr_to_binary(o, attr, &attr_size); 356 if (res != TEE_SUCCESS) 357 goto exit; 358 } 359 } else { 360 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 361 if (res != TEE_SUCCESS) 362 goto exit; 363 } 364 365 /* write head */ 366 head.magic = TEE_SVC_STORAGE_MAGIC; 367 head.head_size = sizeof(struct tee_svc_storage_head); 368 head.meta_size = attr_size; 369 head.ds_size = len; 370 head.keySize = o->info.keySize; 371 head.maxKeySize = o->info.maxKeySize; 372 head.objectUsage = o->info.objectUsage; 373 head.objectType = o->info.objectType; 374 head.have_attrs = o->have_attrs; 375 376 /* write head */ 377 res = fops->write(o->fh, &head, sizeof(struct tee_svc_storage_head)); 378 if (res != TEE_SUCCESS) 379 goto exit; 380 381 /* write meta */ 382 res = fops->write(o->fh, attr, attr_size); 383 if (res != TEE_SUCCESS) 384 goto exit; 385 386 /* write init data */ 387 o->info.dataSize = len; 388 389 /* write data to fs if needed */ 390 if (data && len) 391 res = fops->write(o->fh, data, len); 392 393 exit: 394 free(attr); 395 free(tmpfile); 396 fops->close(&o->fh); 397 398 return res; 399 } 400 401 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 402 size_t object_id_len, unsigned long flags, 403 uint32_t *obj) 404 { 405 TEE_Result res; 406 struct tee_ta_session *sess; 407 struct tee_obj *o = NULL; 408 char *file = NULL; 409 struct tee_pobj *po = NULL; 410 struct user_ta_ctx *utc; 411 const struct tee_file_operations *fops = file_ops(storage_id); 412 size_t attr_size; 413 414 if (!fops) { 415 res = TEE_ERROR_ITEM_NOT_FOUND; 416 goto exit; 417 } 418 419 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 420 res = TEE_ERROR_BAD_PARAMETERS; 421 goto exit; 422 } 423 424 res = tee_ta_get_current_session(&sess); 425 if (res != TEE_SUCCESS) 426 goto err; 427 utc = to_user_ta_ctx(sess->ctx); 428 429 res = tee_mmu_check_access_rights(utc, 430 TEE_MEMORY_ACCESS_READ | 431 TEE_MEMORY_ACCESS_ANY_OWNER, 432 (uaddr_t) object_id, 433 object_id_len); 434 if (res != TEE_SUCCESS) 435 goto err; 436 437 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 438 object_id_len, flags, fops, &po); 439 if (res != TEE_SUCCESS) 440 goto err; 441 442 o = tee_obj_alloc(); 443 if (o == NULL) { 444 tee_pobj_release(po); 445 res = TEE_ERROR_OUT_OF_MEMORY; 446 goto err; 447 } 448 449 o->info.handleFlags = 450 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 451 o->flags = flags; 452 o->pobj = po; 453 tee_obj_add(utc, o); 454 455 res = tee_svc_storage_read_head(sess, o); 456 if (res != TEE_SUCCESS) { 457 if (res == TEE_ERROR_CORRUPT_OBJECT) { 458 EMSG("Object corrupt"); 459 goto err; 460 } 461 goto oclose; 462 } 463 464 res = tee_svc_copy_kaddr_to_uref(obj, o); 465 if (res != TEE_SUCCESS) 466 goto oclose; 467 468 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 469 if (res != TEE_SUCCESS) 470 goto oclose; 471 472 res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, 473 TEE_DATA_SEEK_SET, NULL); 474 if (res != TEE_SUCCESS) 475 goto err; 476 477 goto exit; 478 479 oclose: 480 tee_obj_close(utc, o); 481 o = NULL; 482 483 err: 484 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 485 res = TEE_ERROR_CORRUPT_OBJECT; 486 if (res == TEE_ERROR_CORRUPT_OBJECT && o) 487 tee_svc_storage_remove_corrupt_obj(sess, o); 488 489 exit: 490 free(file); 491 file = NULL; 492 return res; 493 } 494 495 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 496 size_t object_id_len, unsigned long flags, 497 unsigned long attr, void *data, size_t len, 498 uint32_t *obj) 499 { 500 TEE_Result res; 501 struct tee_ta_session *sess; 502 struct tee_obj *o = NULL; 503 struct tee_obj *attr_o = NULL; 504 char *file = NULL; 505 struct tee_pobj *po = NULL; 506 char *tmpfile = NULL; 507 struct user_ta_ctx *utc; 508 const struct tee_file_operations *fops = file_ops(storage_id); 509 size_t attr_size; 510 511 if (!fops) 512 return TEE_ERROR_ITEM_NOT_FOUND; 513 514 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 515 return TEE_ERROR_BAD_PARAMETERS; 516 517 res = tee_ta_get_current_session(&sess); 518 if (res != TEE_SUCCESS) 519 return res; 520 utc = to_user_ta_ctx(sess->ctx); 521 522 res = tee_mmu_check_access_rights(utc, 523 TEE_MEMORY_ACCESS_READ | 524 TEE_MEMORY_ACCESS_ANY_OWNER, 525 (uaddr_t) object_id, 526 object_id_len); 527 if (res != TEE_SUCCESS) 528 goto err; 529 530 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 531 object_id_len, flags, fops, &po); 532 if (res != TEE_SUCCESS) 533 goto err; 534 535 /* check rights of the provided buffer */ 536 if (data && len) { 537 res = tee_mmu_check_access_rights(utc, 538 TEE_MEMORY_ACCESS_READ | 539 TEE_MEMORY_ACCESS_ANY_OWNER, 540 (uaddr_t) data, len); 541 542 if (res != TEE_SUCCESS) 543 goto err; 544 } 545 546 o = tee_obj_alloc(); 547 if (o == NULL) { 548 res = TEE_ERROR_OUT_OF_MEMORY; 549 goto err; 550 } 551 552 o->info.handleFlags = 553 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 554 o->flags = flags; 555 o->pobj = po; 556 557 if (attr != TEE_HANDLE_NULL) { 558 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 559 &attr_o); 560 if (res != TEE_SUCCESS) 561 goto err; 562 } 563 564 res = tee_svc_storage_init_file(sess, o, attr_o, data, len); 565 if (res != TEE_SUCCESS) 566 goto err; 567 568 /* create persistent object filename */ 569 file = tee_svc_storage_create_filename(sess, object_id, 570 object_id_len, false); 571 if (file == NULL) { 572 res = TEE_ERROR_OUT_OF_MEMORY; 573 goto err; 574 } 575 576 /* create temporary persistent object filename */ 577 tmpfile = tee_svc_storage_create_filename(sess, object_id, 578 object_id_len, 579 true); 580 if (tmpfile == NULL) { 581 res = TEE_ERROR_OUT_OF_MEMORY; 582 goto err; 583 } 584 585 /* rename temporary persistent object filename */ 586 res = fops->rename(tmpfile, file, !!(flags & TEE_DATA_FLAG_OVERWRITE)); 587 if (res != TEE_SUCCESS) 588 goto rmfile; 589 590 res = fops->open(file, &o->fh); 591 if (res != TEE_SUCCESS) 592 goto err; 593 594 tee_obj_add(utc, o); 595 596 res = tee_svc_copy_kaddr_to_uref(obj, o); 597 if (res != TEE_SUCCESS) 598 goto oclose; 599 600 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 601 if (res != TEE_SUCCESS) 602 goto oclose; 603 604 res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, 605 TEE_DATA_SEEK_SET, NULL); 606 if (res != TEE_SUCCESS) 607 goto oclose; 608 609 goto exit; 610 611 oclose: 612 tee_obj_close(utc, o); 613 goto exit; 614 615 rmfile: 616 fops->remove(tmpfile); 617 618 err: 619 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 620 res = TEE_ERROR_CORRUPT_OBJECT; 621 if (res == TEE_ERROR_CORRUPT_OBJECT && file) 622 fops->remove(file); 623 if (o) 624 fops->close(&o->fh); 625 if (po) 626 tee_pobj_release(po); 627 free(o); 628 629 exit: 630 free(file); 631 free(tmpfile); 632 633 return res; 634 } 635 636 TEE_Result syscall_storage_obj_del(unsigned long obj) 637 { 638 TEE_Result res; 639 struct tee_ta_session *sess; 640 struct tee_obj *o; 641 char *file; 642 struct user_ta_ctx *utc; 643 const struct tee_file_operations *fops; 644 645 res = tee_ta_get_current_session(&sess); 646 if (res != TEE_SUCCESS) 647 return res; 648 utc = to_user_ta_ctx(sess->ctx); 649 650 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 651 if (res != TEE_SUCCESS) 652 return res; 653 654 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 655 return TEE_ERROR_ACCESS_CONFLICT; 656 657 if (o->pobj == NULL || o->pobj->obj_id == NULL) 658 return TEE_ERROR_BAD_STATE; 659 660 file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 661 o->pobj->obj_id_len, false); 662 if (file == NULL) 663 return TEE_ERROR_OUT_OF_MEMORY; 664 665 fops = o->pobj->fops; 666 tee_obj_close(utc, o); 667 668 res = fops->remove(file); 669 free(file); 670 return res; 671 } 672 673 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 674 size_t object_id_len) 675 { 676 TEE_Result res; 677 struct tee_ta_session *sess; 678 struct tee_obj *o; 679 struct tee_pobj *po = NULL; 680 char *new_file = NULL; 681 char *old_file = NULL; 682 struct user_ta_ctx *utc; 683 const struct tee_file_operations *fops; 684 685 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 686 return TEE_ERROR_BAD_PARAMETERS; 687 688 res = tee_ta_get_current_session(&sess); 689 if (res != TEE_SUCCESS) 690 return res; 691 utc = to_user_ta_ctx(sess->ctx); 692 693 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 694 if (res != TEE_SUCCESS) 695 return res; 696 697 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 698 res = TEE_ERROR_BAD_STATE; 699 goto exit; 700 } 701 702 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 703 res = TEE_ERROR_BAD_STATE; 704 goto exit; 705 } 706 707 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 708 res = TEE_ERROR_BAD_STATE; 709 goto exit; 710 } 711 712 res = tee_mmu_check_access_rights(utc, 713 TEE_MEMORY_ACCESS_READ | 714 TEE_MEMORY_ACCESS_ANY_OWNER, 715 (uaddr_t) object_id, object_id_len); 716 if (res != TEE_SUCCESS) 717 goto exit; 718 719 /* get new ds name */ 720 new_file = tee_svc_storage_create_filename(sess, object_id, 721 object_id_len, false); 722 if (new_file == NULL) { 723 res = TEE_ERROR_OUT_OF_MEMORY; 724 goto exit; 725 } 726 727 old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 728 o->pobj->obj_id_len, false); 729 if (old_file == NULL) { 730 res = TEE_ERROR_OUT_OF_MEMORY; 731 goto exit; 732 } 733 734 /* reserve dest name */ 735 fops = o->pobj->fops; 736 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 737 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 738 fops, &po); 739 if (res != TEE_SUCCESS) 740 goto exit; 741 742 /* move */ 743 res = fops->rename(old_file, new_file, false /* no overwrite */); 744 if (res == TEE_ERROR_GENERIC) 745 goto exit; 746 747 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 748 749 exit: 750 tee_pobj_release(po); 751 752 free(new_file); 753 free(old_file); 754 755 return res; 756 } 757 758 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 759 { 760 struct tee_storage_enum *e; 761 struct tee_ta_session *sess; 762 TEE_Result res; 763 struct user_ta_ctx *utc; 764 765 if (obj_enum == NULL) 766 return TEE_ERROR_BAD_PARAMETERS; 767 768 res = tee_ta_get_current_session(&sess); 769 if (res != TEE_SUCCESS) 770 return res; 771 utc = to_user_ta_ctx(sess->ctx); 772 773 e = malloc(sizeof(struct tee_storage_enum)); 774 if (e == NULL) 775 return TEE_ERROR_OUT_OF_MEMORY; 776 777 e->dir = NULL; 778 e->fops = NULL; 779 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 780 781 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 782 } 783 784 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 785 { 786 struct tee_storage_enum *e; 787 TEE_Result res; 788 struct tee_ta_session *sess; 789 struct user_ta_ctx *utc; 790 791 res = tee_ta_get_current_session(&sess); 792 if (res != TEE_SUCCESS) 793 return res; 794 utc = to_user_ta_ctx(sess->ctx); 795 796 res = tee_svc_storage_get_enum(utc, 797 tee_svc_uref_to_vaddr(obj_enum), &e); 798 if (res != TEE_SUCCESS) 799 return res; 800 801 return tee_svc_close_enum(utc, e); 802 } 803 804 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 805 { 806 struct tee_storage_enum *e; 807 TEE_Result res; 808 struct tee_ta_session *sess; 809 810 res = tee_ta_get_current_session(&sess); 811 if (res != TEE_SUCCESS) 812 return res; 813 814 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 815 tee_svc_uref_to_vaddr(obj_enum), &e); 816 if (res != TEE_SUCCESS) 817 return res; 818 819 e->fops->closedir(e->dir); 820 e->dir = NULL; 821 822 return TEE_SUCCESS; 823 } 824 825 static TEE_Result tee_svc_storage_set_enum(char *d_name, 826 const struct tee_file_operations *fops, 827 struct tee_obj *o) 828 { 829 TEE_Result res; 830 uint32_t blen; 831 uint32_t hslen; 832 833 o->info.handleFlags = 834 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 835 o->info.objectUsage = TEE_USAGE_DEFAULT; 836 837 hslen = strlen(d_name); 838 blen = TEE_HS2B_BBUF_SIZE(hslen); 839 o->pobj->obj_id = malloc(blen); 840 if (!o->pobj->obj_id) { 841 res = TEE_ERROR_OUT_OF_MEMORY; 842 goto exit; 843 } 844 tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen); 845 o->pobj->obj_id_len = blen; 846 o->pobj->fops = fops; 847 848 res = TEE_SUCCESS; 849 850 exit: 851 return res; 852 853 } 854 855 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 856 unsigned long storage_id) 857 { 858 struct tee_storage_enum *e; 859 char *dir; 860 TEE_Result res; 861 struct tee_ta_session *sess; 862 const struct tee_file_operations *fops = file_ops(storage_id); 863 864 res = tee_ta_get_current_session(&sess); 865 if (res != TEE_SUCCESS) 866 return res; 867 868 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 869 tee_svc_uref_to_vaddr(obj_enum), &e); 870 if (res != TEE_SUCCESS) 871 return res; 872 873 if (!fops) 874 return TEE_ERROR_ITEM_NOT_FOUND; 875 876 e->fops = fops; 877 dir = tee_svc_storage_create_dirname(sess); 878 if (dir == NULL) { 879 res = TEE_ERROR_OUT_OF_MEMORY; 880 goto exit; 881 } 882 883 assert(!e->dir); 884 res = fops->opendir(dir, &e->dir); 885 free(dir); 886 exit: 887 return res; 888 } 889 890 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 891 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 892 { 893 struct tee_storage_enum *e; 894 struct tee_fs_dirent *d; 895 TEE_Result res = TEE_SUCCESS; 896 struct tee_ta_session *sess; 897 struct tee_obj *o = NULL; 898 uint64_t l; 899 struct user_ta_ctx *utc; 900 901 res = tee_ta_get_current_session(&sess); 902 if (res != TEE_SUCCESS) 903 goto exit; 904 utc = to_user_ta_ctx(sess->ctx); 905 906 res = tee_svc_storage_get_enum(utc, 907 tee_svc_uref_to_vaddr(obj_enum), &e); 908 if (res != TEE_SUCCESS) 909 goto exit; 910 911 /* check rights of the provided buffers */ 912 res = tee_mmu_check_access_rights(utc, 913 TEE_MEMORY_ACCESS_WRITE | 914 TEE_MEMORY_ACCESS_ANY_OWNER, 915 (uaddr_t) info, 916 sizeof(TEE_ObjectInfo)); 917 if (res != TEE_SUCCESS) 918 goto exit; 919 920 res = tee_mmu_check_access_rights(utc, 921 TEE_MEMORY_ACCESS_WRITE | 922 TEE_MEMORY_ACCESS_ANY_OWNER, 923 (uaddr_t) obj_id, 924 TEE_OBJECT_ID_MAX_LEN); 925 if (res != TEE_SUCCESS) 926 goto exit; 927 928 if (!e->fops) { 929 res = TEE_ERROR_ITEM_NOT_FOUND; 930 goto exit; 931 } 932 933 res = e->fops->readdir(e->dir, &d); 934 if (res != TEE_SUCCESS) 935 goto exit; 936 937 o = tee_obj_alloc(); 938 if (o == NULL) { 939 res = TEE_ERROR_OUT_OF_MEMORY; 940 goto exit; 941 } 942 o->flags = TEE_DATA_FLAG_SHARE_READ; 943 944 o->pobj = calloc(1, sizeof(struct tee_pobj)); 945 if (!o->pobj) { 946 res = TEE_ERROR_OUT_OF_MEMORY; 947 goto exit; 948 } 949 950 res = tee_svc_storage_set_enum(d->d_name, e->fops, o); 951 if (res != TEE_SUCCESS) 952 goto exit; 953 954 res = tee_svc_storage_read_head(sess, o); 955 if (res != TEE_SUCCESS) 956 goto exit; 957 958 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 959 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 960 961 l = o->pobj->obj_id_len; 962 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 963 964 exit: 965 if (o) { 966 if (o->pobj) { 967 o->pobj->fops->close(&o->fh); 968 free(o->pobj->obj_id); 969 } 970 free(o->pobj); 971 tee_obj_free(o); 972 } 973 974 return res; 975 } 976 977 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 978 uint64_t *count) 979 { 980 TEE_Result res; 981 struct tee_ta_session *sess; 982 struct tee_obj *o; 983 uint64_t u_count; 984 struct user_ta_ctx *utc; 985 size_t bytes; 986 987 res = tee_ta_get_current_session(&sess); 988 if (res != TEE_SUCCESS) 989 goto exit; 990 utc = to_user_ta_ctx(sess->ctx); 991 992 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 993 if (res != TEE_SUCCESS) 994 goto exit; 995 996 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 997 res = TEE_ERROR_BAD_STATE; 998 goto exit; 999 } 1000 1001 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 1002 res = TEE_ERROR_ACCESS_CONFLICT; 1003 goto exit; 1004 } 1005 1006 /* check rights of the provided buffer */ 1007 res = tee_mmu_check_access_rights(utc, 1008 TEE_MEMORY_ACCESS_WRITE | 1009 TEE_MEMORY_ACCESS_ANY_OWNER, 1010 (uaddr_t) data, len); 1011 if (res != TEE_SUCCESS) 1012 goto exit; 1013 1014 bytes = len; 1015 res = o->pobj->fops->read(o->fh, data, &bytes); 1016 if (res != TEE_SUCCESS) { 1017 EMSG("Error code=%x\n", (uint32_t)res); 1018 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1019 EMSG("Object corrupt\n"); 1020 tee_svc_storage_remove_corrupt_obj(sess, o); 1021 } 1022 goto exit; 1023 } 1024 1025 o->info.dataPosition += bytes; 1026 1027 u_count = bytes; 1028 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 1029 exit: 1030 return res; 1031 } 1032 1033 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 1034 { 1035 TEE_Result res; 1036 struct tee_ta_session *sess; 1037 struct tee_obj *o; 1038 struct user_ta_ctx *utc; 1039 1040 res = tee_ta_get_current_session(&sess); 1041 if (res != TEE_SUCCESS) 1042 goto exit; 1043 utc = to_user_ta_ctx(sess->ctx); 1044 1045 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1046 if (res != TEE_SUCCESS) 1047 goto exit; 1048 1049 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1050 res = TEE_ERROR_BAD_STATE; 1051 goto exit; 1052 } 1053 1054 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1055 res = TEE_ERROR_ACCESS_CONFLICT; 1056 goto exit; 1057 } 1058 1059 /* check rights of the provided buffer */ 1060 res = tee_mmu_check_access_rights(utc, 1061 TEE_MEMORY_ACCESS_READ | 1062 TEE_MEMORY_ACCESS_ANY_OWNER, 1063 (uaddr_t) data, len); 1064 if (res != TEE_SUCCESS) 1065 goto exit; 1066 1067 res = o->pobj->fops->write(o->fh, data, len); 1068 if (res != TEE_SUCCESS) 1069 goto exit; 1070 1071 o->info.dataPosition += len; 1072 if (o->info.dataPosition > o->info.dataSize) 1073 o->info.dataSize = o->info.dataPosition; 1074 1075 exit: 1076 return res; 1077 } 1078 1079 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 1080 { 1081 TEE_Result res; 1082 struct tee_ta_session *sess; 1083 struct tee_obj *o; 1084 size_t off; 1085 size_t attr_size; 1086 1087 res = tee_ta_get_current_session(&sess); 1088 if (res != TEE_SUCCESS) 1089 goto exit; 1090 1091 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1092 tee_svc_uref_to_vaddr(obj), &o); 1093 if (res != TEE_SUCCESS) 1094 goto exit; 1095 1096 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1097 res = TEE_ERROR_BAD_STATE; 1098 goto exit; 1099 } 1100 1101 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1102 res = TEE_ERROR_ACCESS_CONFLICT; 1103 goto exit; 1104 } 1105 1106 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1107 if (res != TEE_SUCCESS) 1108 goto exit; 1109 1110 off = sizeof(struct tee_svc_storage_head) + attr_size; 1111 res = o->pobj->fops->truncate(o->fh, len + off); 1112 if (res != TEE_SUCCESS) { 1113 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1114 EMSG("Object corrupt\n"); 1115 res = tee_svc_storage_remove_corrupt_obj(sess, o); 1116 if (res != TEE_SUCCESS) 1117 goto exit; 1118 res = TEE_ERROR_CORRUPT_OBJECT; 1119 goto exit; 1120 } else 1121 res = TEE_ERROR_GENERIC; 1122 } 1123 1124 exit: 1125 return res; 1126 } 1127 1128 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 1129 unsigned long whence) 1130 { 1131 TEE_Result res; 1132 struct tee_ta_session *sess; 1133 struct tee_obj *o; 1134 int32_t off; 1135 size_t attr_size; 1136 1137 res = tee_ta_get_current_session(&sess); 1138 if (res != TEE_SUCCESS) 1139 goto exit; 1140 1141 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1142 tee_svc_uref_to_vaddr(obj), &o); 1143 if (res != TEE_SUCCESS) 1144 goto exit; 1145 1146 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1147 res = TEE_ERROR_BAD_STATE; 1148 goto exit; 1149 } 1150 1151 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1152 if (res != TEE_SUCCESS) 1153 goto exit; 1154 1155 off = offset; 1156 if (whence == TEE_DATA_SEEK_SET) 1157 off += sizeof(struct tee_svc_storage_head) + attr_size; 1158 1159 res = o->pobj->fops->seek(o->fh, off, whence, &off); 1160 if (res != TEE_SUCCESS) 1161 goto exit; 1162 o->info.dataPosition = off - (sizeof(struct tee_svc_storage_head) + 1163 attr_size); 1164 1165 exit: 1166 return res; 1167 } 1168 1169 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1170 { 1171 struct tee_storage_enum_head *eh = &utc->storage_enums; 1172 1173 /* disregard return value */ 1174 while (!TAILQ_EMPTY(eh)) 1175 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1176 } 1177