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