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