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