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