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/tee_ta_manager.h> 29 #include <kernel/tee_misc.h> 30 #include <mm/tee_mmu.h> 31 #include <tee/tee_fs.h> 32 #include <tee/tee_fs_defs.h> 33 #include <tee/tee_obj.h> 34 #include <tee/tee_svc.h> 35 #include <tee/tee_pobj.h> 36 #include <tee/tee_svc_storage.h> 37 #include <tee/tee_svc_cryp.h> 38 #include <tee_api_defines.h> 39 #include <tee_api_defines_extensions.h> 40 #include <trace.h> 41 42 /* 43 * Returns the appropriate tee_file_operations for the specified storage ID. 44 * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise 45 * RPMB. 46 */ 47 static const struct tee_file_operations *file_ops(uint32_t storage_id) 48 { 49 50 switch (storage_id) { 51 case TEE_STORAGE_PRIVATE: 52 #if defined(CFG_REE_FS) 53 return &ree_fs_ops; 54 #elif defined(CFG_RPMB_FS) 55 return &rpmb_fs_ops; 56 #elif defined(CFG_SQL_FS) 57 return &sql_fs_ops; 58 #else 59 #error At least one filesystem must be enabled. 60 #endif 61 #ifdef CFG_REE_FS 62 case TEE_STORAGE_PRIVATE_REE: 63 return &ree_fs_ops; 64 #endif 65 #ifdef CFG_RPMB_FS 66 case TEE_STORAGE_PRIVATE_RPMB: 67 return &rpmb_fs_ops; 68 #endif 69 #ifdef CFG_SQL_FS 70 case TEE_STORAGE_PRIVATE_SQL: 71 return &sql_fs_ops; 72 #endif 73 default: 74 return NULL; 75 } 76 } 77 78 /* SSF (Secure Storage File version 00 */ 79 #define TEE_SVC_STORAGE_MAGIC 0x53534600; 80 81 /* Header of GP formated secure storage files */ 82 struct tee_svc_storage_head { 83 uint32_t magic; 84 uint32_t head_size; 85 uint32_t meta_size; 86 uint32_t ds_size; 87 uint32_t keySize; 88 uint32_t maxKeySize; 89 uint32_t objectUsage; 90 uint32_t objectType; 91 uint32_t have_attrs; 92 }; 93 94 struct tee_storage_enum { 95 TAILQ_ENTRY(tee_storage_enum) link; 96 struct tee_fs_dir *dir; 97 const struct tee_file_operations *fops; 98 }; 99 100 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, 101 uint32_t enum_id, 102 struct tee_storage_enum **e_out) 103 { 104 struct tee_storage_enum *e; 105 106 TAILQ_FOREACH(e, &utc->storage_enums, link) { 107 if (enum_id == (vaddr_t)e) { 108 *e_out = e; 109 return TEE_SUCCESS; 110 } 111 } 112 return TEE_ERROR_BAD_PARAMETERS; 113 } 114 115 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, 116 struct tee_storage_enum *e) 117 { 118 int ret; 119 120 if (e == NULL || utc == NULL) 121 return TEE_ERROR_BAD_PARAMETERS; 122 123 TAILQ_REMOVE(&utc->storage_enums, e, link); 124 125 if (!e->fops) 126 return TEE_ERROR_ITEM_NOT_FOUND; 127 128 ret = e->fops->closedir(e->dir); 129 e->dir = NULL; 130 e->fops = NULL; 131 132 free(e); 133 134 if (ret != 0) 135 return TEE_ERROR_ITEM_NOT_FOUND; 136 137 return TEE_SUCCESS; 138 } 139 140 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ 141 char *tee_svc_storage_create_filename(struct tee_ta_session *sess, 142 void *object_id, 143 uint32_t object_id_len, 144 bool transient) 145 { 146 uint8_t *file; 147 uint32_t pos = 0; 148 uint32_t hslen = 1 /* Leading slash */ 149 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) 150 + 1; /* Intermediate slash */ 151 152 /* +1 for the '.' (temporary persistent object) */ 153 if (transient) 154 hslen++; 155 156 file = malloc(hslen); 157 if (!file) 158 return NULL; 159 160 file[pos++] = '/'; 161 pos += tee_b2hs((uint8_t *)&sess->ctx->uuid, &file[pos], 162 sizeof(TEE_UUID), hslen); 163 file[pos++] = '/'; 164 165 if (transient) 166 file[pos++] = '.'; 167 168 tee_b2hs(object_id, file + pos, object_id_len, hslen - pos); 169 170 return (char *)file; 171 } 172 173 /* "/TA_uuid" */ 174 char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) 175 { 176 uint8_t *dir; 177 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; 178 179 dir = malloc(hslen); 180 if (!dir) 181 return NULL; 182 183 dir[0] = '/'; 184 tee_b2hs((uint8_t *)&sess->ctx->uuid, dir + 1, sizeof(TEE_UUID), 185 hslen); 186 187 return (char *)dir; 188 } 189 190 static TEE_Result tee_svc_storage_remove_corrupt_obj( 191 struct tee_ta_session *sess, 192 struct tee_obj *o) 193 { 194 TEE_Result res; 195 char *file = NULL; 196 char *dir = NULL; 197 const struct tee_file_operations *fops = o->pobj->fops; 198 199 file = tee_svc_storage_create_filename(sess, 200 o->pobj->obj_id, 201 o->pobj->obj_id_len, 202 false); 203 if (file == NULL) { 204 res = TEE_ERROR_OUT_OF_MEMORY; 205 goto exit; 206 } 207 208 tee_obj_close(to_user_ta_ctx(sess->ctx), o); 209 fops->unlink(file); 210 free(file); 211 dir = tee_svc_storage_create_dirname(sess); 212 if (dir != NULL) { 213 fops->rmdir(dir); 214 free(dir); 215 } 216 217 res = TEE_SUCCESS; 218 219 exit: 220 return res; 221 } 222 223 static uint32_t tee_svc_storage_conv_oflags(uint32_t flags) 224 { 225 uint32_t out = 0; 226 227 if (flags & (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_SHARE_READ)) { 228 if (flags & (TEE_DATA_FLAG_ACCESS_WRITE | 229 TEE_DATA_FLAG_ACCESS_WRITE_META | 230 TEE_DATA_FLAG_SHARE_WRITE)) 231 out |= TEE_FS_O_RDWR; 232 else 233 out |= TEE_FS_O_RDONLY; 234 } else { 235 if (flags & (TEE_DATA_FLAG_ACCESS_WRITE | 236 TEE_DATA_FLAG_ACCESS_WRITE_META | 237 TEE_DATA_FLAG_SHARE_WRITE)) 238 out |= TEE_FS_O_WRONLY; 239 } 240 241 return out; 242 } 243 244 static int tee_svc_storage_conv_whence(TEE_Whence whence) 245 { 246 switch (whence) { 247 case TEE_DATA_SEEK_SET: 248 return TEE_FS_SEEK_SET; 249 case TEE_DATA_SEEK_CUR: 250 return TEE_FS_SEEK_CUR; 251 case TEE_DATA_SEEK_END: 252 return TEE_FS_SEEK_END; 253 default: 254 return -1; 255 } 256 } 257 258 static TEE_Result tee_svc_storage_create_file(struct tee_ta_session *sess, 259 char *file, 260 const struct tee_file_operations *fops, 261 int *fd) 262 { 263 TEE_Result res = TEE_SUCCESS; 264 TEE_Result errno; 265 char *dir = NULL; 266 int tmp; 267 int err; 268 uint32_t cflags = TEE_FS_O_WRONLY | 269 TEE_FS_O_CREATE | TEE_FS_O_TRUNC; 270 271 dir = tee_svc_storage_create_dirname(sess); 272 if (dir == NULL) { 273 res = TEE_ERROR_OUT_OF_MEMORY; 274 goto exit; 275 } 276 277 /* try and make directory */ 278 err = fops->access(dir, TEE_FS_F_OK); 279 if (err) { 280 /* directory does not exists */ 281 tmp = fops->mkdir(dir, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR | 282 TEE_FS_S_IXUSR); 283 284 if (tmp < 0) { 285 /* error codes needs better granularity */ 286 res = TEE_ERROR_GENERIC; 287 goto exit; 288 } 289 } 290 291 /* try and open again */ 292 *fd = fops->open(&errno, file, cflags); 293 if (*fd < 0) 294 res = errno; 295 296 exit: 297 free(dir); 298 299 return res; 300 } 301 302 static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, 303 struct tee_obj *o) 304 { 305 TEE_Result res = TEE_SUCCESS; 306 TEE_Result errno; 307 int fd = -1; 308 int err; 309 struct tee_svc_storage_head head; 310 char *file = NULL; 311 const struct tee_file_operations *fops; 312 void *attr = NULL; 313 314 if (o == NULL || o->pobj == NULL) 315 return TEE_ERROR_BAD_PARAMETERS; 316 317 fops = o->pobj->fops; 318 319 file = tee_svc_storage_create_filename(sess, 320 o->pobj->obj_id, 321 o->pobj->obj_id_len, 322 false); 323 if (file == NULL) { 324 res = TEE_ERROR_OUT_OF_MEMORY; 325 goto exit; 326 } 327 328 fd = fops->open(&errno, file, TEE_FS_O_RDONLY); 329 free(file); 330 if (fd < 0) { 331 res = errno; 332 goto exit; 333 } 334 335 /* read head */ 336 err = fops->read(&errno, fd, &head, 337 sizeof(struct tee_svc_storage_head)); 338 if (err < 0) { 339 res = errno; 340 if (res == TEE_ERROR_CORRUPT_OBJECT) 341 EMSG("Head corrupt\n"); 342 goto exit; 343 } 344 345 if (err != sizeof(struct tee_svc_storage_head)) { 346 res = TEE_ERROR_BAD_FORMAT; 347 goto exit; 348 } 349 350 res = tee_obj_set_type(o, head.objectType, head.maxKeySize); 351 if (res != TEE_SUCCESS) 352 goto exit; 353 354 if (head.meta_size) { 355 attr = malloc(head.meta_size); 356 if (!attr) { 357 res = TEE_ERROR_OUT_OF_MEMORY; 358 goto exit; 359 } 360 361 /* read meta */ 362 err = fops->read(&errno, fd, attr, head.meta_size); 363 if (err != (int)head.meta_size) { 364 res = TEE_ERROR_CORRUPT_OBJECT; 365 goto exit; 366 } 367 } 368 369 res = tee_obj_attr_from_binary(o, attr, head.meta_size); 370 if (res != TEE_SUCCESS) 371 goto exit; 372 373 o->info.dataSize = head.ds_size; 374 o->info.keySize = head.keySize; 375 o->info.objectUsage = head.objectUsage; 376 o->info.objectType = head.objectType; 377 o->have_attrs = head.have_attrs; 378 379 exit: 380 free(attr); 381 if (fd >= 0) 382 fops->close(fd); 383 384 return res; 385 } 386 387 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, 388 struct tee_obj *o, 389 struct tee_obj *attr_o, void *data, 390 uint32_t len) 391 { 392 TEE_Result res = TEE_SUCCESS; 393 TEE_Result errno; 394 int fd = -1; 395 int err = -1; 396 struct tee_svc_storage_head head; 397 char *tmpfile = NULL; 398 const struct tee_file_operations *fops; 399 void *attr = NULL; 400 size_t attr_size = 0; 401 402 if (o == NULL || o->pobj == NULL) 403 return TEE_ERROR_BAD_PARAMETERS; 404 405 fops = o->pobj->fops; 406 407 /* create temporary persistent object filename */ 408 tmpfile = tee_svc_storage_create_filename(sess, 409 o->pobj->obj_id, 410 o->pobj->obj_id_len, 411 true); 412 413 if (tmpfile == NULL) { 414 res = TEE_ERROR_OUT_OF_MEMORY; 415 goto exit; 416 } 417 418 res = tee_svc_storage_create_file(sess, tmpfile, fops, &fd); 419 if (res != TEE_SUCCESS) 420 goto exit; 421 422 if (attr_o) { 423 res = tee_obj_set_type(o, attr_o->info.objectType, 424 attr_o->info.maxKeySize); 425 if (res != TEE_SUCCESS) 426 goto exit; 427 res = tee_obj_attr_copy_from(o, attr_o); 428 if (res != TEE_SUCCESS) 429 goto exit; 430 o->have_attrs = attr_o->have_attrs; 431 o->info.objectUsage = attr_o->info.objectUsage; 432 o->info.keySize = attr_o->info.keySize; 433 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 434 if (res != TEE_SUCCESS) 435 goto exit; 436 if (attr_size) { 437 attr = malloc(attr_size); 438 if (!attr) { 439 res = TEE_ERROR_OUT_OF_MEMORY; 440 goto exit; 441 } 442 res = tee_obj_attr_to_binary(o, attr, &attr_size); 443 if (res != TEE_SUCCESS) 444 goto exit; 445 } 446 } else { 447 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 448 if (res != TEE_SUCCESS) 449 goto exit; 450 } 451 452 /* write head */ 453 head.magic = TEE_SVC_STORAGE_MAGIC; 454 head.head_size = sizeof(struct tee_svc_storage_head); 455 head.meta_size = attr_size; 456 head.ds_size = len; 457 head.keySize = o->info.keySize; 458 head.maxKeySize = o->info.maxKeySize; 459 head.objectUsage = o->info.objectUsage; 460 head.objectType = o->info.objectType; 461 head.have_attrs = o->have_attrs; 462 463 /* write head */ 464 err = fops->write(&errno, fd, &head, 465 sizeof(struct tee_svc_storage_head)); 466 if (err < 0) 467 res = errno; 468 if (err != sizeof(struct tee_svc_storage_head)) 469 goto exit; 470 471 /* write meta */ 472 err = fops->write(&errno, fd, attr, attr_size); 473 if (err < 0) 474 res = errno; 475 if (err != (int)attr_size) 476 goto exit; 477 478 /* write init data */ 479 o->info.dataSize = len; 480 481 /* write data to fs if needed */ 482 if (data && len) { 483 err = fops->write(&errno, fd, data, len); 484 if (err < 0) 485 res = errno; 486 if (err != (int)len) 487 goto exit; 488 } 489 490 exit: 491 free(attr); 492 free(tmpfile); 493 tmpfile = NULL; 494 if (fd != -1) 495 fops->close(fd); 496 497 return res; 498 } 499 500 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 501 size_t object_id_len, unsigned long flags, 502 uint32_t *obj) 503 { 504 TEE_Result res; 505 TEE_Result errno; 506 struct tee_ta_session *sess; 507 struct tee_obj *o; 508 char *file = NULL; 509 int fs_flags; 510 int fd = -1; 511 tee_fs_off_t off; 512 tee_fs_off_t e_off; 513 struct tee_pobj *po = NULL; 514 int err = -1; 515 struct user_ta_ctx *utc; 516 const struct tee_file_operations *fops = file_ops(storage_id); 517 size_t attr_size; 518 519 if (!fops) { 520 res = TEE_ERROR_ITEM_NOT_FOUND; 521 goto exit; 522 } 523 524 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 525 res = TEE_ERROR_BAD_PARAMETERS; 526 goto exit; 527 } 528 529 res = tee_ta_get_current_session(&sess); 530 if (res != TEE_SUCCESS) 531 goto err; 532 utc = to_user_ta_ctx(sess->ctx); 533 534 res = tee_mmu_check_access_rights(utc, 535 TEE_MEMORY_ACCESS_READ | 536 TEE_MEMORY_ACCESS_ANY_OWNER, 537 (tee_uaddr_t) object_id, 538 object_id_len); 539 if (res != TEE_SUCCESS) 540 goto err; 541 542 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 543 object_id_len, flags, fops, &po); 544 if (res != TEE_SUCCESS) 545 goto err; 546 547 fs_flags = tee_svc_storage_conv_oflags(flags); 548 549 o = tee_obj_alloc(); 550 if (o == NULL) { 551 res = TEE_ERROR_OUT_OF_MEMORY; 552 goto err; 553 } 554 555 o->info.handleFlags = 556 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 557 o->flags = flags; 558 o->pobj = po; 559 560 res = tee_svc_storage_read_head(sess, o); 561 if (res != TEE_SUCCESS) { 562 tee_obj_add(utc, o); 563 if (res == TEE_ERROR_CORRUPT_OBJECT) { 564 EMSG("Object corrupt\n"); 565 res = tee_svc_storage_remove_corrupt_obj(sess, o); 566 if (res != TEE_SUCCESS) 567 goto exit; 568 res = TEE_ERROR_CORRUPT_OBJECT; 569 goto exit; 570 } 571 goto oclose; 572 } 573 574 file = tee_svc_storage_create_filename(sess, object_id, 575 object_id_len, false); 576 if (file == NULL) { 577 res = TEE_ERROR_OUT_OF_MEMORY; 578 goto err; 579 } 580 581 err = fops->access(file, TEE_FS_F_OK); 582 if (err) { 583 /* file not found */ 584 res = TEE_ERROR_STORAGE_NOT_AVAILABLE; 585 goto err; 586 } 587 588 fd = fops->open(&errno, file, fs_flags); 589 if (fd < 0) { 590 res = errno; 591 goto err; 592 } 593 o->fd = fd; 594 595 tee_obj_add(utc, o); 596 597 res = tee_svc_copy_kaddr_to_uref(obj, o); 598 if (res != TEE_SUCCESS) 599 goto oclose; 600 601 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 602 if (res != TEE_SUCCESS && res) 603 goto oclose; 604 605 e_off = sizeof(struct tee_svc_storage_head) + attr_size; 606 off = fops->lseek(&errno, fd, e_off, TEE_FS_SEEK_SET); 607 if (off != e_off) { 608 res = TEE_ERROR_NO_DATA; 609 goto oclose; 610 } else { 611 res = TEE_SUCCESS; 612 } 613 614 goto exit; 615 616 oclose: 617 tee_obj_close(utc, o); 618 619 err: 620 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 621 res = TEE_ERROR_CORRUPT_OBJECT; 622 if (res == TEE_ERROR_CORRUPT_OBJECT) 623 fops->unlink(file); 624 if (fd >= 0) 625 fops->close(fd); 626 if (po) 627 tee_pobj_release(po); 628 629 exit: 630 free(file); 631 file = NULL; 632 return res; 633 } 634 635 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 636 size_t object_id_len, unsigned long flags, 637 unsigned long attr, void *data, size_t len, 638 uint32_t *obj) 639 { 640 TEE_Result res; 641 TEE_Result errno; 642 struct tee_ta_session *sess; 643 struct tee_obj *o = NULL; 644 struct tee_obj *attr_o = NULL; 645 char *file = NULL; 646 int fd = -1; 647 int fs_flags; 648 tee_fs_off_t off; 649 tee_fs_off_t e_off; 650 struct tee_pobj *po = NULL; 651 char *tmpfile = NULL; 652 int err = -1; 653 int filedoesnotexist; 654 struct user_ta_ctx *utc; 655 const struct tee_file_operations *fops = file_ops(storage_id); 656 size_t attr_size; 657 658 if (!fops) 659 return TEE_ERROR_ITEM_NOT_FOUND; 660 661 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 662 return TEE_ERROR_BAD_PARAMETERS; 663 664 res = tee_ta_get_current_session(&sess); 665 if (res != TEE_SUCCESS) 666 return res; 667 utc = to_user_ta_ctx(sess->ctx); 668 669 res = tee_mmu_check_access_rights(utc, 670 TEE_MEMORY_ACCESS_READ | 671 TEE_MEMORY_ACCESS_ANY_OWNER, 672 (tee_uaddr_t) object_id, 673 object_id_len); 674 if (res != TEE_SUCCESS) 675 goto err; 676 677 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 678 object_id_len, flags, fops, &po); 679 if (res != TEE_SUCCESS) 680 goto err; 681 682 /* check rights of the provided buffer */ 683 if (data && len) { 684 res = tee_mmu_check_access_rights(utc, 685 TEE_MEMORY_ACCESS_READ | 686 TEE_MEMORY_ACCESS_ANY_OWNER, 687 (tee_uaddr_t) data, len); 688 689 if (res != TEE_SUCCESS) 690 goto err; 691 } 692 693 o = tee_obj_alloc(); 694 if (o == NULL) { 695 res = TEE_ERROR_OUT_OF_MEMORY; 696 goto err; 697 } 698 699 o->info.handleFlags = 700 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 701 o->flags = flags; 702 o->pobj = po; 703 704 if (attr != TEE_HANDLE_NULL) { 705 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 706 &attr_o); 707 if (res != TEE_SUCCESS) 708 goto err; 709 } 710 711 res = tee_svc_storage_init_file(sess, o, attr_o, data, len); 712 if (res != TEE_SUCCESS) 713 goto err; 714 715 /* create persistent object filename */ 716 file = tee_svc_storage_create_filename(sess, object_id, 717 object_id_len, false); 718 if (file == NULL) { 719 res = TEE_ERROR_OUT_OF_MEMORY; 720 goto err; 721 } 722 723 filedoesnotexist = fops->access(file, TEE_FS_F_OK); 724 if (!filedoesnotexist) { 725 /* file exists */ 726 if (!(flags & TEE_DATA_FLAG_OVERWRITE)) { 727 res = TEE_ERROR_ACCESS_CONFLICT; 728 goto err; 729 } 730 } 731 732 /* create temporary persistent object filename */ 733 tmpfile = tee_svc_storage_create_filename(sess, object_id, 734 object_id_len, 735 true); 736 if (tmpfile == NULL) { 737 res = TEE_ERROR_OUT_OF_MEMORY; 738 goto err; 739 } 740 741 /* 742 * remove the file if it exists, because rename does not perform 743 * this operation. Note that it delete and rename should be atomic, 744 * which is not the case currently. 745 * Fixme: unlink must be removed once rename() support prior deletion 746 * of the new file name when it already exists. 747 */ 748 if (!filedoesnotexist) 749 fops->unlink(file); 750 /* rename temporary persistent object filename */ 751 err = fops->rename(tmpfile, file); 752 if (err) { 753 /* error codes needs better granularity */ 754 res = TEE_ERROR_GENERIC; 755 goto rmfile; 756 } 757 758 fs_flags = tee_svc_storage_conv_oflags(flags); 759 760 fd = fops->open(&errno, file, fs_flags); 761 if (fd < 0) { 762 res = errno; 763 goto err; 764 } 765 o->fd = fd; 766 767 tee_obj_add(utc, o); 768 769 res = tee_svc_copy_kaddr_to_uref(obj, o); 770 if (res != TEE_SUCCESS) 771 goto oclose; 772 773 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 774 if (res != TEE_SUCCESS) 775 goto oclose; 776 777 e_off = sizeof(struct tee_svc_storage_head) + attr_size; 778 off = fops->lseek(&errno, fd, e_off, TEE_FS_SEEK_SET); 779 if (off != e_off) { 780 res = TEE_ERROR_NO_DATA; 781 goto oclose; 782 } else { 783 res = TEE_SUCCESS; 784 } 785 786 goto exit; 787 788 oclose: 789 tee_obj_close(utc, o); 790 goto exit; 791 792 rmfile: 793 fops->unlink(tmpfile); 794 795 err: 796 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 797 res = TEE_ERROR_CORRUPT_OBJECT; 798 if (res == TEE_ERROR_CORRUPT_OBJECT && file) 799 fops->unlink(file); 800 if (fd >= 0) 801 fops->close(fd); 802 if (po) 803 tee_pobj_release(po); 804 if (o) 805 free(o); 806 807 exit: 808 free(file); 809 file = NULL; 810 free(tmpfile); 811 tmpfile = NULL; 812 813 return res; 814 } 815 816 TEE_Result syscall_storage_obj_del(unsigned long obj) 817 { 818 TEE_Result res; 819 struct tee_ta_session *sess; 820 struct tee_obj *o; 821 int err; 822 char *file; 823 char *dir; 824 struct user_ta_ctx *utc; 825 const struct tee_file_operations *fops; 826 827 res = tee_ta_get_current_session(&sess); 828 if (res != TEE_SUCCESS) 829 return res; 830 utc = to_user_ta_ctx(sess->ctx); 831 832 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 833 if (res != TEE_SUCCESS) 834 return res; 835 836 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 837 return TEE_ERROR_ACCESS_CONFLICT; 838 839 if (o->pobj == NULL || o->pobj->obj_id == NULL) 840 return TEE_ERROR_BAD_STATE; 841 842 file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 843 o->pobj->obj_id_len, false); 844 if (file == NULL) 845 return TEE_ERROR_OUT_OF_MEMORY; 846 847 fops = o->pobj->fops; 848 tee_obj_close(utc, o); 849 850 err = fops->access(file, TEE_FS_F_OK); 851 if (err) 852 /* file not found */ 853 return TEE_ERROR_STORAGE_NOT_AVAILABLE; 854 855 err = fops->unlink(file); 856 free(file); 857 if (err) 858 /* error codes needs better granularity */ 859 return TEE_ERROR_GENERIC; 860 861 /* try and remove dir */ 862 dir = tee_svc_storage_create_dirname(sess); 863 if (dir == NULL) 864 return TEE_ERROR_OUT_OF_MEMORY; 865 /* ignore result */ 866 fops->rmdir(dir); 867 free(dir); 868 869 return TEE_SUCCESS; 870 } 871 872 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 873 size_t object_id_len) 874 { 875 TEE_Result res; 876 struct tee_ta_session *sess; 877 struct tee_obj *o; 878 struct tee_pobj *po = NULL; 879 char *new_file = NULL; 880 char *old_file = NULL; 881 int err = -1; 882 struct user_ta_ctx *utc; 883 const struct tee_file_operations *fops; 884 885 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 886 return TEE_ERROR_BAD_PARAMETERS; 887 888 res = tee_ta_get_current_session(&sess); 889 if (res != TEE_SUCCESS) 890 return res; 891 utc = to_user_ta_ctx(sess->ctx); 892 893 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 894 if (res != TEE_SUCCESS) 895 return res; 896 897 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 898 res = TEE_ERROR_BAD_STATE; 899 goto exit; 900 } 901 902 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 903 res = TEE_ERROR_BAD_STATE; 904 goto exit; 905 } 906 907 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 908 res = TEE_ERROR_BAD_STATE; 909 goto exit; 910 } 911 912 res = tee_mmu_check_access_rights(utc, 913 TEE_MEMORY_ACCESS_READ | 914 TEE_MEMORY_ACCESS_ANY_OWNER, 915 (tee_uaddr_t) object_id, object_id_len); 916 if (res != TEE_SUCCESS) 917 goto exit; 918 919 res = tee_obj_verify(sess, o); 920 if (res != TEE_SUCCESS) 921 goto exit; 922 923 /* get new ds name */ 924 new_file = tee_svc_storage_create_filename(sess, object_id, 925 object_id_len, false); 926 if (new_file == NULL) { 927 res = TEE_ERROR_OUT_OF_MEMORY; 928 goto exit; 929 } 930 931 old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 932 o->pobj->obj_id_len, false); 933 if (old_file == NULL) { 934 res = TEE_ERROR_OUT_OF_MEMORY; 935 goto exit; 936 } 937 938 /* reserve dest name */ 939 fops = o->pobj->fops; 940 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 941 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 942 fops, &po); 943 if (res != TEE_SUCCESS) 944 goto exit; 945 946 err = fops->access(new_file, TEE_FS_F_OK); 947 if (err == 0) { 948 /* file exists */ 949 res = TEE_ERROR_ACCESS_CONFLICT; 950 goto exit; 951 } 952 953 /* move */ 954 err = fops->rename(old_file, new_file); 955 if (err) { 956 /* error codes needs better granularity */ 957 res = TEE_ERROR_GENERIC; 958 goto exit; 959 } 960 961 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 962 963 exit: 964 tee_pobj_release(po); 965 966 free(new_file); 967 free(old_file); 968 969 return res; 970 } 971 972 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 973 { 974 struct tee_storage_enum *e; 975 struct tee_ta_session *sess; 976 TEE_Result res; 977 struct user_ta_ctx *utc; 978 979 if (obj_enum == NULL) 980 return TEE_ERROR_BAD_PARAMETERS; 981 982 res = tee_ta_get_current_session(&sess); 983 if (res != TEE_SUCCESS) 984 return res; 985 utc = to_user_ta_ctx(sess->ctx); 986 987 e = malloc(sizeof(struct tee_storage_enum)); 988 if (e == NULL) 989 return TEE_ERROR_OUT_OF_MEMORY; 990 991 e->dir = NULL; 992 e->fops = NULL; 993 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 994 995 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 996 } 997 998 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 999 { 1000 struct tee_storage_enum *e; 1001 TEE_Result res; 1002 struct tee_ta_session *sess; 1003 struct user_ta_ctx *utc; 1004 1005 res = tee_ta_get_current_session(&sess); 1006 if (res != TEE_SUCCESS) 1007 return res; 1008 utc = to_user_ta_ctx(sess->ctx); 1009 1010 res = tee_svc_storage_get_enum(utc, 1011 tee_svc_uref_to_vaddr(obj_enum), &e); 1012 if (res != TEE_SUCCESS) 1013 return res; 1014 1015 return tee_svc_close_enum(utc, e); 1016 } 1017 1018 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 1019 { 1020 struct tee_storage_enum *e; 1021 TEE_Result res; 1022 struct tee_ta_session *sess; 1023 1024 res = tee_ta_get_current_session(&sess); 1025 if (res != TEE_SUCCESS) 1026 return res; 1027 1028 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 1029 tee_svc_uref_to_vaddr(obj_enum), &e); 1030 if (res != TEE_SUCCESS) 1031 return res; 1032 1033 res = e->fops->closedir(e->dir); 1034 e->dir = NULL; 1035 if (res != 0) 1036 return TEE_ERROR_GENERIC; 1037 1038 return TEE_SUCCESS; 1039 } 1040 1041 static TEE_Result tee_svc_storage_set_enum(char *d_name, 1042 const struct tee_file_operations *fops, 1043 struct tee_obj *o) 1044 { 1045 TEE_Result res; 1046 uint32_t blen; 1047 uint32_t hslen; 1048 1049 o->info.handleFlags = 1050 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 1051 o->info.objectUsage = TEE_USAGE_DEFAULT; 1052 1053 hslen = strlen(d_name); 1054 blen = TEE_HS2B_BBUF_SIZE(hslen); 1055 o->pobj->obj_id = malloc(blen); 1056 if (!o->pobj->obj_id) { 1057 res = TEE_ERROR_OUT_OF_MEMORY; 1058 goto exit; 1059 } 1060 tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen); 1061 o->pobj->obj_id_len = blen; 1062 o->pobj->fops = fops; 1063 1064 res = TEE_SUCCESS; 1065 1066 exit: 1067 return res; 1068 1069 } 1070 1071 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 1072 unsigned long storage_id) 1073 { 1074 struct tee_storage_enum *e; 1075 char *dir; 1076 TEE_Result res; 1077 struct tee_ta_session *sess; 1078 struct tee_fs_dirent *d = NULL; 1079 struct tee_obj *o = NULL; 1080 const struct tee_file_operations *fops = file_ops(storage_id); 1081 1082 res = tee_ta_get_current_session(&sess); 1083 if (res != TEE_SUCCESS) 1084 return res; 1085 1086 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 1087 tee_svc_uref_to_vaddr(obj_enum), &e); 1088 if (res != TEE_SUCCESS) 1089 return res; 1090 1091 if (!fops) 1092 return TEE_ERROR_ITEM_NOT_FOUND; 1093 1094 dir = tee_svc_storage_create_dirname(sess); 1095 if (dir == NULL) 1096 return TEE_ERROR_OUT_OF_MEMORY; 1097 1098 e->fops = fops; 1099 e->dir = fops->opendir(dir); 1100 free(dir); 1101 if (e->dir == NULL) 1102 /* error codes needs better granularity */ 1103 return TEE_ERROR_ITEM_NOT_FOUND; 1104 1105 /* verify object */ 1106 o = tee_obj_alloc(); 1107 if (o == NULL) { 1108 res = TEE_ERROR_OUT_OF_MEMORY; 1109 goto exit; 1110 } 1111 1112 o->pobj = calloc(1, sizeof(struct tee_pobj)); 1113 if (!o->pobj) { 1114 res = TEE_ERROR_OUT_OF_MEMORY; 1115 goto exit; 1116 } 1117 1118 /* object enumeration loop */ 1119 do { 1120 d = fops->readdir(e->dir); 1121 if (d) { 1122 /* allocate obj_id and set object */ 1123 res = tee_svc_storage_set_enum(d->d_name, fops, o); 1124 if (res != TEE_SUCCESS) 1125 goto exit; 1126 res = tee_obj_verify(sess, o); 1127 if (res != TEE_SUCCESS) 1128 goto exit; 1129 /* free obj_id for each iteration */ 1130 free(o->pobj->obj_id); 1131 /* force obj_id to skip freeing at exit statement */ 1132 o->pobj->obj_id = NULL; 1133 } 1134 } while (d); 1135 1136 /* re-start */ 1137 res = fops->closedir(e->dir); 1138 e->dir = NULL; 1139 if (res != 0) { 1140 res = TEE_ERROR_GENERIC; 1141 goto exit; 1142 } 1143 1144 dir = tee_svc_storage_create_dirname(sess); 1145 if (dir == NULL) { 1146 res = TEE_ERROR_OUT_OF_MEMORY; 1147 goto exit; 1148 } 1149 1150 e->dir = fops->opendir(dir); 1151 free(dir); 1152 1153 exit: 1154 if (o) { 1155 if (o->pobj) 1156 free(o->pobj->obj_id); 1157 free(o->pobj); 1158 tee_obj_free(o); 1159 } 1160 1161 return res; 1162 } 1163 1164 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 1165 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 1166 { 1167 struct tee_storage_enum *e; 1168 struct tee_fs_dirent *d; 1169 TEE_Result res = TEE_SUCCESS; 1170 struct tee_ta_session *sess; 1171 struct tee_obj *o = NULL; 1172 uint64_t l; 1173 struct user_ta_ctx *utc; 1174 1175 res = tee_ta_get_current_session(&sess); 1176 if (res != TEE_SUCCESS) 1177 goto exit; 1178 utc = to_user_ta_ctx(sess->ctx); 1179 1180 res = tee_svc_storage_get_enum(utc, 1181 tee_svc_uref_to_vaddr(obj_enum), &e); 1182 if (res != TEE_SUCCESS) 1183 goto exit; 1184 1185 /* check rights of the provided buffers */ 1186 res = tee_mmu_check_access_rights(utc, 1187 TEE_MEMORY_ACCESS_WRITE | 1188 TEE_MEMORY_ACCESS_ANY_OWNER, 1189 (tee_uaddr_t) info, 1190 sizeof(TEE_ObjectInfo)); 1191 if (res != TEE_SUCCESS) 1192 goto exit; 1193 1194 res = tee_mmu_check_access_rights(utc, 1195 TEE_MEMORY_ACCESS_WRITE | 1196 TEE_MEMORY_ACCESS_ANY_OWNER, 1197 (tee_uaddr_t) obj_id, 1198 TEE_OBJECT_ID_MAX_LEN); 1199 if (res != TEE_SUCCESS) 1200 goto exit; 1201 1202 if (!e->fops) { 1203 res = TEE_ERROR_ITEM_NOT_FOUND; 1204 goto exit; 1205 } 1206 1207 d = e->fops->readdir(e->dir); 1208 if (d == NULL) { 1209 res = TEE_ERROR_ITEM_NOT_FOUND; 1210 goto exit; 1211 } 1212 1213 o = tee_obj_alloc(); 1214 if (o == NULL) { 1215 res = TEE_ERROR_OUT_OF_MEMORY; 1216 goto exit; 1217 } 1218 1219 o->pobj = calloc(1, sizeof(struct tee_pobj)); 1220 if (!o->pobj) { 1221 res = TEE_ERROR_OUT_OF_MEMORY; 1222 goto exit; 1223 } 1224 1225 res = tee_svc_storage_set_enum(d->d_name, e->fops, o); 1226 if (res != TEE_SUCCESS) 1227 goto exit; 1228 1229 res = tee_obj_verify(sess, o); 1230 if (res != TEE_SUCCESS) 1231 goto exit; 1232 1233 res = tee_svc_storage_read_head(sess, o); 1234 if (res != TEE_SUCCESS) 1235 goto exit; 1236 1237 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 1238 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 1239 1240 l = o->pobj->obj_id_len; 1241 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 1242 1243 exit: 1244 if (o) { 1245 if (o->pobj) 1246 free(o->pobj->obj_id); 1247 free(o->pobj); 1248 tee_obj_free(o); 1249 } 1250 1251 return res; 1252 } 1253 1254 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 1255 uint64_t *count) 1256 { 1257 TEE_Result res; 1258 TEE_Result errno; 1259 struct tee_ta_session *sess; 1260 struct tee_obj *o; 1261 int n_count; 1262 uint64_t u_count; 1263 struct user_ta_ctx *utc; 1264 1265 res = tee_ta_get_current_session(&sess); 1266 if (res != TEE_SUCCESS) 1267 goto exit; 1268 utc = to_user_ta_ctx(sess->ctx); 1269 1270 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1271 if (res != TEE_SUCCESS) 1272 goto exit; 1273 1274 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1275 res = TEE_ERROR_BAD_STATE; 1276 goto exit; 1277 } 1278 1279 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 1280 res = TEE_ERROR_ACCESS_CONFLICT; 1281 goto exit; 1282 } 1283 1284 /* check rights of the provided buffer */ 1285 res = tee_mmu_check_access_rights(utc, 1286 TEE_MEMORY_ACCESS_WRITE | 1287 TEE_MEMORY_ACCESS_ANY_OWNER, 1288 (tee_uaddr_t) data, len); 1289 if (res != TEE_SUCCESS) 1290 goto exit; 1291 1292 n_count = o->pobj->fops->read(&errno, o->fd, data, len); 1293 if (n_count < 0) { 1294 res = errno; 1295 EMSG("Error code=%x\n", (uint32_t)res); 1296 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1297 EMSG("Object corrupt\n"); 1298 tee_svc_storage_remove_corrupt_obj(sess, o); 1299 } 1300 goto exit; 1301 } 1302 u_count = (uint64_t)((n_count < 0) ? 0 : n_count); 1303 1304 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 1305 1306 o->info.dataPosition += u_count; 1307 1308 exit: 1309 return res; 1310 } 1311 1312 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 1313 { 1314 TEE_Result res; 1315 TEE_Result errno; 1316 struct tee_ta_session *sess; 1317 struct tee_obj *o; 1318 int err; 1319 struct user_ta_ctx *utc; 1320 1321 res = tee_ta_get_current_session(&sess); 1322 if (res != TEE_SUCCESS) 1323 goto exit; 1324 utc = to_user_ta_ctx(sess->ctx); 1325 1326 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1327 if (res != TEE_SUCCESS) 1328 goto exit; 1329 1330 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1331 res = TEE_ERROR_BAD_STATE; 1332 goto exit; 1333 } 1334 1335 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1336 res = TEE_ERROR_ACCESS_CONFLICT; 1337 goto exit; 1338 } 1339 1340 /* check rights of the provided buffer */ 1341 res = tee_mmu_check_access_rights(utc, 1342 TEE_MEMORY_ACCESS_READ | 1343 TEE_MEMORY_ACCESS_ANY_OWNER, 1344 (tee_uaddr_t) data, len); 1345 if (res != TEE_SUCCESS) 1346 goto exit; 1347 1348 err = o->pobj->fops->write(&errno, o->fd, data, len); 1349 if (err < 0) 1350 res = errno; 1351 if (err != (int)len) 1352 goto exit; 1353 1354 o->info.dataPosition += len; 1355 if (o->info.dataPosition > o->info.dataSize) 1356 o->info.dataSize = o->info.dataPosition; 1357 1358 exit: 1359 return res; 1360 } 1361 1362 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 1363 { 1364 TEE_Result res; 1365 TEE_Result errno; 1366 struct tee_ta_session *sess; 1367 struct tee_obj *o; 1368 int err; 1369 tee_fs_off_t off; 1370 size_t attr_size; 1371 1372 res = tee_ta_get_current_session(&sess); 1373 if (res != TEE_SUCCESS) 1374 goto exit; 1375 1376 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1377 tee_svc_uref_to_vaddr(obj), &o); 1378 if (res != TEE_SUCCESS) 1379 goto exit; 1380 1381 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1382 res = TEE_ERROR_BAD_STATE; 1383 goto exit; 1384 } 1385 1386 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1387 res = TEE_ERROR_ACCESS_CONFLICT; 1388 goto exit; 1389 } 1390 1391 res = tee_obj_verify(sess, o); 1392 if (res != TEE_SUCCESS) 1393 goto exit; 1394 1395 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1396 if (res != TEE_SUCCESS) 1397 goto exit; 1398 1399 off = sizeof(struct tee_svc_storage_head) + attr_size; 1400 err = o->pobj->fops->ftruncate(&errno, o->fd, len + off); 1401 if (err < 0) { 1402 res = errno; 1403 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1404 EMSG("Object corrupt\n"); 1405 res = tee_svc_storage_remove_corrupt_obj(sess, o); 1406 if (res != TEE_SUCCESS) 1407 goto exit; 1408 res = TEE_ERROR_CORRUPT_OBJECT; 1409 goto exit; 1410 } else 1411 res = TEE_ERROR_GENERIC; 1412 } 1413 1414 exit: 1415 return res; 1416 } 1417 1418 TEE_Result syscall_storage_obj_seek(unsigned long obj, long offset, 1419 unsigned long whence) 1420 { 1421 TEE_Result res; 1422 TEE_Result errno; 1423 struct tee_ta_session *sess; 1424 struct tee_obj *o; 1425 int fw; 1426 tee_fs_off_t off; 1427 tee_fs_off_t e_off = 0; 1428 size_t attr_size; 1429 1430 res = tee_ta_get_current_session(&sess); 1431 if (res != TEE_SUCCESS) 1432 goto exit; 1433 1434 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1435 tee_svc_uref_to_vaddr(obj), &o); 1436 if (res != TEE_SUCCESS) 1437 goto exit; 1438 1439 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1440 res = TEE_ERROR_BAD_STATE; 1441 goto exit; 1442 } 1443 1444 res = tee_obj_verify(sess, o); 1445 if (res != TEE_SUCCESS) 1446 goto exit; 1447 1448 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 1449 if (res != TEE_SUCCESS) 1450 goto exit; 1451 1452 fw = tee_svc_storage_conv_whence(whence); 1453 1454 if (whence == TEE_DATA_SEEK_SET) 1455 e_off = sizeof(struct tee_svc_storage_head) + attr_size; 1456 1457 off = o->pobj->fops->lseek(&errno, o->fd, e_off + offset, fw); 1458 if (off > -1 && off >= e_off) { 1459 res = TEE_SUCCESS; 1460 o->info.dataPosition = off - 1461 (sizeof(struct tee_svc_storage_head) + attr_size); 1462 } else { 1463 res = TEE_ERROR_GENERIC; 1464 goto exit; 1465 } 1466 1467 exit: 1468 return res; 1469 } 1470 1471 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1472 { 1473 struct tee_storage_enum_head *eh = &utc->storage_enums; 1474 1475 /* disregard return value */ 1476 while (!TAILQ_EMPTY(eh)) 1477 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1478 } 1479