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