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 static TEE_Result tee_svc_storage_update_head(struct tee_obj *o, 301 uint32_t ds_size) 302 { 303 TEE_Result res; 304 const struct tee_file_operations *fops; 305 int32_t old_off; 306 307 fops = o->pobj->fops; 308 309 /* save original offset */ 310 res = fops->seek(o->fh, 0, TEE_DATA_SEEK_CUR, &old_off); 311 if (res != TEE_SUCCESS) 312 return res; 313 314 /* update head.ds_size */ 315 res = fops->seek(o->fh, offsetof(struct tee_svc_storage_head, 316 ds_size), TEE_DATA_SEEK_SET, NULL); 317 if (res != TEE_SUCCESS) 318 return res; 319 320 res = fops->write(o->fh, &ds_size, sizeof(uint32_t)); 321 if (res != TEE_SUCCESS) 322 return res; 323 324 /* restore original offset */ 325 res = fops->seek(o->fh, old_off, TEE_DATA_SEEK_SET, NULL); 326 return res; 327 } 328 329 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, 330 struct tee_obj *o, 331 struct tee_obj *attr_o, void *data, 332 uint32_t len) 333 { 334 TEE_Result res = TEE_SUCCESS; 335 struct tee_svc_storage_head head; 336 char *tmpfile = NULL; 337 const struct tee_file_operations *fops; 338 void *attr = NULL; 339 size_t attr_size = 0; 340 341 if (o == NULL || o->pobj == NULL) 342 return TEE_ERROR_BAD_PARAMETERS; 343 344 fops = o->pobj->fops; 345 346 /* create temporary persistent object filename */ 347 tmpfile = tee_svc_storage_create_filename(sess, 348 o->pobj->obj_id, 349 o->pobj->obj_id_len, 350 true); 351 352 if (tmpfile == NULL) { 353 res = TEE_ERROR_OUT_OF_MEMORY; 354 goto exit; 355 } 356 357 mutex_lock(&ta_dir_mutex); 358 res = fops->create(tmpfile, &o->fh); 359 mutex_unlock(&ta_dir_mutex); 360 if (res != TEE_SUCCESS) 361 goto exit; 362 363 if (attr_o) { 364 res = tee_obj_set_type(o, attr_o->info.objectType, 365 attr_o->info.maxKeySize); 366 if (res != TEE_SUCCESS) 367 goto exit; 368 res = tee_obj_attr_copy_from(o, attr_o); 369 if (res != TEE_SUCCESS) 370 goto exit; 371 o->have_attrs = attr_o->have_attrs; 372 o->info.objectUsage = attr_o->info.objectUsage; 373 o->info.keySize = attr_o->info.keySize; 374 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 375 if (res != TEE_SUCCESS) 376 goto exit; 377 if (attr_size) { 378 attr = malloc(attr_size); 379 if (!attr) { 380 res = TEE_ERROR_OUT_OF_MEMORY; 381 goto exit; 382 } 383 res = tee_obj_attr_to_binary(o, attr, &attr_size); 384 if (res != TEE_SUCCESS) 385 goto exit; 386 } 387 } else { 388 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 389 if (res != TEE_SUCCESS) 390 goto exit; 391 } 392 393 /* write head */ 394 head.magic = TEE_SVC_STORAGE_MAGIC; 395 head.head_size = sizeof(struct tee_svc_storage_head); 396 head.meta_size = attr_size; 397 head.ds_size = len; 398 head.keySize = o->info.keySize; 399 head.maxKeySize = o->info.maxKeySize; 400 head.objectUsage = o->info.objectUsage; 401 head.objectType = o->info.objectType; 402 head.have_attrs = o->have_attrs; 403 404 /* write head */ 405 res = fops->write(o->fh, &head, sizeof(struct tee_svc_storage_head)); 406 if (res != TEE_SUCCESS) 407 goto exit; 408 409 /* write meta */ 410 res = fops->write(o->fh, attr, attr_size); 411 if (res != TEE_SUCCESS) 412 goto exit; 413 414 /* write init data */ 415 o->info.dataSize = len; 416 417 /* write data to fs if needed */ 418 if (data && len) 419 res = fops->write(o->fh, data, len); 420 421 exit: 422 free(attr); 423 free(tmpfile); 424 fops->close(&o->fh); 425 426 return res; 427 } 428 429 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 430 size_t object_id_len, unsigned long flags, 431 uint32_t *obj) 432 { 433 TEE_Result res; 434 struct tee_ta_session *sess; 435 struct tee_obj *o = NULL; 436 char *file = NULL; 437 struct tee_pobj *po = NULL; 438 struct user_ta_ctx *utc; 439 const struct tee_file_operations *fops = file_ops(storage_id); 440 size_t attr_size; 441 442 if (!fops) { 443 res = TEE_ERROR_ITEM_NOT_FOUND; 444 goto exit; 445 } 446 447 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 448 res = TEE_ERROR_BAD_PARAMETERS; 449 goto exit; 450 } 451 452 res = tee_ta_get_current_session(&sess); 453 if (res != TEE_SUCCESS) 454 goto err; 455 utc = to_user_ta_ctx(sess->ctx); 456 457 res = tee_mmu_check_access_rights(utc, 458 TEE_MEMORY_ACCESS_READ | 459 TEE_MEMORY_ACCESS_ANY_OWNER, 460 (uaddr_t) object_id, 461 object_id_len); 462 if (res != TEE_SUCCESS) 463 goto err; 464 465 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 466 object_id_len, flags, fops, &po); 467 if (res != TEE_SUCCESS) 468 goto err; 469 470 o = tee_obj_alloc(); 471 if (o == NULL) { 472 tee_pobj_release(po); 473 res = TEE_ERROR_OUT_OF_MEMORY; 474 goto err; 475 } 476 477 o->info.handleFlags = 478 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 479 o->flags = flags; 480 o->pobj = po; 481 tee_obj_add(utc, o); 482 483 res = tee_svc_storage_read_head(sess, o); 484 if (res != TEE_SUCCESS) { 485 if (res == TEE_ERROR_CORRUPT_OBJECT) { 486 EMSG("Object corrupt"); 487 goto err; 488 } 489 goto oclose; 490 } 491 492 res = tee_svc_copy_kaddr_to_uref(obj, o); 493 if (res != TEE_SUCCESS) 494 goto oclose; 495 496 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 497 if (res != TEE_SUCCESS) 498 goto oclose; 499 500 res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, 501 TEE_DATA_SEEK_SET, NULL); 502 if (res != TEE_SUCCESS) 503 goto err; 504 505 goto exit; 506 507 oclose: 508 tee_obj_close(utc, o); 509 o = NULL; 510 511 err: 512 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 513 res = TEE_ERROR_CORRUPT_OBJECT; 514 if (res == TEE_ERROR_CORRUPT_OBJECT && o) 515 tee_svc_storage_remove_corrupt_obj(sess, o); 516 517 exit: 518 free(file); 519 file = NULL; 520 return res; 521 } 522 523 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 524 size_t object_id_len, unsigned long flags, 525 unsigned long attr, void *data, size_t len, 526 uint32_t *obj) 527 { 528 TEE_Result res; 529 struct tee_ta_session *sess; 530 struct tee_obj *o = NULL; 531 struct tee_obj *attr_o = NULL; 532 char *file = NULL; 533 struct tee_pobj *po = NULL; 534 char *tmpfile = NULL; 535 struct user_ta_ctx *utc; 536 const struct tee_file_operations *fops = file_ops(storage_id); 537 size_t attr_size; 538 539 if (!fops) 540 return TEE_ERROR_ITEM_NOT_FOUND; 541 542 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 543 return TEE_ERROR_BAD_PARAMETERS; 544 545 res = tee_ta_get_current_session(&sess); 546 if (res != TEE_SUCCESS) 547 return res; 548 utc = to_user_ta_ctx(sess->ctx); 549 550 res = tee_mmu_check_access_rights(utc, 551 TEE_MEMORY_ACCESS_READ | 552 TEE_MEMORY_ACCESS_ANY_OWNER, 553 (uaddr_t) object_id, 554 object_id_len); 555 if (res != TEE_SUCCESS) 556 goto err; 557 558 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 559 object_id_len, flags, fops, &po); 560 if (res != TEE_SUCCESS) 561 goto err; 562 563 /* check rights of the provided buffer */ 564 if (data && len) { 565 res = tee_mmu_check_access_rights(utc, 566 TEE_MEMORY_ACCESS_READ | 567 TEE_MEMORY_ACCESS_ANY_OWNER, 568 (uaddr_t) data, len); 569 570 if (res != TEE_SUCCESS) 571 goto err; 572 } 573 574 o = tee_obj_alloc(); 575 if (o == NULL) { 576 res = TEE_ERROR_OUT_OF_MEMORY; 577 goto err; 578 } 579 580 o->info.handleFlags = 581 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 582 o->flags = flags; 583 o->pobj = po; 584 585 if (attr != TEE_HANDLE_NULL) { 586 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 587 &attr_o); 588 if (res != TEE_SUCCESS) 589 goto err; 590 } 591 592 res = tee_svc_storage_init_file(sess, o, attr_o, data, len); 593 if (res != TEE_SUCCESS) 594 goto err; 595 596 /* create persistent object filename */ 597 file = tee_svc_storage_create_filename(sess, object_id, 598 object_id_len, false); 599 if (file == NULL) { 600 res = TEE_ERROR_OUT_OF_MEMORY; 601 goto err; 602 } 603 604 /* create temporary persistent object filename */ 605 tmpfile = tee_svc_storage_create_filename(sess, object_id, 606 object_id_len, 607 true); 608 if (tmpfile == NULL) { 609 res = TEE_ERROR_OUT_OF_MEMORY; 610 goto err; 611 } 612 613 /* rename temporary persistent object filename */ 614 res = fops->rename(tmpfile, file, !!(flags & TEE_DATA_FLAG_OVERWRITE)); 615 if (res != TEE_SUCCESS) 616 goto rmfile; 617 618 res = fops->open(file, &o->fh); 619 if (res != TEE_SUCCESS) 620 goto err; 621 622 tee_obj_add(utc, o); 623 624 res = tee_svc_copy_kaddr_to_uref(obj, o); 625 if (res != TEE_SUCCESS) 626 goto oclose; 627 628 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 629 if (res != TEE_SUCCESS) 630 goto oclose; 631 632 res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, 633 TEE_DATA_SEEK_SET, NULL); 634 if (res != TEE_SUCCESS) 635 goto oclose; 636 637 goto exit; 638 639 oclose: 640 tee_obj_close(utc, o); 641 goto exit; 642 643 rmfile: 644 fops->remove(tmpfile); 645 646 err: 647 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 648 res = TEE_ERROR_CORRUPT_OBJECT; 649 if (res == TEE_ERROR_CORRUPT_OBJECT && file) 650 fops->remove(file); 651 if (o) 652 fops->close(&o->fh); 653 if (po) 654 tee_pobj_release(po); 655 free(o); 656 657 exit: 658 free(file); 659 free(tmpfile); 660 661 return res; 662 } 663 664 TEE_Result syscall_storage_obj_del(unsigned long obj) 665 { 666 TEE_Result res; 667 struct tee_ta_session *sess; 668 struct tee_obj *o; 669 char *file; 670 struct user_ta_ctx *utc; 671 const struct tee_file_operations *fops; 672 673 res = tee_ta_get_current_session(&sess); 674 if (res != TEE_SUCCESS) 675 return res; 676 utc = to_user_ta_ctx(sess->ctx); 677 678 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 679 if (res != TEE_SUCCESS) 680 return res; 681 682 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 683 return TEE_ERROR_ACCESS_CONFLICT; 684 685 if (o->pobj == NULL || o->pobj->obj_id == NULL) 686 return TEE_ERROR_BAD_STATE; 687 688 file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 689 o->pobj->obj_id_len, false); 690 if (file == NULL) 691 return TEE_ERROR_OUT_OF_MEMORY; 692 693 fops = o->pobj->fops; 694 tee_obj_close(utc, o); 695 696 res = fops->remove(file); 697 free(file); 698 return res; 699 } 700 701 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 702 size_t object_id_len) 703 { 704 TEE_Result res; 705 struct tee_ta_session *sess; 706 struct tee_obj *o; 707 struct tee_pobj *po = NULL; 708 char *new_file = NULL; 709 char *old_file = NULL; 710 struct user_ta_ctx *utc; 711 const struct tee_file_operations *fops; 712 713 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 714 return TEE_ERROR_BAD_PARAMETERS; 715 716 res = tee_ta_get_current_session(&sess); 717 if (res != TEE_SUCCESS) 718 return res; 719 utc = to_user_ta_ctx(sess->ctx); 720 721 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 722 if (res != TEE_SUCCESS) 723 return res; 724 725 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 726 res = TEE_ERROR_BAD_STATE; 727 goto exit; 728 } 729 730 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 731 res = TEE_ERROR_BAD_STATE; 732 goto exit; 733 } 734 735 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 736 res = TEE_ERROR_BAD_STATE; 737 goto exit; 738 } 739 740 res = tee_mmu_check_access_rights(utc, 741 TEE_MEMORY_ACCESS_READ | 742 TEE_MEMORY_ACCESS_ANY_OWNER, 743 (uaddr_t) object_id, object_id_len); 744 if (res != TEE_SUCCESS) 745 goto exit; 746 747 /* get new ds name */ 748 new_file = tee_svc_storage_create_filename(sess, object_id, 749 object_id_len, false); 750 if (new_file == NULL) { 751 res = TEE_ERROR_OUT_OF_MEMORY; 752 goto exit; 753 } 754 755 old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 756 o->pobj->obj_id_len, false); 757 if (old_file == NULL) { 758 res = TEE_ERROR_OUT_OF_MEMORY; 759 goto exit; 760 } 761 762 /* reserve dest name */ 763 fops = o->pobj->fops; 764 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 765 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 766 fops, &po); 767 if (res != TEE_SUCCESS) 768 goto exit; 769 770 /* move */ 771 res = fops->rename(old_file, new_file, false /* no overwrite */); 772 if (res == TEE_ERROR_GENERIC) 773 goto exit; 774 775 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 776 777 exit: 778 tee_pobj_release(po); 779 780 free(new_file); 781 free(old_file); 782 783 return res; 784 } 785 786 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 787 { 788 struct tee_storage_enum *e; 789 struct tee_ta_session *sess; 790 TEE_Result res; 791 struct user_ta_ctx *utc; 792 793 if (obj_enum == NULL) 794 return TEE_ERROR_BAD_PARAMETERS; 795 796 res = tee_ta_get_current_session(&sess); 797 if (res != TEE_SUCCESS) 798 return res; 799 utc = to_user_ta_ctx(sess->ctx); 800 801 e = malloc(sizeof(struct tee_storage_enum)); 802 if (e == NULL) 803 return TEE_ERROR_OUT_OF_MEMORY; 804 805 e->dir = NULL; 806 e->fops = NULL; 807 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 808 809 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 810 } 811 812 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 813 { 814 struct tee_storage_enum *e; 815 TEE_Result res; 816 struct tee_ta_session *sess; 817 struct user_ta_ctx *utc; 818 819 res = tee_ta_get_current_session(&sess); 820 if (res != TEE_SUCCESS) 821 return res; 822 utc = to_user_ta_ctx(sess->ctx); 823 824 res = tee_svc_storage_get_enum(utc, 825 tee_svc_uref_to_vaddr(obj_enum), &e); 826 if (res != TEE_SUCCESS) 827 return res; 828 829 return tee_svc_close_enum(utc, e); 830 } 831 832 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 833 { 834 struct tee_storage_enum *e; 835 TEE_Result res; 836 struct tee_ta_session *sess; 837 838 res = tee_ta_get_current_session(&sess); 839 if (res != TEE_SUCCESS) 840 return res; 841 842 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 843 tee_svc_uref_to_vaddr(obj_enum), &e); 844 if (res != TEE_SUCCESS) 845 return res; 846 847 e->fops->closedir(e->dir); 848 e->dir = NULL; 849 850 return TEE_SUCCESS; 851 } 852 853 static TEE_Result tee_svc_storage_set_enum(char *d_name, 854 const struct tee_file_operations *fops, 855 struct tee_obj *o) 856 { 857 TEE_Result res; 858 uint32_t blen; 859 uint32_t hslen; 860 861 o->info.handleFlags = 862 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 863 o->info.objectUsage = TEE_USAGE_DEFAULT; 864 865 hslen = strlen(d_name); 866 blen = TEE_HS2B_BBUF_SIZE(hslen); 867 o->pobj->obj_id = malloc(blen); 868 if (!o->pobj->obj_id) { 869 res = TEE_ERROR_OUT_OF_MEMORY; 870 goto exit; 871 } 872 tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen); 873 o->pobj->obj_id_len = blen; 874 o->pobj->fops = fops; 875 876 res = TEE_SUCCESS; 877 878 exit: 879 return res; 880 881 } 882 883 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 884 unsigned long storage_id) 885 { 886 struct tee_storage_enum *e; 887 char *dir; 888 TEE_Result res; 889 struct tee_ta_session *sess; 890 const struct tee_file_operations *fops = file_ops(storage_id); 891 892 res = tee_ta_get_current_session(&sess); 893 if (res != TEE_SUCCESS) 894 return res; 895 896 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 897 tee_svc_uref_to_vaddr(obj_enum), &e); 898 if (res != TEE_SUCCESS) 899 return res; 900 901 if (!fops) 902 return TEE_ERROR_ITEM_NOT_FOUND; 903 904 e->fops = fops; 905 dir = tee_svc_storage_create_dirname(sess); 906 if (dir == NULL) { 907 res = TEE_ERROR_OUT_OF_MEMORY; 908 goto exit; 909 } 910 911 assert(!e->dir); 912 res = fops->opendir(dir, &e->dir); 913 free(dir); 914 exit: 915 return res; 916 } 917 918 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 919 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 920 { 921 struct tee_storage_enum *e; 922 struct tee_fs_dirent *d; 923 TEE_Result res = TEE_SUCCESS; 924 struct tee_ta_session *sess; 925 struct tee_obj *o = NULL; 926 uint64_t l; 927 struct user_ta_ctx *utc; 928 929 res = tee_ta_get_current_session(&sess); 930 if (res != TEE_SUCCESS) 931 goto exit; 932 utc = to_user_ta_ctx(sess->ctx); 933 934 res = tee_svc_storage_get_enum(utc, 935 tee_svc_uref_to_vaddr(obj_enum), &e); 936 if (res != TEE_SUCCESS) 937 goto exit; 938 939 /* check rights of the provided buffers */ 940 res = tee_mmu_check_access_rights(utc, 941 TEE_MEMORY_ACCESS_WRITE | 942 TEE_MEMORY_ACCESS_ANY_OWNER, 943 (uaddr_t) info, 944 sizeof(TEE_ObjectInfo)); 945 if (res != TEE_SUCCESS) 946 goto exit; 947 948 res = tee_mmu_check_access_rights(utc, 949 TEE_MEMORY_ACCESS_WRITE | 950 TEE_MEMORY_ACCESS_ANY_OWNER, 951 (uaddr_t) obj_id, 952 TEE_OBJECT_ID_MAX_LEN); 953 if (res != TEE_SUCCESS) 954 goto exit; 955 956 if (!e->fops) { 957 res = TEE_ERROR_ITEM_NOT_FOUND; 958 goto exit; 959 } 960 961 res = e->fops->readdir(e->dir, &d); 962 if (res != TEE_SUCCESS) 963 goto exit; 964 965 o = tee_obj_alloc(); 966 if (o == NULL) { 967 res = TEE_ERROR_OUT_OF_MEMORY; 968 goto exit; 969 } 970 o->flags = TEE_DATA_FLAG_SHARE_READ; 971 972 o->pobj = calloc(1, sizeof(struct tee_pobj)); 973 if (!o->pobj) { 974 res = TEE_ERROR_OUT_OF_MEMORY; 975 goto exit; 976 } 977 978 res = tee_svc_storage_set_enum(d->d_name, e->fops, o); 979 if (res != TEE_SUCCESS) 980 goto exit; 981 982 res = tee_svc_storage_read_head(sess, o); 983 if (res != TEE_SUCCESS) 984 goto exit; 985 986 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 987 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 988 989 l = o->pobj->obj_id_len; 990 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 991 992 exit: 993 if (o) { 994 if (o->pobj) { 995 o->pobj->fops->close(&o->fh); 996 free(o->pobj->obj_id); 997 } 998 free(o->pobj); 999 tee_obj_free(o); 1000 } 1001 1002 return res; 1003 } 1004 1005 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 1006 uint64_t *count) 1007 { 1008 TEE_Result res; 1009 struct tee_ta_session *sess; 1010 struct tee_obj *o; 1011 uint64_t u_count; 1012 struct user_ta_ctx *utc; 1013 size_t bytes; 1014 1015 res = tee_ta_get_current_session(&sess); 1016 if (res != TEE_SUCCESS) 1017 goto exit; 1018 utc = to_user_ta_ctx(sess->ctx); 1019 1020 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1021 if (res != TEE_SUCCESS) 1022 goto exit; 1023 1024 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1025 res = TEE_ERROR_BAD_STATE; 1026 goto exit; 1027 } 1028 1029 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 1030 res = TEE_ERROR_ACCESS_CONFLICT; 1031 goto exit; 1032 } 1033 1034 /* check rights of the provided buffer */ 1035 res = tee_mmu_check_access_rights(utc, 1036 TEE_MEMORY_ACCESS_WRITE | 1037 TEE_MEMORY_ACCESS_ANY_OWNER, 1038 (uaddr_t) data, len); 1039 if (res != TEE_SUCCESS) 1040 goto exit; 1041 1042 bytes = len; 1043 res = o->pobj->fops->read(o->fh, data, &bytes); 1044 if (res != TEE_SUCCESS) { 1045 EMSG("Error code=%x\n", (uint32_t)res); 1046 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1047 EMSG("Object corrupt\n"); 1048 tee_svc_storage_remove_corrupt_obj(sess, o); 1049 } 1050 goto exit; 1051 } 1052 1053 o->info.dataPosition += bytes; 1054 1055 u_count = bytes; 1056 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 1057 exit: 1058 return res; 1059 } 1060 1061 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 1062 { 1063 TEE_Result res; 1064 struct tee_ta_session *sess; 1065 struct tee_obj *o; 1066 struct user_ta_ctx *utc; 1067 1068 res = tee_ta_get_current_session(&sess); 1069 if (res != TEE_SUCCESS) 1070 goto exit; 1071 utc = to_user_ta_ctx(sess->ctx); 1072 1073 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1074 if (res != TEE_SUCCESS) 1075 goto exit; 1076 1077 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1078 res = TEE_ERROR_BAD_STATE; 1079 goto exit; 1080 } 1081 1082 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1083 res = TEE_ERROR_ACCESS_CONFLICT; 1084 goto exit; 1085 } 1086 1087 /* check rights of the provided buffer */ 1088 res = tee_mmu_check_access_rights(utc, 1089 TEE_MEMORY_ACCESS_READ | 1090 TEE_MEMORY_ACCESS_ANY_OWNER, 1091 (uaddr_t) data, len); 1092 if (res != TEE_SUCCESS) 1093 goto exit; 1094 1095 res = o->pobj->fops->write(o->fh, data, len); 1096 if (res != TEE_SUCCESS) 1097 goto exit; 1098 1099 o->info.dataPosition += len; 1100 if (o->info.dataPosition > o->info.dataSize) { 1101 res = tee_svc_storage_update_head(o, o->info.dataPosition); 1102 if (res != TEE_SUCCESS) 1103 goto exit; 1104 o->info.dataSize = o->info.dataPosition; 1105 } 1106 1107 exit: 1108 return res; 1109 } 1110 1111 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 1112 { 1113 TEE_Result res; 1114 struct tee_ta_session *sess; 1115 struct tee_obj *o; 1116 size_t off; 1117 size_t attr_size; 1118 1119 res = tee_ta_get_current_session(&sess); 1120 if (res != TEE_SUCCESS) 1121 goto exit; 1122 1123 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1124 tee_svc_uref_to_vaddr(obj), &o); 1125 if (res != TEE_SUCCESS) 1126 goto exit; 1127 1128 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1129 res = TEE_ERROR_BAD_STATE; 1130 goto exit; 1131 } 1132 1133 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1134 res = TEE_ERROR_ACCESS_CONFLICT; 1135 goto exit; 1136 } 1137 1138 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1139 if (res != TEE_SUCCESS) 1140 goto exit; 1141 1142 off = sizeof(struct tee_svc_storage_head) + attr_size; 1143 res = o->pobj->fops->truncate(o->fh, len + off); 1144 if (res != TEE_SUCCESS) { 1145 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1146 EMSG("Object corrupt\n"); 1147 res = tee_svc_storage_remove_corrupt_obj(sess, o); 1148 if (res != TEE_SUCCESS) 1149 goto exit; 1150 res = TEE_ERROR_CORRUPT_OBJECT; 1151 goto exit; 1152 } else 1153 res = TEE_ERROR_GENERIC; 1154 } 1155 1156 exit: 1157 return res; 1158 } 1159 1160 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 1161 unsigned long whence) 1162 { 1163 TEE_Result res; 1164 struct tee_ta_session *sess; 1165 struct tee_obj *o; 1166 int32_t off; 1167 size_t attr_size; 1168 1169 res = tee_ta_get_current_session(&sess); 1170 if (res != TEE_SUCCESS) 1171 goto exit; 1172 1173 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1174 tee_svc_uref_to_vaddr(obj), &o); 1175 if (res != TEE_SUCCESS) 1176 goto exit; 1177 1178 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1179 res = TEE_ERROR_BAD_STATE; 1180 goto exit; 1181 } 1182 1183 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1184 if (res != TEE_SUCCESS) 1185 goto exit; 1186 1187 off = offset; 1188 if (whence == TEE_DATA_SEEK_SET) 1189 off += sizeof(struct tee_svc_storage_head) + attr_size; 1190 1191 res = o->pobj->fops->seek(o->fh, off, whence, &off); 1192 if (res != TEE_SUCCESS) 1193 goto exit; 1194 o->info.dataPosition = off - (sizeof(struct tee_svc_storage_head) + 1195 attr_size); 1196 1197 exit: 1198 return res; 1199 } 1200 1201 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1202 { 1203 struct tee_storage_enum_head *eh = &utc->storage_enums; 1204 1205 /* disregard return value */ 1206 while (!TAILQ_EMPTY(eh)) 1207 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1208 } 1209