1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <kernel/mutex.h> 29 #include <kernel/tee_misc.h> 30 #include <kernel/tee_ta_manager.h> 31 #include <mm/tee_mmu.h> 32 #include <string.h> 33 #include <tee_api_defines_extensions.h> 34 #include <tee_api_defines.h> 35 #include <tee/fs_dirfile.h> 36 #include <tee/tee_fs.h> 37 #include <tee/tee_obj.h> 38 #include <tee/tee_pobj.h> 39 #include <tee/tee_svc_cryp.h> 40 #include <tee/tee_svc.h> 41 #include <tee/tee_svc_storage.h> 42 #include <trace.h> 43 44 /* 45 * Returns the appropriate tee_file_operations for the specified storage ID. 46 * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise 47 * RPMB. 48 */ 49 static const struct tee_file_operations *file_ops(uint32_t storage_id) 50 { 51 52 switch (storage_id) { 53 case TEE_STORAGE_PRIVATE: 54 #if defined(CFG_REE_FS) 55 return &ree_fs_ops; 56 #elif defined(CFG_RPMB_FS) 57 return &rpmb_fs_ops; 58 #else 59 #error At least one filesystem must be enabled. 60 #endif 61 #ifdef CFG_REE_FS 62 case TEE_STORAGE_PRIVATE_REE: 63 return &ree_fs_ops; 64 #endif 65 #ifdef CFG_RPMB_FS 66 case TEE_STORAGE_PRIVATE_RPMB: 67 return &rpmb_fs_ops; 68 #endif 69 default: 70 return NULL; 71 } 72 } 73 74 /* Header of GP formated secure storage files */ 75 struct tee_svc_storage_head { 76 uint32_t attr_size; 77 uint32_t keySize; 78 uint32_t maxKeySize; 79 uint32_t objectUsage; 80 uint32_t objectType; 81 uint32_t have_attrs; 82 }; 83 84 struct tee_storage_enum { 85 TAILQ_ENTRY(tee_storage_enum) link; 86 struct tee_fs_dir *dir; 87 const struct tee_file_operations *fops; 88 }; 89 90 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, 91 uint32_t enum_id, 92 struct tee_storage_enum **e_out) 93 { 94 struct tee_storage_enum *e; 95 96 TAILQ_FOREACH(e, &utc->storage_enums, link) { 97 if (enum_id == (vaddr_t)e) { 98 *e_out = e; 99 return TEE_SUCCESS; 100 } 101 } 102 return TEE_ERROR_BAD_PARAMETERS; 103 } 104 105 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, 106 struct tee_storage_enum *e) 107 { 108 if (e == NULL || utc == NULL) 109 return TEE_ERROR_BAD_PARAMETERS; 110 111 TAILQ_REMOVE(&utc->storage_enums, e, link); 112 113 if (e->fops) 114 e->fops->closedir(e->dir); 115 116 e->dir = NULL; 117 e->fops = NULL; 118 119 free(e); 120 121 return TEE_SUCCESS; 122 } 123 124 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ 125 TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen, 126 struct tee_pobj *po, bool transient) 127 { 128 uint8_t *file = buf; 129 uint32_t pos = 0; 130 uint32_t hslen = 1 /* Leading slash */ 131 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) 132 + 1; /* Intermediate slash */ 133 134 /* +1 for the '.' (temporary persistent object) */ 135 if (transient) 136 hslen++; 137 138 if (blen < hslen) 139 return TEE_ERROR_SHORT_BUFFER; 140 141 file[pos++] = '/'; 142 pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], 143 sizeof(TEE_UUID), hslen); 144 file[pos++] = '/'; 145 146 if (transient) 147 file[pos++] = '.'; 148 149 tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); 150 151 return TEE_SUCCESS; 152 } 153 154 #ifdef CFG_REE_FS 155 /* "/dirf.db" or "/<file number>" */ 156 TEE_Result 157 tee_svc_storage_create_filename_dfh(void *buf, size_t blen, 158 const struct tee_fs_dirfile_fileh *dfh) 159 { 160 char *file = buf; 161 size_t pos = 0; 162 size_t l; 163 164 if (pos >= blen) 165 return TEE_ERROR_SHORT_BUFFER; 166 167 file[pos] = '/'; 168 pos++; 169 if (pos >= blen) 170 return TEE_ERROR_SHORT_BUFFER; 171 172 l = blen - pos; 173 return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l); 174 } 175 #endif 176 177 /* "/TA_uuid" */ 178 TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen, 179 const TEE_UUID *uuid) 180 { 181 uint8_t *dir = buf; 182 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; 183 184 if (blen < hslen) 185 return TEE_ERROR_SHORT_BUFFER; 186 187 dir[0] = '/'; 188 tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); 189 190 return TEE_SUCCESS; 191 } 192 193 static TEE_Result tee_svc_storage_remove_corrupt_obj( 194 struct tee_ta_session *sess, 195 struct tee_obj *o) 196 { 197 o->pobj->fops->remove(o->pobj); 198 tee_obj_close(to_user_ta_ctx(sess->ctx), o); 199 200 return TEE_SUCCESS; 201 } 202 203 static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) 204 { 205 TEE_Result res = TEE_SUCCESS; 206 size_t bytes; 207 struct tee_svc_storage_head head; 208 const struct tee_file_operations *fops = o->pobj->fops; 209 void *attr = NULL; 210 size_t size; 211 212 assert(!o->fh); 213 res = fops->open(o->pobj, &size, &o->fh); 214 if (res != TEE_SUCCESS) 215 goto exit; 216 217 /* read head */ 218 bytes = sizeof(struct tee_svc_storage_head); 219 res = fops->read(o->fh, 0, &head, &bytes); 220 if (res != TEE_SUCCESS) { 221 if (res == TEE_ERROR_CORRUPT_OBJECT) 222 EMSG("Head corrupt\n"); 223 goto exit; 224 } 225 226 if (bytes != sizeof(struct tee_svc_storage_head)) { 227 res = TEE_ERROR_BAD_FORMAT; 228 goto exit; 229 } 230 231 res = tee_obj_set_type(o, head.objectType, head.maxKeySize); 232 if (res != TEE_SUCCESS) 233 goto exit; 234 235 o->ds_pos = sizeof(struct tee_svc_storage_head) + head.attr_size; 236 if (head.attr_size) { 237 attr = malloc(head.attr_size); 238 if (!attr) { 239 res = TEE_ERROR_OUT_OF_MEMORY; 240 goto exit; 241 } 242 243 /* read meta */ 244 bytes = head.attr_size; 245 res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), 246 attr, &bytes); 247 if (res != TEE_SUCCESS || bytes != head.attr_size) { 248 res = TEE_ERROR_CORRUPT_OBJECT; 249 goto exit; 250 } 251 } 252 253 res = tee_obj_attr_from_binary(o, attr, head.attr_size); 254 if (res != TEE_SUCCESS) 255 goto exit; 256 257 o->info.dataSize = size - sizeof(head) - head.attr_size; 258 o->info.keySize = head.keySize; 259 o->info.objectUsage = head.objectUsage; 260 o->info.objectType = head.objectType; 261 o->have_attrs = head.have_attrs; 262 263 exit: 264 free(attr); 265 266 return res; 267 } 268 269 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 270 size_t object_id_len, unsigned long flags, 271 uint32_t *obj) 272 { 273 TEE_Result res; 274 struct tee_ta_session *sess; 275 struct tee_obj *o = NULL; 276 char *file = NULL; 277 struct tee_pobj *po = NULL; 278 struct user_ta_ctx *utc; 279 const struct tee_file_operations *fops = file_ops(storage_id); 280 size_t attr_size; 281 282 if (!fops) { 283 res = TEE_ERROR_ITEM_NOT_FOUND; 284 goto exit; 285 } 286 287 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 288 res = TEE_ERROR_BAD_PARAMETERS; 289 goto exit; 290 } 291 292 res = tee_ta_get_current_session(&sess); 293 if (res != TEE_SUCCESS) 294 goto err; 295 utc = to_user_ta_ctx(sess->ctx); 296 297 res = tee_mmu_check_access_rights(utc, 298 TEE_MEMORY_ACCESS_READ | 299 TEE_MEMORY_ACCESS_ANY_OWNER, 300 (uaddr_t) object_id, 301 object_id_len); 302 if (res != TEE_SUCCESS) 303 goto err; 304 305 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 306 object_id_len, flags, false, fops, &po); 307 if (res != TEE_SUCCESS) 308 goto err; 309 310 o = tee_obj_alloc(); 311 if (o == NULL) { 312 tee_pobj_release(po); 313 res = TEE_ERROR_OUT_OF_MEMORY; 314 goto err; 315 } 316 317 o->info.handleFlags = 318 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 319 o->flags = flags; 320 o->pobj = po; 321 tee_obj_add(utc, o); 322 323 res = tee_svc_storage_read_head(o); 324 if (res != TEE_SUCCESS) { 325 if (res == TEE_ERROR_CORRUPT_OBJECT) { 326 EMSG("Object corrupt"); 327 goto err; 328 } 329 goto oclose; 330 } 331 332 res = tee_svc_copy_kaddr_to_uref(obj, o); 333 if (res != TEE_SUCCESS) 334 goto oclose; 335 336 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 337 if (res != TEE_SUCCESS) 338 goto oclose; 339 340 goto exit; 341 342 oclose: 343 tee_obj_close(utc, o); 344 o = NULL; 345 346 err: 347 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 348 res = TEE_ERROR_CORRUPT_OBJECT; 349 if (res == TEE_ERROR_CORRUPT_OBJECT && o) 350 tee_svc_storage_remove_corrupt_obj(sess, o); 351 352 exit: 353 free(file); 354 file = NULL; 355 return res; 356 } 357 358 static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, 359 struct tee_obj *attr_o, void *data, 360 uint32_t len) 361 { 362 TEE_Result res = TEE_SUCCESS; 363 struct tee_svc_storage_head head; 364 const struct tee_file_operations *fops = o->pobj->fops; 365 void *attr = NULL; 366 size_t attr_size = 0; 367 368 if (attr_o) { 369 res = tee_obj_set_type(o, attr_o->info.objectType, 370 attr_o->info.maxKeySize); 371 if (res) 372 return res; 373 res = tee_obj_attr_copy_from(o, attr_o); 374 if (res) 375 return res; 376 o->have_attrs = attr_o->have_attrs; 377 o->info.objectUsage = attr_o->info.objectUsage; 378 o->info.keySize = attr_o->info.keySize; 379 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 380 if (res) 381 return res; 382 if (attr_size) { 383 attr = malloc(attr_size); 384 if (!attr) 385 return TEE_ERROR_OUT_OF_MEMORY; 386 res = tee_obj_attr_to_binary(o, attr, &attr_size); 387 if (res != TEE_SUCCESS) 388 goto exit; 389 } 390 } else { 391 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 392 if (res != TEE_SUCCESS) 393 goto exit; 394 } 395 396 o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; 397 398 /* write head */ 399 head.attr_size = attr_size; 400 head.keySize = o->info.keySize; 401 head.maxKeySize = o->info.maxKeySize; 402 head.objectUsage = o->info.objectUsage; 403 head.objectType = o->info.objectType; 404 head.have_attrs = o->have_attrs; 405 406 res = fops->create(o->pobj, !!(o->flags & TEE_DATA_FLAG_OVERWRITE), 407 &head, sizeof(head), attr, attr_size, data, len, 408 &o->fh); 409 410 if (!res) 411 o->info.dataSize = len; 412 exit: 413 free(attr); 414 return res; 415 } 416 417 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 418 size_t object_id_len, unsigned long flags, 419 unsigned long attr, void *data, size_t len, 420 uint32_t *obj) 421 { 422 TEE_Result res; 423 struct tee_ta_session *sess; 424 struct tee_obj *o = NULL; 425 struct tee_obj *attr_o = NULL; 426 struct tee_pobj *po = NULL; 427 struct user_ta_ctx *utc; 428 const struct tee_file_operations *fops = file_ops(storage_id); 429 430 if (!fops) 431 return TEE_ERROR_ITEM_NOT_FOUND; 432 433 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 434 return TEE_ERROR_BAD_PARAMETERS; 435 436 res = tee_ta_get_current_session(&sess); 437 if (res != TEE_SUCCESS) 438 return res; 439 utc = to_user_ta_ctx(sess->ctx); 440 441 res = tee_mmu_check_access_rights(utc, 442 TEE_MEMORY_ACCESS_READ | 443 TEE_MEMORY_ACCESS_ANY_OWNER, 444 (uaddr_t) object_id, 445 object_id_len); 446 if (res != TEE_SUCCESS) 447 goto err; 448 449 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 450 object_id_len, flags, true, fops, &po); 451 if (res != TEE_SUCCESS) 452 goto err; 453 454 /* check rights of the provided buffer */ 455 if (data && len) { 456 res = tee_mmu_check_access_rights(utc, 457 TEE_MEMORY_ACCESS_READ | 458 TEE_MEMORY_ACCESS_ANY_OWNER, 459 (uaddr_t) data, len); 460 461 if (res != TEE_SUCCESS) 462 goto err; 463 } 464 465 o = tee_obj_alloc(); 466 if (o == NULL) { 467 res = TEE_ERROR_OUT_OF_MEMORY; 468 goto err; 469 } 470 471 o->info.handleFlags = 472 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 473 o->flags = flags; 474 o->pobj = po; 475 476 if (attr != TEE_HANDLE_NULL) { 477 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 478 &attr_o); 479 if (res != TEE_SUCCESS) 480 goto err; 481 } 482 483 res = tee_svc_storage_init_file(o, attr_o, data, len); 484 if (res != TEE_SUCCESS) 485 goto err; 486 487 po = NULL; /* o owns it from now on */ 488 tee_obj_add(utc, o); 489 490 res = tee_svc_copy_kaddr_to_uref(obj, o); 491 if (res != TEE_SUCCESS) 492 goto oclose; 493 494 return TEE_SUCCESS; 495 496 oclose: 497 tee_obj_close(utc, o); 498 return res; 499 500 err: 501 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 502 res = TEE_ERROR_CORRUPT_OBJECT; 503 if (res == TEE_ERROR_CORRUPT_OBJECT && po) 504 fops->remove(po); 505 if (o) 506 fops->close(&o->fh); 507 if (po) 508 tee_pobj_release(po); 509 free(o); 510 511 return res; 512 } 513 514 TEE_Result syscall_storage_obj_del(unsigned long obj) 515 { 516 TEE_Result res; 517 struct tee_ta_session *sess; 518 struct tee_obj *o; 519 struct user_ta_ctx *utc; 520 521 res = tee_ta_get_current_session(&sess); 522 if (res != TEE_SUCCESS) 523 return res; 524 utc = to_user_ta_ctx(sess->ctx); 525 526 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 527 if (res != TEE_SUCCESS) 528 return res; 529 530 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 531 return TEE_ERROR_ACCESS_CONFLICT; 532 533 if (o->pobj == NULL || o->pobj->obj_id == NULL) 534 return TEE_ERROR_BAD_STATE; 535 536 res = o->pobj->fops->remove(o->pobj); 537 tee_obj_close(utc, o); 538 539 return res; 540 } 541 542 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 543 size_t object_id_len) 544 { 545 TEE_Result res; 546 struct tee_ta_session *sess; 547 struct tee_obj *o; 548 struct tee_pobj *po = NULL; 549 char *new_file = NULL; 550 char *old_file = NULL; 551 struct user_ta_ctx *utc; 552 const struct tee_file_operations *fops; 553 554 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 555 return TEE_ERROR_BAD_PARAMETERS; 556 557 res = tee_ta_get_current_session(&sess); 558 if (res != TEE_SUCCESS) 559 return res; 560 utc = to_user_ta_ctx(sess->ctx); 561 562 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 563 if (res != TEE_SUCCESS) 564 return res; 565 566 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 567 res = TEE_ERROR_BAD_STATE; 568 goto exit; 569 } 570 571 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 572 res = TEE_ERROR_BAD_STATE; 573 goto exit; 574 } 575 576 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 577 res = TEE_ERROR_BAD_STATE; 578 goto exit; 579 } 580 581 res = tee_mmu_check_access_rights(utc, 582 TEE_MEMORY_ACCESS_READ | 583 TEE_MEMORY_ACCESS_ANY_OWNER, 584 (uaddr_t) object_id, object_id_len); 585 if (res != TEE_SUCCESS) 586 goto exit; 587 588 /* reserve dest name */ 589 fops = o->pobj->fops; 590 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 591 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 592 false, fops, &po); 593 if (res != TEE_SUCCESS) 594 goto exit; 595 596 /* move */ 597 res = fops->rename(o->pobj, po, false /* no overwrite */); 598 if (res == TEE_ERROR_GENERIC) 599 goto exit; 600 601 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 602 603 exit: 604 tee_pobj_release(po); 605 606 free(new_file); 607 free(old_file); 608 609 return res; 610 } 611 612 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 613 { 614 struct tee_storage_enum *e; 615 struct tee_ta_session *sess; 616 TEE_Result res; 617 struct user_ta_ctx *utc; 618 619 if (obj_enum == NULL) 620 return TEE_ERROR_BAD_PARAMETERS; 621 622 res = tee_ta_get_current_session(&sess); 623 if (res != TEE_SUCCESS) 624 return res; 625 utc = to_user_ta_ctx(sess->ctx); 626 627 e = malloc(sizeof(struct tee_storage_enum)); 628 if (e == NULL) 629 return TEE_ERROR_OUT_OF_MEMORY; 630 631 e->dir = NULL; 632 e->fops = NULL; 633 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 634 635 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 636 } 637 638 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 639 { 640 struct tee_storage_enum *e; 641 TEE_Result res; 642 struct tee_ta_session *sess; 643 struct user_ta_ctx *utc; 644 645 res = tee_ta_get_current_session(&sess); 646 if (res != TEE_SUCCESS) 647 return res; 648 utc = to_user_ta_ctx(sess->ctx); 649 650 res = tee_svc_storage_get_enum(utc, 651 tee_svc_uref_to_vaddr(obj_enum), &e); 652 if (res != TEE_SUCCESS) 653 return res; 654 655 return tee_svc_close_enum(utc, e); 656 } 657 658 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 659 { 660 struct tee_storage_enum *e; 661 TEE_Result res; 662 struct tee_ta_session *sess; 663 664 res = tee_ta_get_current_session(&sess); 665 if (res != TEE_SUCCESS) 666 return res; 667 668 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 669 tee_svc_uref_to_vaddr(obj_enum), &e); 670 if (res != TEE_SUCCESS) 671 return res; 672 673 if (e->fops) { 674 e->fops->closedir(e->dir); 675 e->fops = NULL; 676 e->dir = NULL; 677 } 678 assert(!e->dir); 679 680 return TEE_SUCCESS; 681 } 682 683 static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d, 684 const struct tee_file_operations *fops, 685 struct tee_obj *o) 686 { 687 o->info.handleFlags = 688 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 689 o->info.objectUsage = TEE_USAGE_DEFAULT; 690 691 o->pobj->obj_id = malloc(d->oidlen); 692 if (!o->pobj->obj_id) 693 return TEE_ERROR_OUT_OF_MEMORY; 694 695 memcpy(o->pobj->obj_id, d->oid, d->oidlen); 696 o->pobj->obj_id_len = d->oidlen; 697 o->pobj->fops = fops; 698 699 return TEE_SUCCESS; 700 } 701 702 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 703 unsigned long storage_id) 704 { 705 struct tee_storage_enum *e; 706 TEE_Result res; 707 struct tee_ta_session *sess; 708 const struct tee_file_operations *fops = file_ops(storage_id); 709 710 res = tee_ta_get_current_session(&sess); 711 if (res != TEE_SUCCESS) 712 return res; 713 714 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 715 tee_svc_uref_to_vaddr(obj_enum), &e); 716 if (res != TEE_SUCCESS) 717 return res; 718 719 if (!fops) 720 return TEE_ERROR_ITEM_NOT_FOUND; 721 722 e->fops = fops; 723 assert(!e->dir); 724 return fops->opendir(&sess->ctx->uuid, &e->dir); 725 } 726 727 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 728 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 729 { 730 struct tee_storage_enum *e; 731 struct tee_fs_dirent *d; 732 TEE_Result res = TEE_SUCCESS; 733 struct tee_ta_session *sess; 734 struct tee_obj *o = NULL; 735 uint64_t l; 736 struct user_ta_ctx *utc; 737 738 res = tee_ta_get_current_session(&sess); 739 if (res != TEE_SUCCESS) 740 goto exit; 741 utc = to_user_ta_ctx(sess->ctx); 742 743 res = tee_svc_storage_get_enum(utc, 744 tee_svc_uref_to_vaddr(obj_enum), &e); 745 if (res != TEE_SUCCESS) 746 goto exit; 747 748 /* check rights of the provided buffers */ 749 res = tee_mmu_check_access_rights(utc, 750 TEE_MEMORY_ACCESS_WRITE | 751 TEE_MEMORY_ACCESS_ANY_OWNER, 752 (uaddr_t) info, 753 sizeof(TEE_ObjectInfo)); 754 if (res != TEE_SUCCESS) 755 goto exit; 756 757 res = tee_mmu_check_access_rights(utc, 758 TEE_MEMORY_ACCESS_WRITE | 759 TEE_MEMORY_ACCESS_ANY_OWNER, 760 (uaddr_t) obj_id, 761 TEE_OBJECT_ID_MAX_LEN); 762 if (res != TEE_SUCCESS) 763 goto exit; 764 765 if (!e->fops) { 766 res = TEE_ERROR_ITEM_NOT_FOUND; 767 goto exit; 768 } 769 770 res = e->fops->readdir(e->dir, &d); 771 if (res != TEE_SUCCESS) 772 goto exit; 773 774 o = tee_obj_alloc(); 775 if (o == NULL) { 776 res = TEE_ERROR_OUT_OF_MEMORY; 777 goto exit; 778 } 779 o->flags = TEE_DATA_FLAG_SHARE_READ; 780 781 o->pobj = calloc(1, sizeof(struct tee_pobj)); 782 if (!o->pobj) { 783 res = TEE_ERROR_OUT_OF_MEMORY; 784 goto exit; 785 } 786 787 o->pobj->uuid = sess->ctx->uuid; 788 res = tee_svc_storage_set_enum(d, e->fops, o); 789 if (res != TEE_SUCCESS) 790 goto exit; 791 792 res = tee_svc_storage_read_head(o); 793 if (res != TEE_SUCCESS) 794 goto exit; 795 796 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 797 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 798 799 l = o->pobj->obj_id_len; 800 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 801 802 exit: 803 if (o) { 804 if (o->pobj) { 805 o->pobj->fops->close(&o->fh); 806 free(o->pobj->obj_id); 807 } 808 free(o->pobj); 809 tee_obj_free(o); 810 } 811 812 return res; 813 } 814 815 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 816 uint64_t *count) 817 { 818 TEE_Result res; 819 struct tee_ta_session *sess; 820 struct tee_obj *o; 821 uint64_t u_count; 822 struct user_ta_ctx *utc; 823 size_t bytes; 824 825 res = tee_ta_get_current_session(&sess); 826 if (res != TEE_SUCCESS) 827 goto exit; 828 utc = to_user_ta_ctx(sess->ctx); 829 830 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 831 if (res != TEE_SUCCESS) 832 goto exit; 833 834 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 835 res = TEE_ERROR_BAD_STATE; 836 goto exit; 837 } 838 839 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) { 840 res = TEE_ERROR_ACCESS_CONFLICT; 841 goto exit; 842 } 843 844 /* check rights of the provided buffer */ 845 res = tee_mmu_check_access_rights(utc, 846 TEE_MEMORY_ACCESS_WRITE | 847 TEE_MEMORY_ACCESS_ANY_OWNER, 848 (uaddr_t) data, len); 849 if (res != TEE_SUCCESS) 850 goto exit; 851 852 bytes = len; 853 res = o->pobj->fops->read(o->fh, o->ds_pos + o->info.dataPosition, 854 data, &bytes); 855 if (res != TEE_SUCCESS) { 856 EMSG("Error code=%x\n", (uint32_t)res); 857 if (res == TEE_ERROR_CORRUPT_OBJECT) { 858 EMSG("Object corrupt\n"); 859 tee_svc_storage_remove_corrupt_obj(sess, o); 860 } 861 goto exit; 862 } 863 864 o->info.dataPosition += bytes; 865 866 u_count = bytes; 867 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 868 exit: 869 return res; 870 } 871 872 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 873 { 874 TEE_Result res; 875 struct tee_ta_session *sess; 876 struct tee_obj *o; 877 struct user_ta_ctx *utc; 878 879 res = tee_ta_get_current_session(&sess); 880 if (res != TEE_SUCCESS) 881 goto exit; 882 utc = to_user_ta_ctx(sess->ctx); 883 884 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 885 if (res != TEE_SUCCESS) 886 goto exit; 887 888 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 889 res = TEE_ERROR_BAD_STATE; 890 goto exit; 891 } 892 893 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 894 res = TEE_ERROR_ACCESS_CONFLICT; 895 goto exit; 896 } 897 898 /* check rights of the provided buffer */ 899 res = tee_mmu_check_access_rights(utc, 900 TEE_MEMORY_ACCESS_READ | 901 TEE_MEMORY_ACCESS_ANY_OWNER, 902 (uaddr_t) data, len); 903 if (res != TEE_SUCCESS) 904 goto exit; 905 906 res = o->pobj->fops->write(o->fh, o->ds_pos + o->info.dataPosition, 907 data, len); 908 if (res != TEE_SUCCESS) 909 goto exit; 910 911 o->info.dataPosition += len; 912 if (o->info.dataPosition > o->info.dataSize) 913 o->info.dataSize = o->info.dataPosition; 914 915 exit: 916 return res; 917 } 918 919 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 920 { 921 TEE_Result res; 922 struct tee_ta_session *sess; 923 struct tee_obj *o; 924 size_t off; 925 size_t attr_size; 926 927 res = tee_ta_get_current_session(&sess); 928 if (res != TEE_SUCCESS) 929 goto exit; 930 931 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 932 tee_svc_uref_to_vaddr(obj), &o); 933 if (res != TEE_SUCCESS) 934 goto exit; 935 936 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 937 res = TEE_ERROR_BAD_STATE; 938 goto exit; 939 } 940 941 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 942 res = TEE_ERROR_ACCESS_CONFLICT; 943 goto exit; 944 } 945 946 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 947 if (res != TEE_SUCCESS) 948 goto exit; 949 950 off = sizeof(struct tee_svc_storage_head) + attr_size; 951 res = o->pobj->fops->truncate(o->fh, len + off); 952 if (res != TEE_SUCCESS) { 953 if (res == TEE_ERROR_CORRUPT_OBJECT) { 954 EMSG("Object corrupt\n"); 955 res = tee_svc_storage_remove_corrupt_obj(sess, o); 956 if (res != TEE_SUCCESS) 957 goto exit; 958 res = TEE_ERROR_CORRUPT_OBJECT; 959 goto exit; 960 } else 961 res = TEE_ERROR_GENERIC; 962 } 963 964 exit: 965 return res; 966 } 967 968 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 969 unsigned long whence) 970 { 971 TEE_Result res; 972 struct tee_ta_session *sess; 973 struct tee_obj *o; 974 size_t attr_size; 975 tee_fs_off_t new_pos; 976 977 res = tee_ta_get_current_session(&sess); 978 if (res != TEE_SUCCESS) 979 return res; 980 981 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 982 tee_svc_uref_to_vaddr(obj), &o); 983 if (res != TEE_SUCCESS) 984 return res; 985 986 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) 987 return TEE_ERROR_BAD_STATE; 988 989 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 990 if (res != TEE_SUCCESS) 991 return res; 992 993 switch (whence) { 994 case TEE_DATA_SEEK_SET: 995 new_pos = offset; 996 break; 997 case TEE_DATA_SEEK_CUR: 998 new_pos = o->info.dataPosition + offset; 999 break; 1000 case TEE_DATA_SEEK_END: 1001 new_pos = o->info.dataSize + offset; 1002 break; 1003 default: 1004 return TEE_ERROR_BAD_PARAMETERS; 1005 } 1006 1007 if (new_pos < 0) 1008 new_pos = 0; 1009 1010 if (new_pos > TEE_DATA_MAX_POSITION) { 1011 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 1012 return TEE_ERROR_BAD_PARAMETERS; 1013 } 1014 1015 o->info.dataPosition = new_pos; 1016 1017 return TEE_SUCCESS; 1018 } 1019 1020 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1021 { 1022 struct tee_storage_enum_head *eh = &utc->storage_enums; 1023 1024 /* disregard return value */ 1025 while (!TAILQ_EMPTY(eh)) 1026 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1027 } 1028