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