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 size_t tmp = 0; 185 186 assert(!o->fh); 187 res = fops->open(o->pobj, &size, &o->fh); 188 if (res != TEE_SUCCESS) 189 goto exit; 190 191 /* read head */ 192 bytes = sizeof(struct tee_svc_storage_head); 193 res = fops->read(o->fh, 0, &head, &bytes); 194 if (res != TEE_SUCCESS) { 195 if (res == TEE_ERROR_CORRUPT_OBJECT) 196 EMSG("Head corrupt"); 197 goto exit; 198 } 199 200 if (ADD_OVERFLOW(sizeof(head), head.attr_size, &tmp)) { 201 res = TEE_ERROR_OVERFLOW; 202 goto exit; 203 } 204 if (tmp > size) { 205 res = TEE_ERROR_CORRUPT_OBJECT; 206 goto exit; 207 } 208 209 if (bytes != sizeof(struct tee_svc_storage_head)) { 210 res = TEE_ERROR_BAD_FORMAT; 211 goto exit; 212 } 213 214 res = tee_obj_set_type(o, head.objectType, head.maxKeySize); 215 if (res != TEE_SUCCESS) 216 goto exit; 217 218 o->ds_pos = tmp; 219 220 if (head.attr_size) { 221 attr = malloc(head.attr_size); 222 if (!attr) { 223 res = TEE_ERROR_OUT_OF_MEMORY; 224 goto exit; 225 } 226 227 /* read meta */ 228 bytes = head.attr_size; 229 res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), 230 attr, &bytes); 231 if (res == TEE_ERROR_OUT_OF_MEMORY) 232 goto exit; 233 if (res != TEE_SUCCESS || bytes != head.attr_size) 234 res = TEE_ERROR_CORRUPT_OBJECT; 235 if (res) 236 goto exit; 237 } 238 239 res = tee_obj_attr_from_binary(o, attr, head.attr_size); 240 if (res != TEE_SUCCESS) 241 goto exit; 242 243 o->info.dataSize = size - sizeof(head) - head.attr_size; 244 o->info.keySize = head.keySize; 245 o->info.objectUsage = head.objectUsage; 246 o->info.objectType = head.objectType; 247 o->have_attrs = head.have_attrs; 248 249 exit: 250 free(attr); 251 252 return res; 253 } 254 255 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 256 size_t object_id_len, unsigned long flags, 257 uint32_t *obj) 258 { 259 const struct tee_file_operations *fops = 260 tee_svc_storage_file_ops(storage_id); 261 struct tee_ta_session *sess = NULL; 262 struct user_ta_ctx *utc = NULL; 263 TEE_Result res = TEE_SUCCESS; 264 struct tee_pobj *po = NULL; 265 struct tee_obj *o = NULL; 266 char *file = NULL; 267 268 if (!fops) { 269 res = TEE_ERROR_ITEM_NOT_FOUND; 270 goto exit; 271 } 272 273 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 274 res = TEE_ERROR_BAD_PARAMETERS; 275 goto exit; 276 } 277 278 res = tee_ta_get_current_session(&sess); 279 if (res != TEE_SUCCESS) 280 goto err; 281 utc = to_user_ta_ctx(sess->ctx); 282 283 res = tee_mmu_check_access_rights(&utc->uctx, 284 TEE_MEMORY_ACCESS_READ, 285 (uaddr_t) object_id, 286 object_id_len); 287 if (res != TEE_SUCCESS) 288 goto err; 289 290 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 291 object_id_len, flags, false, fops, &po); 292 if (res != TEE_SUCCESS) 293 goto err; 294 295 o = tee_obj_alloc(); 296 if (o == NULL) { 297 tee_pobj_release(po); 298 res = TEE_ERROR_OUT_OF_MEMORY; 299 goto err; 300 } 301 302 o->info.handleFlags = 303 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 304 o->flags = flags; 305 o->pobj = po; 306 tee_obj_add(utc, o); 307 308 res = tee_svc_storage_read_head(o); 309 if (res != TEE_SUCCESS) { 310 if (res == TEE_ERROR_CORRUPT_OBJECT) { 311 EMSG("Object corrupt"); 312 goto err; 313 } 314 goto oclose; 315 } 316 317 res = tee_svc_copy_kaddr_to_uref(obj, o); 318 if (res != TEE_SUCCESS) 319 goto oclose; 320 321 goto exit; 322 323 oclose: 324 tee_obj_close(utc, o); 325 o = NULL; 326 327 err: 328 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 329 res = TEE_ERROR_CORRUPT_OBJECT; 330 if (res == TEE_ERROR_CORRUPT_OBJECT && o) 331 tee_svc_storage_remove_corrupt_obj(sess, o); 332 333 exit: 334 free(file); 335 file = NULL; 336 return res; 337 } 338 339 static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, 340 struct tee_obj *attr_o, void *data, 341 uint32_t len) 342 { 343 TEE_Result res = TEE_SUCCESS; 344 struct tee_svc_storage_head head; 345 const struct tee_file_operations *fops = o->pobj->fops; 346 void *attr = NULL; 347 size_t attr_size = 0; 348 349 if (attr_o) { 350 res = tee_obj_set_type(o, attr_o->info.objectType, 351 attr_o->info.maxKeySize); 352 if (res) 353 return res; 354 res = tee_obj_attr_copy_from(o, attr_o); 355 if (res) 356 return res; 357 o->have_attrs = attr_o->have_attrs; 358 o->info.objectUsage = attr_o->info.objectUsage; 359 o->info.keySize = attr_o->info.keySize; 360 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 361 if (res) 362 return res; 363 if (attr_size) { 364 attr = malloc(attr_size); 365 if (!attr) 366 return TEE_ERROR_OUT_OF_MEMORY; 367 res = tee_obj_attr_to_binary(o, attr, &attr_size); 368 if (res != TEE_SUCCESS) 369 goto exit; 370 } 371 } else { 372 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); 373 if (res != TEE_SUCCESS) 374 goto exit; 375 } 376 377 o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; 378 379 /* write head */ 380 head.attr_size = attr_size; 381 head.keySize = o->info.keySize; 382 head.maxKeySize = o->info.maxKeySize; 383 head.objectUsage = o->info.objectUsage; 384 head.objectType = o->info.objectType; 385 head.have_attrs = o->have_attrs; 386 387 res = fops->create(o->pobj, !!(o->flags & TEE_DATA_FLAG_OVERWRITE), 388 &head, sizeof(head), attr, attr_size, data, len, 389 &o->fh); 390 391 if (!res) 392 o->info.dataSize = len; 393 exit: 394 free(attr); 395 return res; 396 } 397 398 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, 399 size_t object_id_len, unsigned long flags, 400 unsigned long attr, void *data, size_t len, 401 uint32_t *obj) 402 { 403 const struct tee_file_operations *fops = 404 tee_svc_storage_file_ops(storage_id); 405 struct tee_ta_session *sess = NULL; 406 struct user_ta_ctx *utc = NULL; 407 struct tee_obj *attr_o = NULL; 408 TEE_Result res = TEE_SUCCESS; 409 struct tee_pobj *po = NULL; 410 struct tee_obj *o = NULL; 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->uctx, TEE_MEMORY_ACCESS_READ, 424 (uaddr_t)object_id, object_id_len); 425 if (res != TEE_SUCCESS) 426 goto err; 427 428 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 429 object_id_len, flags, true, fops, &po); 430 if (res != TEE_SUCCESS) 431 goto err; 432 433 /* check rights of the provided buffer */ 434 if (len) { 435 if (data) { 436 uint32_t f = TEE_MEMORY_ACCESS_READ | 437 TEE_MEMORY_ACCESS_ANY_OWNER; 438 439 res = tee_mmu_check_access_rights(&utc->uctx, f, 440 (uaddr_t)data, len); 441 442 if (res != TEE_SUCCESS) 443 goto err; 444 } else { 445 res = TEE_ERROR_BAD_PARAMETERS; 446 goto err; 447 } 448 } 449 450 o = tee_obj_alloc(); 451 if (o == NULL) { 452 res = TEE_ERROR_OUT_OF_MEMORY; 453 goto err; 454 } 455 456 o->info.handleFlags = 457 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 458 o->flags = flags; 459 o->pobj = po; 460 461 if (attr != TEE_HANDLE_NULL) { 462 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr), 463 &attr_o); 464 if (res != TEE_SUCCESS) 465 goto err; 466 /* The supplied handle must be one of an initialized object */ 467 if (!(attr_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { 468 res = TEE_ERROR_BAD_PARAMETERS; 469 goto err; 470 } 471 } 472 473 res = tee_svc_storage_init_file(o, attr_o, data, len); 474 if (res != TEE_SUCCESS) 475 goto err; 476 477 po = NULL; /* o owns it from now on */ 478 tee_obj_add(utc, o); 479 480 res = tee_svc_copy_kaddr_to_uref(obj, o); 481 if (res != TEE_SUCCESS) 482 goto oclose; 483 484 return TEE_SUCCESS; 485 486 oclose: 487 tee_obj_close(utc, o); 488 return res; 489 490 err: 491 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) 492 res = TEE_ERROR_CORRUPT_OBJECT; 493 if (res == TEE_ERROR_CORRUPT_OBJECT && po) 494 fops->remove(po); 495 if (o) { 496 fops->close(&o->fh); 497 tee_obj_free(o); 498 } 499 if (po) 500 tee_pobj_release(po); 501 502 return res; 503 } 504 505 TEE_Result syscall_storage_obj_del(unsigned long obj) 506 { 507 TEE_Result res; 508 struct tee_ta_session *sess; 509 struct tee_obj *o; 510 struct user_ta_ctx *utc; 511 512 res = tee_ta_get_current_session(&sess); 513 if (res != TEE_SUCCESS) 514 return res; 515 utc = to_user_ta_ctx(sess->ctx); 516 517 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 518 if (res != TEE_SUCCESS) 519 return res; 520 521 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 522 return TEE_ERROR_ACCESS_CONFLICT; 523 524 if (o->pobj == NULL || o->pobj->obj_id == NULL) 525 return TEE_ERROR_BAD_STATE; 526 527 res = o->pobj->fops->remove(o->pobj); 528 tee_obj_close(utc, o); 529 530 return res; 531 } 532 533 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 534 size_t object_id_len) 535 { 536 const struct tee_file_operations *fops = NULL; 537 struct tee_ta_session *sess = NULL; 538 struct user_ta_ctx *utc = NULL; 539 TEE_Result res = TEE_SUCCESS; 540 struct tee_pobj *po = NULL; 541 struct tee_obj *o = NULL; 542 char *new_file = NULL; 543 char *old_file = NULL; 544 545 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 546 return TEE_ERROR_BAD_PARAMETERS; 547 548 res = tee_ta_get_current_session(&sess); 549 if (res != TEE_SUCCESS) 550 return res; 551 utc = to_user_ta_ctx(sess->ctx); 552 553 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 554 if (res != TEE_SUCCESS) 555 return res; 556 557 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 558 res = TEE_ERROR_BAD_STATE; 559 goto exit; 560 } 561 562 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 563 res = TEE_ERROR_BAD_STATE; 564 goto exit; 565 } 566 567 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 568 res = TEE_ERROR_BAD_STATE; 569 goto exit; 570 } 571 572 res = tee_mmu_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, 573 (uaddr_t)object_id, object_id_len); 574 if (res != TEE_SUCCESS) 575 goto exit; 576 577 /* reserve dest name */ 578 fops = o->pobj->fops; 579 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 580 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 581 false, fops, &po); 582 if (res != TEE_SUCCESS) 583 goto exit; 584 585 /* move */ 586 res = fops->rename(o->pobj, po, false /* no overwrite */); 587 if (res) 588 goto exit; 589 590 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 591 592 exit: 593 tee_pobj_release(po); 594 595 free(new_file); 596 free(old_file); 597 598 return res; 599 } 600 601 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 602 { 603 struct tee_storage_enum *e; 604 struct tee_ta_session *sess; 605 TEE_Result res; 606 struct user_ta_ctx *utc; 607 608 if (obj_enum == NULL) 609 return TEE_ERROR_BAD_PARAMETERS; 610 611 res = tee_ta_get_current_session(&sess); 612 if (res != TEE_SUCCESS) 613 return res; 614 utc = to_user_ta_ctx(sess->ctx); 615 616 e = malloc(sizeof(struct tee_storage_enum)); 617 if (e == NULL) 618 return TEE_ERROR_OUT_OF_MEMORY; 619 620 e->dir = NULL; 621 e->fops = NULL; 622 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 623 624 return tee_svc_copy_kaddr_to_uref(obj_enum, e); 625 } 626 627 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 628 { 629 struct tee_storage_enum *e; 630 TEE_Result res; 631 struct tee_ta_session *sess; 632 struct user_ta_ctx *utc; 633 634 res = tee_ta_get_current_session(&sess); 635 if (res != TEE_SUCCESS) 636 return res; 637 utc = to_user_ta_ctx(sess->ctx); 638 639 res = tee_svc_storage_get_enum(utc, 640 tee_svc_uref_to_vaddr(obj_enum), &e); 641 if (res != TEE_SUCCESS) 642 return res; 643 644 return tee_svc_close_enum(utc, e); 645 } 646 647 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 648 { 649 struct tee_storage_enum *e; 650 TEE_Result res; 651 struct tee_ta_session *sess; 652 653 res = tee_ta_get_current_session(&sess); 654 if (res != TEE_SUCCESS) 655 return res; 656 657 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 658 tee_svc_uref_to_vaddr(obj_enum), &e); 659 if (res != TEE_SUCCESS) 660 return res; 661 662 if (e->fops) { 663 e->fops->closedir(e->dir); 664 e->fops = NULL; 665 e->dir = NULL; 666 } 667 assert(!e->dir); 668 669 return TEE_SUCCESS; 670 } 671 672 static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d, 673 const struct tee_file_operations *fops, 674 struct tee_obj *o) 675 { 676 o->info.handleFlags = 677 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 678 o->info.objectUsage = TEE_USAGE_DEFAULT; 679 680 if (d->oidlen > TEE_OBJECT_ID_MAX_LEN) 681 return TEE_ERROR_CORRUPT_OBJECT; 682 683 o->pobj->obj_id = malloc(d->oidlen); 684 if (!o->pobj->obj_id) 685 return TEE_ERROR_OUT_OF_MEMORY; 686 687 memcpy(o->pobj->obj_id, d->oid, d->oidlen); 688 o->pobj->obj_id_len = d->oidlen; 689 o->pobj->fops = fops; 690 691 return TEE_SUCCESS; 692 } 693 694 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 695 unsigned long storage_id) 696 { 697 struct tee_storage_enum *e; 698 TEE_Result res; 699 struct tee_ta_session *sess; 700 const struct tee_file_operations *fops = 701 tee_svc_storage_file_ops(storage_id); 702 703 res = tee_ta_get_current_session(&sess); 704 if (res != TEE_SUCCESS) 705 return res; 706 707 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 708 tee_svc_uref_to_vaddr(obj_enum), &e); 709 if (res != TEE_SUCCESS) 710 return res; 711 712 if (e->dir) { 713 e->fops->closedir(e->dir); 714 e->dir = NULL; 715 } 716 717 if (!fops) 718 return TEE_ERROR_ITEM_NOT_FOUND; 719 720 e->fops = fops; 721 722 return fops->opendir(&sess->ctx->uuid, &e->dir); 723 } 724 725 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 726 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 727 { 728 struct tee_ta_session *sess = NULL; 729 struct tee_storage_enum *e = NULL; 730 struct tee_fs_dirent *d = NULL; 731 struct user_ta_ctx *utc = NULL; 732 TEE_Result res = TEE_SUCCESS; 733 struct tee_obj *o = NULL; 734 uint64_t l = 0; 735 736 res = tee_ta_get_current_session(&sess); 737 if (res != TEE_SUCCESS) 738 goto exit; 739 utc = to_user_ta_ctx(sess->ctx); 740 741 res = tee_svc_storage_get_enum(utc, 742 tee_svc_uref_to_vaddr(obj_enum), &e); 743 if (res != TEE_SUCCESS) 744 goto exit; 745 746 /* check rights of the provided buffers */ 747 res = tee_mmu_check_access_rights(&utc->uctx, 748 TEE_MEMORY_ACCESS_WRITE | 749 TEE_MEMORY_ACCESS_ANY_OWNER, 750 (uaddr_t)info, 751 sizeof(TEE_ObjectInfo)); 752 if (res != TEE_SUCCESS) 753 goto exit; 754 755 res = tee_mmu_check_access_rights(&utc->uctx, 756 TEE_MEMORY_ACCESS_WRITE | 757 TEE_MEMORY_ACCESS_ANY_OWNER, 758 (uaddr_t)obj_id, 759 TEE_OBJECT_ID_MAX_LEN); 760 if (res != TEE_SUCCESS) 761 goto exit; 762 763 if (!e->fops) { 764 res = TEE_ERROR_ITEM_NOT_FOUND; 765 goto exit; 766 } 767 768 res = e->fops->readdir(e->dir, &d); 769 if (res != TEE_SUCCESS) 770 goto exit; 771 772 o = tee_obj_alloc(); 773 if (o == NULL) { 774 res = TEE_ERROR_OUT_OF_MEMORY; 775 goto exit; 776 } 777 o->flags = TEE_DATA_FLAG_SHARE_READ; 778 779 o->pobj = calloc(1, sizeof(struct tee_pobj)); 780 if (!o->pobj) { 781 res = TEE_ERROR_OUT_OF_MEMORY; 782 goto exit; 783 } 784 785 o->pobj->uuid = sess->ctx->uuid; 786 res = tee_svc_storage_set_enum(d, e->fops, o); 787 if (res != TEE_SUCCESS) 788 goto exit; 789 790 res = tee_svc_storage_read_head(o); 791 if (res != TEE_SUCCESS) 792 goto exit; 793 794 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 795 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 796 797 l = o->pobj->obj_id_len; 798 res = tee_svc_copy_to_user(len, &l, sizeof(*len)); 799 800 exit: 801 if (o) { 802 if (o->pobj) { 803 if (o->pobj->fops) 804 o->pobj->fops->close(&o->fh); 805 free(o->pobj->obj_id); 806 } 807 free(o->pobj); 808 tee_obj_free(o); 809 } 810 811 return res; 812 } 813 814 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 815 uint64_t *count) 816 { 817 struct tee_ta_session *sess = NULL; 818 struct user_ta_ctx *utc = NULL; 819 TEE_Result res = TEE_SUCCESS; 820 struct tee_obj *o = NULL; 821 uint64_t u_count = 0; 822 size_t pos_tmp = 0; 823 size_t bytes = 0; 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 /* Guard o->info.dataPosition += bytes below from overflowing */ 845 if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { 846 res = TEE_ERROR_OVERFLOW; 847 goto exit; 848 } 849 850 /* check rights of the provided buffer */ 851 res = tee_mmu_check_access_rights(&utc->uctx, 852 TEE_MEMORY_ACCESS_WRITE | 853 TEE_MEMORY_ACCESS_ANY_OWNER, 854 (uaddr_t)data, len); 855 if (res != TEE_SUCCESS) 856 goto exit; 857 858 bytes = len; 859 if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { 860 res = TEE_ERROR_OVERFLOW; 861 goto exit; 862 } 863 res = o->pobj->fops->read(o->fh, pos_tmp, data, &bytes); 864 if (res != TEE_SUCCESS) { 865 if (res == TEE_ERROR_CORRUPT_OBJECT) { 866 EMSG("Object corrupt"); 867 tee_svc_storage_remove_corrupt_obj(sess, o); 868 } 869 goto exit; 870 } 871 872 o->info.dataPosition += bytes; 873 874 u_count = bytes; 875 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count)); 876 exit: 877 return res; 878 } 879 880 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 881 { 882 struct tee_ta_session *sess = NULL; 883 struct user_ta_ctx *utc = NULL; 884 TEE_Result res = TEE_SUCCESS; 885 struct tee_obj *o = NULL; 886 size_t pos_tmp = 0; 887 888 res = tee_ta_get_current_session(&sess); 889 if (res != TEE_SUCCESS) 890 goto exit; 891 utc = to_user_ta_ctx(sess->ctx); 892 893 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o); 894 if (res != TEE_SUCCESS) 895 goto exit; 896 897 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 898 res = TEE_ERROR_BAD_STATE; 899 goto exit; 900 } 901 902 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 903 res = TEE_ERROR_ACCESS_CONFLICT; 904 goto exit; 905 } 906 907 /* Guard o->info.dataPosition += bytes below from overflowing */ 908 if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { 909 res = TEE_ERROR_OVERFLOW; 910 goto exit; 911 } 912 913 /* check rights of the provided buffer */ 914 res = tee_mmu_check_access_rights(&utc->uctx, 915 TEE_MEMORY_ACCESS_READ | 916 TEE_MEMORY_ACCESS_ANY_OWNER, 917 (uaddr_t)data, len); 918 if (res != TEE_SUCCESS) 919 goto exit; 920 921 if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { 922 res = TEE_ERROR_ACCESS_CONFLICT; 923 goto exit; 924 } 925 res = o->pobj->fops->write(o->fh, pos_tmp, data, len); 926 if (res != TEE_SUCCESS) 927 goto exit; 928 929 o->info.dataPosition += len; 930 if (o->info.dataPosition > o->info.dataSize) 931 o->info.dataSize = o->info.dataPosition; 932 933 exit: 934 return res; 935 } 936 937 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 938 { 939 TEE_Result res; 940 struct tee_ta_session *sess; 941 struct tee_obj *o; 942 size_t off; 943 size_t attr_size; 944 945 res = tee_ta_get_current_session(&sess); 946 if (res != TEE_SUCCESS) 947 goto exit; 948 949 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 950 tee_svc_uref_to_vaddr(obj), &o); 951 if (res != TEE_SUCCESS) 952 goto exit; 953 954 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 955 res = TEE_ERROR_BAD_STATE; 956 goto exit; 957 } 958 959 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) { 960 res = TEE_ERROR_ACCESS_CONFLICT; 961 goto exit; 962 } 963 964 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 965 if (res != TEE_SUCCESS) 966 goto exit; 967 968 if (ADD_OVERFLOW(sizeof(struct tee_svc_storage_head), attr_size, 969 &off)) { 970 res = TEE_ERROR_OVERFLOW; 971 goto exit; 972 } 973 if (ADD_OVERFLOW(len, off, &off)) { 974 res = TEE_ERROR_OVERFLOW; 975 goto exit; 976 } 977 res = o->pobj->fops->truncate(o->fh, off); 978 switch (res) { 979 case TEE_SUCCESS: 980 o->info.dataSize = len; 981 break; 982 case TEE_ERROR_CORRUPT_OBJECT: 983 EMSG("Object corruption"); 984 (void)tee_svc_storage_remove_corrupt_obj(sess, o); 985 break; 986 default: 987 res = TEE_ERROR_GENERIC; 988 break; 989 } 990 991 exit: 992 return res; 993 } 994 995 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 996 unsigned long whence) 997 { 998 TEE_Result res; 999 struct tee_ta_session *sess; 1000 struct tee_obj *o; 1001 tee_fs_off_t new_pos; 1002 1003 res = tee_ta_get_current_session(&sess); 1004 if (res != TEE_SUCCESS) 1005 return res; 1006 1007 res = tee_obj_get(to_user_ta_ctx(sess->ctx), 1008 tee_svc_uref_to_vaddr(obj), &o); 1009 if (res != TEE_SUCCESS) 1010 return res; 1011 1012 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) 1013 return TEE_ERROR_BAD_STATE; 1014 1015 switch (whence) { 1016 case TEE_DATA_SEEK_SET: 1017 new_pos = offset; 1018 break; 1019 case TEE_DATA_SEEK_CUR: 1020 if (ADD_OVERFLOW(o->info.dataPosition, offset, &new_pos)) 1021 return TEE_ERROR_OVERFLOW; 1022 break; 1023 case TEE_DATA_SEEK_END: 1024 if (ADD_OVERFLOW(o->info.dataSize, offset, &new_pos)) 1025 return TEE_ERROR_OVERFLOW; 1026 break; 1027 default: 1028 return TEE_ERROR_BAD_PARAMETERS; 1029 } 1030 1031 if (new_pos < 0) 1032 new_pos = 0; 1033 1034 if (new_pos > TEE_DATA_MAX_POSITION) { 1035 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 1036 return TEE_ERROR_BAD_PARAMETERS; 1037 } 1038 1039 o->info.dataPosition = new_pos; 1040 1041 return TEE_SUCCESS; 1042 } 1043 1044 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 1045 { 1046 struct tee_storage_enum_head *eh = &utc->storage_enums; 1047 1048 /* disregard return value */ 1049 while (!TAILQ_EMPTY(eh)) 1050 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 1051 } 1052