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