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 user_ta_ctx *utc, 58 uint32_t enum_id, 59 struct tee_storage_enum **e_out) 60 { 61 struct tee_storage_enum *e; 62 63 TAILQ_FOREACH(e, &utc->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 user_ta_ctx *utc, 73 struct tee_storage_enum *e) 74 { 75 int ret; 76 77 if (e == NULL || utc == NULL) 78 return TEE_ERROR_BAD_PARAMETERS; 79 80 TAILQ_REMOVE(&utc->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(to_user_ta_ctx(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 struct user_ta_ctx *utc; 416 417 if (storage_id != TEE_STORAGE_PRIVATE) { 418 res = TEE_ERROR_ITEM_NOT_FOUND; 419 goto exit; 420 } 421 422 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 423 res = TEE_ERROR_BAD_PARAMETERS; 424 goto exit; 425 } 426 427 res = tee_ta_get_current_session(&sess); 428 if (res != TEE_SUCCESS) 429 goto err; 430 utc = to_user_ta_ctx(sess->ctx); 431 432 res = tee_mmu_check_access_rights(utc, 433 TEE_MEMORY_ACCESS_READ | 434 TEE_MEMORY_ACCESS_ANY_OWNER, 435 (tee_uaddr_t) object_id, 436 object_id_len); 437 if (res != TEE_SUCCESS) 438 goto err; 439 440 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 441 object_id_len, flags, &po); 442 if (res != TEE_SUCCESS) 443 goto err; 444 445 fs_flags = tee_svc_storage_conv_oflags(flags); 446 447 o = calloc(1, sizeof(*o)); 448 if (o == NULL) { 449 res = TEE_ERROR_OUT_OF_MEMORY; 450 goto err; 451 } 452 453 o->info.handleFlags = 454 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 455 o->info.objectUsage = TEE_USAGE_DEFAULT; 456 o->flags = flags; 457 o->pobj = po; 458 459 res = tee_svc_storage_read_head(sess, o); 460 if (res != TEE_SUCCESS) { 461 tee_obj_add(utc, o); 462 if (res == TEE_ERROR_CORRUPT_OBJECT) { 463 EMSG("Object corrupt\n"); 464 res = tee_svc_storage_remove_corrupt_obj(sess, o); 465 if (res != TEE_SUCCESS) 466 goto exit; 467 res = TEE_ERROR_CORRUPT_OBJECT; 468 goto exit; 469 } 470 goto oclose; 471 } 472 473 file = tee_svc_storage_create_filename(sess, object_id, 474 object_id_len, false); 475 if (file == NULL) { 476 res = TEE_ERROR_OUT_OF_MEMORY; 477 goto err; 478 } 479 480 err = tee_file_ops.access(file, TEE_FS_F_OK); 481 if (err) { 482 /* file not found */ 483 res = TEE_ERROR_STORAGE_NOT_AVAILABLE; 484 goto err; 485 } 486 487 fd = tee_file_ops.open(&res, file, fs_flags); 488 if (fd < 0) { 489 goto err; 490 } 491 o->fd = fd; 492 493 tee_obj_add(utc, o); 494 495 res = tee_svc_copy_kaddr_to_uref(sess, obj, o); 496 if (res != TEE_SUCCESS) 497 goto oclose; 498 499 e_off = sizeof(struct tee_svc_storage_head) + o->data_size; 500 off = tee_file_ops.lseek(&res, fd, e_off, TEE_FS_SEEK_SET); 501 if (off != e_off) { 502 res = TEE_ERROR_NO_DATA; 503 goto oclose; 504 } 505 506 goto exit; 507 508 oclose: 509 tee_obj_close(utc, o); 510 511 err: 512 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 513 res = TEE_ERROR_CORRUPT_OBJECT; 514 if (res == TEE_ERROR_CORRUPT_OBJECT) 515 tee_file_ops.unlink(file); 516 if (fd >= 0) 517 tee_file_ops.close(fd); 518 if (po) 519 tee_pobj_release(po); 520 521 exit: 522 free(file); 523 file = NULL; 524 return res; 525 } 526 527 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 528 size_t object_id_len, unsigned long flags, 529 unsigned long attr, void *data, size_t len, 530 uint32_t *obj) 531 { 532 TEE_Result res; 533 struct tee_ta_session *sess; 534 struct tee_obj *o = NULL; 535 struct tee_obj *attr_o = NULL; 536 char *file = NULL; 537 int fd = -1; 538 int fs_flags; 539 tee_fs_off_t off; 540 tee_fs_off_t e_off; 541 struct tee_pobj *po = NULL; 542 char *tmpfile = NULL; 543 int err = -1; 544 struct user_ta_ctx *utc; 545 546 if (storage_id != TEE_STORAGE_PRIVATE) 547 return TEE_ERROR_ITEM_NOT_FOUND; 548 549 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 550 return TEE_ERROR_BAD_PARAMETERS; 551 552 res = tee_ta_get_current_session(&sess); 553 if (res != TEE_SUCCESS) 554 return res; 555 utc = to_user_ta_ctx(sess->ctx); 556 557 res = tee_mmu_check_access_rights(utc, 558 TEE_MEMORY_ACCESS_READ | 559 TEE_MEMORY_ACCESS_ANY_OWNER, 560 (tee_uaddr_t) object_id, 561 object_id_len); 562 if (res != TEE_SUCCESS) 563 goto err; 564 565 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 566 object_id_len, flags, &po); 567 if (res != TEE_SUCCESS) 568 goto err; 569 570 /* check rights of the provided buffer */ 571 if (data && len) { 572 res = tee_mmu_check_access_rights(utc, 573 TEE_MEMORY_ACCESS_READ | 574 TEE_MEMORY_ACCESS_ANY_OWNER, 575 (tee_uaddr_t) data, len); 576 577 if (res != TEE_SUCCESS) 578 goto err; 579 } 580 581 o = calloc(1, sizeof(*o)); 582 if (o == NULL) { 583 res = TEE_ERROR_OUT_OF_MEMORY; 584 goto err; 585 } 586 587 o->info.handleFlags = 588 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 589 o->flags = flags; 590 o->pobj = po; 591 592 if (attr != TEE_HANDLE_NULL) { 593 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 594 &attr_o); 595 if (res != TEE_SUCCESS) 596 goto err; 597 } 598 599 res = tee_svc_storage_init_file(sess, o, attr_o, data, len); 600 if (res != TEE_SUCCESS) 601 goto err; 602 603 /* create persistent object filename */ 604 file = tee_svc_storage_create_filename(sess, object_id, 605 object_id_len, false); 606 if (file == NULL) { 607 res = TEE_ERROR_OUT_OF_MEMORY; 608 goto err; 609 } 610 611 err = tee_file_ops.access(file, TEE_FS_F_OK); 612 if (!err) { 613 /* file exists */ 614 if (!(flags & TEE_DATA_FLAG_OVERWRITE)) { 615 res = TEE_ERROR_ACCESS_CONFLICT; 616 goto err; 617 } 618 } 619 620 /* create temporary persistent object filename */ 621 tmpfile = tee_svc_storage_create_filename(sess, object_id, 622 object_id_len, 623 true); 624 if (tmpfile == NULL) { 625 res = TEE_ERROR_OUT_OF_MEMORY; 626 goto err; 627 } 628 629 /* rename temporary persistent object filename */ 630 err = tee_file_ops.rename(tmpfile, file); 631 if (err) { 632 /* error codes needs better granularity */ 633 res = TEE_ERROR_GENERIC; 634 goto rmfile; 635 } 636 637 fs_flags = tee_svc_storage_conv_oflags(flags); 638 639 fd = tee_file_ops.open(&res, file, fs_flags); 640 if (fd < 0) { 641 goto err; 642 } 643 o->fd = fd; 644 645 tee_obj_add(utc, o); 646 647 res = tee_svc_copy_kaddr_to_uref(sess, obj, o); 648 if (res != TEE_SUCCESS) 649 goto oclose; 650 651 e_off = sizeof(struct tee_svc_storage_head) + o->data_size; 652 off = tee_file_ops.lseek(&res, fd, e_off, TEE_FS_SEEK_SET); 653 if (off != e_off) { 654 res = TEE_ERROR_NO_DATA; 655 goto oclose; 656 } 657 658 goto exit; 659 660 oclose: 661 tee_obj_close(utc, o); 662 goto exit; 663 664 rmfile: 665 tee_file_ops.unlink(tmpfile); 666 667 err: 668 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 669 res = TEE_ERROR_CORRUPT_OBJECT; 670 if (res == TEE_ERROR_CORRUPT_OBJECT) 671 tee_file_ops.unlink(file); 672 if (fd >= 0) 673 tee_file_ops.close(fd); 674 if (po) 675 tee_pobj_release(po); 676 if (o) 677 free(o); 678 679 exit: 680 free(file); 681 file = NULL; 682 free(tmpfile); 683 tmpfile = NULL; 684 685 return res; 686 } 687 688 TEE_Result syscall_storage_obj_del(unsigned long obj) 689 { 690 TEE_Result res; 691 struct tee_ta_session *sess; 692 struct tee_obj *o; 693 int err; 694 char *file; 695 char *dir; 696 struct user_ta_ctx *utc; 697 698 res = tee_ta_get_current_session(&sess); 699 if (res != TEE_SUCCESS) 700 return res; 701 utc = to_user_ta_ctx(sess->ctx); 702 703 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 704 if (res != TEE_SUCCESS) 705 return res; 706 707 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 708 return TEE_ERROR_ACCESS_CONFLICT; 709 710 if (o->pobj == NULL || o->pobj->obj_id == NULL) 711 return TEE_ERROR_BAD_STATE; 712 713 file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 714 o->pobj->obj_id_len, false); 715 if (file == NULL) 716 return TEE_ERROR_OUT_OF_MEMORY; 717 718 tee_obj_close(utc, o); 719 720 err = tee_file_ops.access(file, TEE_FS_F_OK); 721 if (err) 722 /* file not found */ 723 return TEE_ERROR_STORAGE_NOT_AVAILABLE; 724 725 err = tee_file_ops.unlink(file); 726 free(file); 727 if (err) 728 /* error codes needs better granularity */ 729 return TEE_ERROR_GENERIC; 730 731 /* try and remove dir */ 732 dir = tee_svc_storage_create_dirname(sess); 733 if (dir == NULL) 734 return TEE_ERROR_OUT_OF_MEMORY; 735 /* ignore result */ 736 tee_file_ops.rmdir(dir); 737 free(dir); 738 739 return TEE_SUCCESS; 740 } 741 742 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 743 size_t object_id_len) 744 { 745 TEE_Result res; 746 struct tee_ta_session *sess; 747 struct tee_obj *o; 748 struct tee_pobj *po = NULL; 749 char *new_file = NULL; 750 char *old_file = NULL; 751 int err = -1; 752 struct user_ta_ctx *utc; 753 754 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 755 return TEE_ERROR_BAD_PARAMETERS; 756 757 res = tee_ta_get_current_session(&sess); 758 if (res != TEE_SUCCESS) 759 return res; 760 utc = to_user_ta_ctx(sess->ctx); 761 762 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 763 if (res != TEE_SUCCESS) 764 return res; 765 766 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 767 res = TEE_ERROR_BAD_STATE; 768 goto exit; 769 } 770 771 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 772 res = TEE_ERROR_BAD_STATE; 773 goto exit; 774 } 775 776 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 777 res = TEE_ERROR_BAD_STATE; 778 goto exit; 779 } 780 781 res = tee_mmu_check_access_rights(utc, 782 TEE_MEMORY_ACCESS_READ | 783 TEE_MEMORY_ACCESS_ANY_OWNER, 784 (tee_uaddr_t) object_id, object_id_len); 785 if (res != TEE_SUCCESS) 786 goto exit; 787 788 res = tee_obj_verify(sess, o); 789 if (res != TEE_SUCCESS) 790 goto exit; 791 792 /* get new ds name */ 793 new_file = tee_svc_storage_create_filename(sess, object_id, 794 object_id_len, false); 795 if (new_file == NULL) { 796 res = TEE_ERROR_OUT_OF_MEMORY; 797 goto exit; 798 } 799 800 old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, 801 o->pobj->obj_id_len, false); 802 if (old_file == NULL) { 803 res = TEE_ERROR_OUT_OF_MEMORY; 804 goto exit; 805 } 806 807 /* reserve dest name */ 808 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 809 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po); 810 if (res != TEE_SUCCESS) 811 goto exit; 812 813 err = tee_file_ops.access(new_file, TEE_FS_F_OK); 814 if (err == 0) { 815 /* file exists */ 816 res = TEE_ERROR_ACCESS_CONFLICT; 817 goto exit; 818 } 819 820 /* move */ 821 err = tee_file_ops.rename(old_file, new_file); 822 if (err) { 823 /* error codes needs better granularity */ 824 res = TEE_ERROR_GENERIC; 825 goto exit; 826 } 827 828 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 829 830 exit: 831 tee_pobj_release(po); 832 833 free(new_file); 834 free(old_file); 835 836 return res; 837 } 838 839 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 840 { 841 struct tee_storage_enum *e; 842 struct tee_ta_session *sess; 843 TEE_Result res; 844 struct user_ta_ctx *utc; 845 846 if (obj_enum == NULL) 847 return TEE_ERROR_BAD_PARAMETERS; 848 849 res = tee_ta_get_current_session(&sess); 850 if (res != TEE_SUCCESS) 851 return res; 852 utc = to_user_ta_ctx(sess->ctx); 853 854 e = malloc(sizeof(struct tee_storage_enum)); 855 856 if (e == NULL) 857 return TEE_ERROR_OUT_OF_MEMORY; 858 859 e->dir = NULL; 860 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 861 862 return tee_svc_copy_kaddr_to_uref(sess, obj_enum, e); 863 } 864 865 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 866 { 867 struct tee_storage_enum *e; 868 TEE_Result res; 869 struct tee_ta_session *sess; 870 struct user_ta_ctx *utc; 871 872 res = tee_ta_get_current_session(&sess); 873 if (res != TEE_SUCCESS) 874 return res; 875 utc = to_user_ta_ctx(sess->ctx); 876 877 res = tee_svc_storage_get_enum(utc, 878 tee_svc_uref_to_vaddr(obj_enum), &e); 879 if (res != TEE_SUCCESS) 880 return res; 881 882 return tee_svc_close_enum(utc, e); 883 } 884 885 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 886 { 887 struct tee_storage_enum *e; 888 TEE_Result res; 889 struct tee_ta_session *sess; 890 891 res = tee_ta_get_current_session(&sess); 892 if (res != TEE_SUCCESS) 893 return res; 894 895 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 896 tee_svc_uref_to_vaddr(obj_enum), &e); 897 if (res != TEE_SUCCESS) 898 return res; 899 900 res = tee_file_ops.closedir(e->dir); 901 e->dir = NULL; 902 if (res != 0) 903 return TEE_ERROR_GENERIC; 904 905 return TEE_SUCCESS; 906 } 907 908 static TEE_Result tee_svc_storage_set_enum(char *d_name, struct tee_obj *o) 909 { 910 TEE_Result res; 911 uint32_t blen; 912 uint32_t hslen; 913 914 o->info.handleFlags = 915 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 916 o->info.objectUsage = TEE_USAGE_DEFAULT; 917 918 hslen = strlen(d_name); 919 blen = TEE_HS2B_BBUF_SIZE(hslen); 920 o->pobj->obj_id = malloc(blen); 921 if (!o->pobj->obj_id) { 922 res = TEE_ERROR_OUT_OF_MEMORY; 923 goto exit; 924 } 925 tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen); 926 o->pobj->obj_id_len = blen; 927 928 res = TEE_SUCCESS; 929 930 exit: 931 return res; 932 933 } 934 935 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 936 unsigned long storage_id) 937 { 938 struct tee_storage_enum *e; 939 char *dir; 940 TEE_Result res; 941 struct tee_ta_session *sess; 942 struct tee_fs_dirent *d = NULL; 943 struct tee_obj *o = NULL; 944 945 res = tee_ta_get_current_session(&sess); 946 if (res != TEE_SUCCESS) 947 return res; 948 949 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 950 tee_svc_uref_to_vaddr(obj_enum), &e); 951 if (res != TEE_SUCCESS) 952 return res; 953 954 if (storage_id != TEE_STORAGE_PRIVATE) 955 return TEE_ERROR_ITEM_NOT_FOUND; 956 957 dir = tee_svc_storage_create_dirname(sess); 958 if (dir == NULL) 959 return TEE_ERROR_OUT_OF_MEMORY; 960 961 e->dir = tee_file_ops.opendir(dir); 962 free(dir); 963 964 if (e->dir == NULL) 965 /* error codes needs better granularity */ 966 return TEE_ERROR_ITEM_NOT_FOUND; 967 968 /* verify object */ 969 o = calloc(1, sizeof(struct tee_obj)); 970 if (o == NULL) { 971 res = TEE_ERROR_OUT_OF_MEMORY; 972 goto exit; 973 } 974 975 o->pobj = calloc(1, sizeof(struct tee_pobj)); 976 if (!o->pobj) { 977 res = TEE_ERROR_OUT_OF_MEMORY; 978 goto exit; 979 } 980 981 /* object enumeration loop */ 982 do { 983 d = tee_file_ops.readdir(e->dir); 984 if (d) { 985 /* allocate obj_id and set object */ 986 res = tee_svc_storage_set_enum(d->d_name, o); 987 if (res != TEE_SUCCESS) 988 goto exit; 989 res = tee_obj_verify(sess, o); 990 if (res != TEE_SUCCESS) 991 goto exit; 992 /* free obj_id for each iteration */ 993 free(o->pobj->obj_id); 994 /* force obj_id to skip freeing at exit statement */ 995 o->pobj->obj_id = NULL; 996 } 997 } while (d); 998 999 /* re-start */ 1000 res = tee_file_ops.closedir(e->dir); 1001 e->dir = NULL; 1002 if (res != 0) { 1003 res = TEE_ERROR_GENERIC; 1004 goto exit; 1005 } 1006 1007 dir = tee_svc_storage_create_dirname(sess); 1008 if (dir == NULL) { 1009 res = TEE_ERROR_OUT_OF_MEMORY; 1010 goto exit; 1011 } 1012 1013 e->dir = tee_file_ops.opendir(dir); 1014 free(dir); 1015 1016 exit: 1017 if (o) { 1018 if (o->pobj) 1019 free(o->pobj->obj_id); 1020 free(o->pobj); 1021 free(o->data); 1022 } 1023 free(o); 1024 1025 return res; 1026 } 1027 1028 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 1029 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 1030 { 1031 struct tee_storage_enum *e; 1032 struct tee_fs_dirent *d; 1033 TEE_Result res = TEE_SUCCESS; 1034 struct tee_ta_session *sess; 1035 struct tee_obj *o = NULL; 1036 uint64_t l; 1037 struct user_ta_ctx *utc; 1038 1039 res = tee_ta_get_current_session(&sess); 1040 if (res != TEE_SUCCESS) 1041 goto exit; 1042 utc = to_user_ta_ctx(sess->ctx); 1043 1044 res = tee_svc_storage_get_enum(utc, 1045 tee_svc_uref_to_vaddr(obj_enum), &e); 1046 if (res != TEE_SUCCESS) 1047 goto exit; 1048 1049 /* check rights of the provided buffers */ 1050 res = tee_mmu_check_access_rights(utc, 1051 TEE_MEMORY_ACCESS_WRITE | 1052 TEE_MEMORY_ACCESS_ANY_OWNER, 1053 (tee_uaddr_t) info, 1054 sizeof(TEE_ObjectInfo)); 1055 if (res != TEE_SUCCESS) 1056 goto exit; 1057 1058 res = tee_mmu_check_access_rights(utc, 1059 TEE_MEMORY_ACCESS_WRITE | 1060 TEE_MEMORY_ACCESS_ANY_OWNER, 1061 (tee_uaddr_t) obj_id, 1062 TEE_OBJECT_ID_MAX_LEN); 1063 if (res != TEE_SUCCESS) 1064 goto exit; 1065 1066 d = tee_file_ops.readdir(e->dir); 1067 if (d == NULL) { 1068 res = TEE_ERROR_ITEM_NOT_FOUND; 1069 goto exit; 1070 } 1071 1072 o = calloc(1, sizeof(struct tee_obj)); 1073 if (o == NULL) { 1074 res = TEE_ERROR_OUT_OF_MEMORY; 1075 goto exit; 1076 } 1077 1078 o->pobj = calloc(1, sizeof(struct tee_pobj)); 1079 if (!o->pobj) { 1080 res = TEE_ERROR_OUT_OF_MEMORY; 1081 goto exit; 1082 } 1083 1084 res = tee_svc_storage_set_enum(d->d_name, o); 1085 if (res != TEE_SUCCESS) 1086 goto exit; 1087 1088 res = tee_obj_verify(sess, o); 1089 if (res != TEE_SUCCESS) 1090 goto exit; 1091 1092 res = tee_svc_storage_read_head(sess, o); 1093 if (res != TEE_SUCCESS) 1094 goto exit; 1095 1096 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 1097 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 1098 1099 l = o->pobj->obj_id_len; 1100 res = tee_svc_copy_to_user(sess, len, &l, sizeof(*len)); 1101 1102 exit: 1103 if (o) { 1104 if (o->pobj) 1105 free(o->pobj->obj_id); 1106 free(o->pobj); 1107 free(o->data); 1108 } 1109 free(o); 1110 1111 return res; 1112 } 1113 1114 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 1115 uint64_t *count) 1116 { 1117 TEE_Result res; 1118 struct tee_ta_session *sess; 1119 struct tee_obj *o; 1120 int n_count; 1121 uint64_t u_count; 1122 struct user_ta_ctx *utc; 1123 1124 res = tee_ta_get_current_session(&sess); 1125 if (res != TEE_SUCCESS) 1126 goto exit; 1127 utc = to_user_ta_ctx(sess->ctx); 1128 1129 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1130 if (res != TEE_SUCCESS) 1131 goto exit; 1132 1133 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1134 res = TEE_ERROR_BAD_STATE; 1135 goto exit; 1136 } 1137 1138 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 1139 res = TEE_ERROR_ACCESS_CONFLICT; 1140 goto exit; 1141 } 1142 1143 /* check rights of the provided buffer */ 1144 res = tee_mmu_check_access_rights(utc, 1145 TEE_MEMORY_ACCESS_WRITE | 1146 TEE_MEMORY_ACCESS_ANY_OWNER, 1147 (tee_uaddr_t) data, len); 1148 if (res != TEE_SUCCESS) 1149 goto exit; 1150 1151 n_count = tee_file_ops.read(&res, o->fd, data, len); 1152 if (n_count < 0) { 1153 EMSG("Error code=%x\n", (uint32_t)res); 1154 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1155 EMSG("Object corrupt\n"); 1156 tee_svc_storage_remove_corrupt_obj(sess, o); 1157 } 1158 goto exit; 1159 } 1160 u_count = (uint64_t)((n_count < 0) ? 0 : n_count); 1161 1162 res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(*count)); 1163 1164 o->info.dataPosition += u_count; 1165 1166 res = TEE_SUCCESS; 1167 1168 exit: 1169 return res; 1170 } 1171 1172 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 1173 { 1174 TEE_Result res; 1175 struct tee_ta_session *sess; 1176 struct tee_obj *o; 1177 int err; 1178 struct user_ta_ctx *utc; 1179 1180 res = tee_ta_get_current_session(&sess); 1181 if (res != TEE_SUCCESS) 1182 goto exit; 1183 utc = to_user_ta_ctx(sess->ctx); 1184 1185 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 1186 if (res != TEE_SUCCESS) 1187 goto exit; 1188 1189 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1190 res = TEE_ERROR_BAD_STATE; 1191 goto exit; 1192 } 1193 1194 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1195 res = TEE_ERROR_ACCESS_CONFLICT; 1196 goto exit; 1197 } 1198 1199 /* check rights of the provided buffer */ 1200 res = tee_mmu_check_access_rights(utc, 1201 TEE_MEMORY_ACCESS_READ | 1202 TEE_MEMORY_ACCESS_ANY_OWNER, 1203 (tee_uaddr_t) data, len); 1204 1205 err = tee_file_ops.write(&res, o->fd, data, len); 1206 1207 if (err != (int)len) 1208 goto exit; 1209 1210 o->info.dataPosition += len; 1211 if (o->info.dataPosition > o->info.dataSize) 1212 o->info.dataSize = o->info.dataPosition; 1213 1214 res = TEE_SUCCESS; 1215 exit: 1216 return res; 1217 } 1218 1219 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 1220 { 1221 TEE_Result res; 1222 struct tee_ta_session *sess; 1223 struct tee_obj *o; 1224 int err; 1225 tee_fs_off_t off; 1226 1227 res = tee_ta_get_current_session(&sess); 1228 if (res != TEE_SUCCESS) 1229 goto exit; 1230 1231 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1232 tee_svc_uref_to_vaddr(obj), &o); 1233 if (res != TEE_SUCCESS) 1234 goto exit; 1235 1236 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1237 res = TEE_ERROR_BAD_STATE; 1238 goto exit; 1239 } 1240 1241 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 1242 res = TEE_ERROR_ACCESS_CONFLICT; 1243 goto exit; 1244 } 1245 1246 res = tee_obj_verify(sess, o); 1247 if (res != TEE_SUCCESS) 1248 goto exit; 1249 1250 off = sizeof(struct tee_svc_storage_head) + o->data_size; 1251 err = tee_file_ops.ftruncate(&res, o->fd, len + off); 1252 if (err) { 1253 if (res == TEE_ERROR_CORRUPT_OBJECT) { 1254 EMSG("Object corrupt\n"); 1255 res = tee_svc_storage_remove_corrupt_obj(sess, o); 1256 if (res != TEE_SUCCESS) 1257 goto exit; 1258 res = TEE_ERROR_CORRUPT_OBJECT; 1259 goto exit; 1260 } else 1261 res = TEE_ERROR_GENERIC; 1262 } 1263 1264 exit: 1265 return res; 1266 } 1267 1268 TEE_Result syscall_storage_obj_seek(unsigned long obj, long offset, 1269 unsigned long whence) 1270 { 1271 TEE_Result res; 1272 struct tee_ta_session *sess; 1273 struct tee_obj *o; 1274 int fw; 1275 tee_fs_off_t off; 1276 tee_fs_off_t e_off = 0; 1277 1278 res = tee_ta_get_current_session(&sess); 1279 if (res != TEE_SUCCESS) 1280 goto exit; 1281 1282 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1283 tee_svc_uref_to_vaddr(obj), &o); 1284 if (res != TEE_SUCCESS) 1285 goto exit; 1286 1287 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 1288 res = TEE_ERROR_BAD_STATE; 1289 goto exit; 1290 } 1291 1292 res = tee_obj_verify(sess, o); 1293 if (res != TEE_SUCCESS) 1294 goto exit; 1295 1296 fw = tee_svc_storage_conv_whence(whence); 1297 1298 if (whence == TEE_DATA_SEEK_SET) 1299 e_off = sizeof(struct tee_svc_storage_head) + o->data_size; 1300 1301 off = tee_file_ops.lseek(&res, o->fd, e_off + offset, fw); 1302 if (off > -1 && off >= e_off) 1303 o->info.dataPosition = off - 1304 (sizeof(struct tee_svc_storage_head) + o->data_size); 1305 else { 1306 res = TEE_ERROR_GENERIC; 1307 goto exit; 1308 } 1309 1310 res = TEE_SUCCESS; 1311 1312 exit: 1313 return res; 1314 } 1315 1316 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1317 { 1318 struct tee_storage_enum_head *eh = &utc->storage_enums; 1319 1320 /* disregard return value */ 1321 while (!TAILQ_EMPTY(eh)) 1322 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1323 } 1324