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