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