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 <config.h> 8 #include <crypto/crypto.h> 9 #include <kernel/mutex.h> 10 #include <kernel/tee_misc.h> 11 #include <kernel/tee_ta_manager.h> 12 #include <kernel/ts_manager.h> 13 #include <kernel/user_access.h> 14 #include <mm/vm.h> 15 #include <string.h> 16 #include <tee_api_defines_extensions.h> 17 #include <tee_api_defines.h> 18 #include <tee/fs_dirfile.h> 19 #include <tee/tee_fs.h> 20 #include <tee/tee_obj.h> 21 #include <tee/tee_pobj.h> 22 #include <tee/tee_svc_cryp.h> 23 #include <tee/tee_svc.h> 24 #include <tee/tee_svc_storage.h> 25 #include <trace.h> 26 27 const struct tee_file_operations *tee_svc_storage_file_ops(uint32_t storage_id) 28 { 29 30 switch (storage_id) { 31 case TEE_STORAGE_PRIVATE: 32 #if defined(CFG_REE_FS) 33 return &ree_fs_ops; 34 #elif defined(CFG_RPMB_FS) 35 return &rpmb_fs_ops; 36 #else 37 #error At least one filesystem must be enabled. 38 #endif 39 #ifdef CFG_REE_FS 40 case TEE_STORAGE_PRIVATE_REE: 41 return &ree_fs_ops; 42 #endif 43 #ifdef CFG_RPMB_FS 44 case TEE_STORAGE_PRIVATE_RPMB: 45 return &rpmb_fs_ops; 46 #endif 47 default: 48 return NULL; 49 } 50 } 51 52 /* Header of GP formated secure storage files */ 53 struct tee_svc_storage_head { 54 uint32_t attr_size; 55 uint32_t keySize; 56 uint32_t maxKeySize; 57 uint32_t objectUsage; 58 uint32_t objectType; 59 uint32_t have_attrs; 60 }; 61 62 struct tee_storage_enum { 63 TAILQ_ENTRY(tee_storage_enum) link; 64 struct tee_fs_dir *dir; 65 const struct tee_file_operations *fops; 66 }; 67 68 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, 69 vaddr_t enum_id, 70 struct tee_storage_enum **e_out) 71 { 72 struct tee_storage_enum *e; 73 74 TAILQ_FOREACH(e, &utc->storage_enums, link) { 75 if (enum_id == (vaddr_t)e) { 76 *e_out = e; 77 return TEE_SUCCESS; 78 } 79 } 80 return TEE_ERROR_BAD_PARAMETERS; 81 } 82 83 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, 84 struct tee_storage_enum *e) 85 { 86 if (e == NULL || utc == NULL) 87 return TEE_ERROR_BAD_PARAMETERS; 88 89 TAILQ_REMOVE(&utc->storage_enums, e, link); 90 91 if (e->fops) 92 e->fops->closedir(e->dir); 93 94 e->dir = NULL; 95 e->fops = NULL; 96 97 free(e); 98 99 return TEE_SUCCESS; 100 } 101 102 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ 103 TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen, 104 struct tee_pobj *po, bool transient) 105 { 106 uint8_t *file = buf; 107 uint32_t pos = 0; 108 uint32_t hslen = 1 /* Leading slash */ 109 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) 110 + 1; /* Intermediate slash */ 111 112 /* +1 for the '.' (temporary persistent object) */ 113 if (transient) 114 hslen++; 115 116 if (blen < hslen) 117 return TEE_ERROR_SHORT_BUFFER; 118 119 file[pos++] = '/'; 120 pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], 121 sizeof(TEE_UUID), hslen); 122 file[pos++] = '/'; 123 124 if (transient) 125 file[pos++] = '.'; 126 127 tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); 128 129 return TEE_SUCCESS; 130 } 131 132 #ifdef CFG_REE_FS 133 /* "/dirf.db" or "/<file number>" */ 134 TEE_Result 135 tee_svc_storage_create_filename_dfh(void *buf, size_t blen, 136 const struct tee_fs_dirfile_fileh *dfh) 137 { 138 char *file = buf; 139 size_t pos = 0; 140 size_t l; 141 142 if (pos >= blen) 143 return TEE_ERROR_SHORT_BUFFER; 144 145 file[pos] = '/'; 146 pos++; 147 if (pos >= blen) 148 return TEE_ERROR_SHORT_BUFFER; 149 150 l = blen - pos; 151 return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l); 152 } 153 #endif 154 155 /* "/TA_uuid" */ 156 TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen, 157 const TEE_UUID *uuid) 158 { 159 uint8_t *dir = buf; 160 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; 161 162 if (blen < hslen) 163 return TEE_ERROR_SHORT_BUFFER; 164 165 dir[0] = '/'; 166 tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); 167 168 return TEE_SUCCESS; 169 } 170 171 static TEE_Result tee_svc_storage_remove_corrupt_obj(struct ts_session *sess, 172 struct tee_obj *o) 173 { 174 o->pobj->fops->remove(o->pobj); 175 tee_obj_close(to_user_ta_ctx(sess->ctx), o); 176 177 return TEE_SUCCESS; 178 } 179 180 static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) 181 { 182 TEE_Result res = TEE_SUCCESS; 183 size_t bytes; 184 struct tee_svc_storage_head head; 185 const struct tee_file_operations *fops = o->pobj->fops; 186 void *attr = NULL; 187 size_t size; 188 size_t tmp = 0; 189 190 assert(!o->fh); 191 res = fops->open(o->pobj, &size, &o->fh); 192 if (res != TEE_SUCCESS) 193 goto exit; 194 195 /* read head */ 196 bytes = sizeof(struct tee_svc_storage_head); 197 res = fops->read(o->fh, 0, &head, &bytes); 198 if (res != TEE_SUCCESS) { 199 if (res == TEE_ERROR_CORRUPT_OBJECT) 200 EMSG("Head corrupt"); 201 goto exit; 202 } 203 204 if (ADD_OVERFLOW(sizeof(head), head.attr_size, &tmp)) { 205 res = TEE_ERROR_OVERFLOW; 206 goto exit; 207 } 208 if (tmp > size) { 209 res = TEE_ERROR_CORRUPT_OBJECT; 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 = tmp; 223 224 if (head.attr_size) { 225 attr = malloc(head.attr_size); 226 if (!attr) { 227 res = TEE_ERROR_OUT_OF_MEMORY; 228 goto exit; 229 } 230 231 /* read meta */ 232 bytes = head.attr_size; 233 res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), 234 attr, &bytes); 235 if (res == TEE_ERROR_OUT_OF_MEMORY) 236 goto exit; 237 if (res != TEE_SUCCESS || bytes != head.attr_size) 238 res = TEE_ERROR_CORRUPT_OBJECT; 239 if (res) 240 goto exit; 241 } 242 243 res = tee_obj_attr_from_binary(o, attr, head.attr_size); 244 if (res != TEE_SUCCESS) 245 goto exit; 246 247 o->info.dataSize = size - sizeof(head) - head.attr_size; 248 o->info.keySize = head.keySize; 249 o->info.objectUsage = head.objectUsage; 250 o->info.objectType = head.objectType; 251 o->have_attrs = head.have_attrs; 252 253 exit: 254 free(attr); 255 256 return res; 257 } 258 259 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, 260 size_t object_id_len, unsigned long flags, 261 uint32_t *obj) 262 { 263 const unsigned long valid_flags = TEE_DATA_FLAG_ACCESS_READ | 264 TEE_DATA_FLAG_ACCESS_WRITE | 265 TEE_DATA_FLAG_ACCESS_WRITE_META | 266 TEE_DATA_FLAG_SHARE_READ | 267 TEE_DATA_FLAG_SHARE_WRITE; 268 const struct tee_file_operations *fops = 269 tee_svc_storage_file_ops(storage_id); 270 struct ts_session *sess = ts_get_current_session(); 271 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 272 TEE_Result res = TEE_SUCCESS; 273 struct tee_pobj *po = NULL; 274 struct tee_obj *o = NULL; 275 char *file = NULL; 276 277 if (flags & ~valid_flags) 278 return TEE_ERROR_BAD_PARAMETERS; 279 280 if (!fops) { 281 res = TEE_ERROR_ITEM_NOT_FOUND; 282 goto exit; 283 } 284 285 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { 286 res = TEE_ERROR_BAD_PARAMETERS; 287 goto exit; 288 } 289 290 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, 291 (uaddr_t)object_id, 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 = vm_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 = vm_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 uint8_t *data = NULL; 521 size_t len = 0; 522 523 res = tee_obj_get(utc, uref_to_vaddr(obj), &o); 524 if (res != TEE_SUCCESS) 525 return res; 526 527 if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 528 return TEE_ERROR_ACCESS_CONFLICT; 529 530 if (o->pobj == NULL || o->pobj->obj_id == NULL) 531 return TEE_ERROR_BAD_STATE; 532 533 if (IS_ENABLED(CFG_NXP_SE05X)) { 534 len = o->info.dataSize; 535 data = calloc(1, len); 536 if (!data) 537 return TEE_ERROR_OUT_OF_MEMORY; 538 539 res = o->pobj->fops->read(o->fh, o->info.dataPosition, 540 data, &len); 541 if (res == TEE_SUCCESS) 542 crypto_storage_obj_del(data, len); 543 free(data); 544 } 545 546 res = o->pobj->fops->remove(o->pobj); 547 tee_obj_close(utc, o); 548 549 return res; 550 } 551 552 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, 553 size_t object_id_len) 554 { 555 const struct tee_file_operations *fops = NULL; 556 struct ts_session *sess = ts_get_current_session(); 557 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 558 TEE_Result res = TEE_SUCCESS; 559 struct tee_pobj *po = NULL; 560 struct tee_obj *o = NULL; 561 char *new_file = NULL; 562 char *old_file = NULL; 563 564 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 565 return TEE_ERROR_BAD_PARAMETERS; 566 567 res = tee_obj_get(utc, uref_to_vaddr(obj), &o); 568 if (res != TEE_SUCCESS) 569 return res; 570 571 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 572 res = TEE_ERROR_BAD_STATE; 573 goto exit; 574 } 575 576 if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 577 res = TEE_ERROR_BAD_STATE; 578 goto exit; 579 } 580 581 if (o->pobj == NULL || o->pobj->obj_id == NULL) { 582 res = TEE_ERROR_BAD_STATE; 583 goto exit; 584 } 585 586 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, 587 (uaddr_t)object_id, object_id_len); 588 if (res != TEE_SUCCESS) 589 goto exit; 590 591 /* reserve dest name */ 592 fops = o->pobj->fops; 593 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, 594 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, 595 TEE_POBJ_USAGE_RENAME, fops, &po); 596 if (res != TEE_SUCCESS) 597 goto exit; 598 599 /* move */ 600 res = fops->rename(o->pobj, po, false /* no overwrite */); 601 if (res) 602 goto exit; 603 604 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 605 606 exit: 607 tee_pobj_release(po); 608 609 free(new_file); 610 free(old_file); 611 612 return res; 613 } 614 615 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) 616 { 617 struct ts_session *sess = ts_get_current_session(); 618 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 619 struct tee_storage_enum *e = NULL; 620 621 if (obj_enum == NULL) 622 return TEE_ERROR_BAD_PARAMETERS; 623 624 e = malloc(sizeof(struct tee_storage_enum)); 625 if (e == NULL) 626 return TEE_ERROR_OUT_OF_MEMORY; 627 628 e->dir = NULL; 629 e->fops = NULL; 630 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); 631 632 return copy_kaddr_to_uref(obj_enum, e); 633 } 634 635 TEE_Result syscall_storage_free_enum(unsigned long obj_enum) 636 { 637 struct ts_session *sess = ts_get_current_session(); 638 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 639 struct tee_storage_enum *e = NULL; 640 TEE_Result res = TEE_SUCCESS; 641 642 res = tee_svc_storage_get_enum(utc, 643 uref_to_vaddr(obj_enum), &e); 644 if (res != TEE_SUCCESS) 645 return res; 646 647 return tee_svc_close_enum(utc, e); 648 } 649 650 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) 651 { 652 struct ts_session *sess = ts_get_current_session(); 653 struct tee_storage_enum *e = NULL; 654 TEE_Result res = TEE_SUCCESS; 655 656 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 657 uref_to_vaddr(obj_enum), &e); 658 if (res != TEE_SUCCESS) 659 return res; 660 661 if (e->fops) { 662 e->fops->closedir(e->dir); 663 e->fops = NULL; 664 e->dir = NULL; 665 } 666 assert(!e->dir); 667 668 return TEE_SUCCESS; 669 } 670 671 TEE_Result syscall_storage_start_enum(unsigned long obj_enum, 672 unsigned long storage_id) 673 { 674 struct ts_session *sess = ts_get_current_session(); 675 struct tee_storage_enum *e = NULL; 676 TEE_Result res = TEE_SUCCESS; 677 const struct tee_file_operations *fops = 678 tee_svc_storage_file_ops(storage_id); 679 680 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), 681 uref_to_vaddr(obj_enum), &e); 682 if (res != TEE_SUCCESS) 683 return res; 684 685 if (e->dir) { 686 e->fops->closedir(e->dir); 687 e->dir = NULL; 688 } 689 690 if (!fops) 691 return TEE_ERROR_ITEM_NOT_FOUND; 692 693 e->fops = fops; 694 695 return fops->opendir(&sess->ctx->uuid, &e->dir); 696 } 697 698 TEE_Result syscall_storage_next_enum(unsigned long obj_enum, 699 TEE_ObjectInfo *info, void *obj_id, uint64_t *len) 700 { 701 struct ts_session *sess = ts_get_current_session(); 702 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 703 struct tee_storage_enum *e = NULL; 704 struct tee_fs_dirent *d = NULL; 705 TEE_Result res = TEE_SUCCESS; 706 struct tee_obj *o = NULL; 707 uint64_t l = 0; 708 709 res = tee_svc_storage_get_enum(utc, uref_to_vaddr(obj_enum), &e); 710 if (res != TEE_SUCCESS) 711 goto exit; 712 713 /* check rights of the provided buffers */ 714 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, 715 (uaddr_t)info, sizeof(TEE_ObjectInfo)); 716 if (res != TEE_SUCCESS) 717 goto exit; 718 719 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, 720 (uaddr_t)obj_id, TEE_OBJECT_ID_MAX_LEN); 721 if (res != TEE_SUCCESS) 722 goto exit; 723 724 if (!e->fops) { 725 res = TEE_ERROR_ITEM_NOT_FOUND; 726 goto exit; 727 } 728 729 res = e->fops->readdir(e->dir, &d); 730 if (res != TEE_SUCCESS) 731 goto exit; 732 733 o = tee_obj_alloc(); 734 if (o == NULL) { 735 res = TEE_ERROR_OUT_OF_MEMORY; 736 goto exit; 737 } 738 739 res = tee_pobj_get(&sess->ctx->uuid, d->oid, d->oidlen, 0, 740 TEE_POBJ_USAGE_ENUM, e->fops, &o->pobj); 741 if (res) 742 goto exit; 743 744 o->info.handleFlags = o->pobj->flags | TEE_HANDLE_FLAG_PERSISTENT | 745 TEE_HANDLE_FLAG_INITIALIZED; 746 747 res = tee_svc_storage_read_head(o); 748 if (res != TEE_SUCCESS) 749 goto exit; 750 751 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 752 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 753 754 l = o->pobj->obj_id_len; 755 res = copy_to_user_private(len, &l, sizeof(*len)); 756 757 exit: 758 if (o) { 759 tee_pobj_release(o->pobj); 760 tee_obj_free(o); 761 } 762 763 return res; 764 } 765 766 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, 767 uint64_t *count) 768 { 769 struct ts_session *sess = ts_get_current_session(); 770 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 771 TEE_Result res = TEE_SUCCESS; 772 struct tee_obj *o = NULL; 773 uint64_t u_count = 0; 774 size_t pos_tmp = 0; 775 size_t bytes = 0; 776 777 res = tee_obj_get(utc, uref_to_vaddr(obj), &o); 778 if (res != TEE_SUCCESS) 779 goto exit; 780 781 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 782 res = TEE_ERROR_BAD_STATE; 783 goto exit; 784 } 785 786 if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_READ)) { 787 res = TEE_ERROR_ACCESS_CONFLICT; 788 goto exit; 789 } 790 791 /* Guard o->info.dataPosition += bytes below from overflowing */ 792 if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { 793 res = TEE_ERROR_OVERFLOW; 794 goto exit; 795 } 796 797 /* check rights of the provided buffer */ 798 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, 799 (uaddr_t)data, len); 800 if (res != TEE_SUCCESS) 801 goto exit; 802 803 bytes = len; 804 if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { 805 res = TEE_ERROR_OVERFLOW; 806 goto exit; 807 } 808 res = o->pobj->fops->read(o->fh, pos_tmp, data, &bytes); 809 if (res != TEE_SUCCESS) { 810 if (res == TEE_ERROR_CORRUPT_OBJECT) { 811 EMSG("Object corrupt"); 812 tee_svc_storage_remove_corrupt_obj(sess, o); 813 } 814 goto exit; 815 } 816 817 o->info.dataPosition += bytes; 818 819 u_count = bytes; 820 res = copy_to_user_private(count, &u_count, sizeof(*count)); 821 exit: 822 return res; 823 } 824 825 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) 826 { 827 struct ts_session *sess = ts_get_current_session(); 828 struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 829 TEE_Result res = TEE_SUCCESS; 830 struct tee_obj *o = NULL; 831 size_t pos_tmp = 0; 832 833 res = tee_obj_get(utc, uref_to_vaddr(obj), &o); 834 if (res != TEE_SUCCESS) 835 goto exit; 836 837 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 838 res = TEE_ERROR_BAD_STATE; 839 goto exit; 840 } 841 842 if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { 843 res = TEE_ERROR_ACCESS_CONFLICT; 844 goto exit; 845 } 846 847 /* Guard o->info.dataPosition += bytes below from overflowing */ 848 if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { 849 res = TEE_ERROR_OVERFLOW; 850 goto exit; 851 } 852 853 /* check rights of the provided buffer */ 854 res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, 855 (uaddr_t)data, len); 856 if (res != TEE_SUCCESS) 857 goto exit; 858 859 if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { 860 res = TEE_ERROR_ACCESS_CONFLICT; 861 goto exit; 862 } 863 res = o->pobj->fops->write(o->fh, pos_tmp, data, len); 864 if (res != TEE_SUCCESS) 865 goto exit; 866 867 o->info.dataPosition += len; 868 if (o->info.dataPosition > o->info.dataSize) 869 o->info.dataSize = o->info.dataPosition; 870 871 exit: 872 return res; 873 } 874 875 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) 876 { 877 struct ts_session *sess = ts_get_current_session(); 878 TEE_Result res = TEE_SUCCESS; 879 struct tee_obj *o = NULL; 880 size_t off = 0; 881 size_t attr_size = 0; 882 883 res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); 884 if (res != TEE_SUCCESS) 885 goto exit; 886 887 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { 888 res = TEE_ERROR_BAD_STATE; 889 goto exit; 890 } 891 892 if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { 893 res = TEE_ERROR_ACCESS_CONFLICT; 894 goto exit; 895 } 896 897 res = tee_obj_attr_to_binary(o, NULL, &attr_size); 898 if (res != TEE_SUCCESS) 899 goto exit; 900 901 if (ADD_OVERFLOW(sizeof(struct tee_svc_storage_head), attr_size, 902 &off)) { 903 res = TEE_ERROR_OVERFLOW; 904 goto exit; 905 } 906 if (ADD_OVERFLOW(len, off, &off)) { 907 res = TEE_ERROR_OVERFLOW; 908 goto exit; 909 } 910 res = o->pobj->fops->truncate(o->fh, off); 911 switch (res) { 912 case TEE_SUCCESS: 913 o->info.dataSize = len; 914 break; 915 case TEE_ERROR_CORRUPT_OBJECT: 916 EMSG("Object corruption"); 917 (void)tee_svc_storage_remove_corrupt_obj(sess, o); 918 break; 919 default: 920 res = TEE_ERROR_GENERIC; 921 break; 922 } 923 924 exit: 925 return res; 926 } 927 928 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, 929 unsigned long whence) 930 { 931 struct ts_session *sess = ts_get_current_session(); 932 TEE_Result res = TEE_SUCCESS; 933 struct tee_obj *o = NULL; 934 tee_fs_off_t new_pos = 0; 935 936 res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); 937 if (res != TEE_SUCCESS) 938 return res; 939 940 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) 941 return TEE_ERROR_BAD_STATE; 942 943 switch (whence) { 944 case TEE_DATA_SEEK_SET: 945 new_pos = offset; 946 break; 947 case TEE_DATA_SEEK_CUR: 948 if (ADD_OVERFLOW(o->info.dataPosition, offset, &new_pos)) 949 return TEE_ERROR_OVERFLOW; 950 break; 951 case TEE_DATA_SEEK_END: 952 if (ADD_OVERFLOW(o->info.dataSize, offset, &new_pos)) 953 return TEE_ERROR_OVERFLOW; 954 break; 955 default: 956 return TEE_ERROR_BAD_PARAMETERS; 957 } 958 959 if (new_pos < 0) 960 new_pos = 0; 961 962 if (new_pos > TEE_DATA_MAX_POSITION) { 963 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 964 return TEE_ERROR_BAD_PARAMETERS; 965 } 966 967 o->info.dataPosition = new_pos; 968 969 return TEE_SUCCESS; 970 } 971 972 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) 973 { 974 struct tee_storage_enum_head *eh = &utc->storage_enums; 975 976 /* disregard return value */ 977 while (!TAILQ_EMPTY(eh)) 978 tee_svc_close_enum(utc, TAILQ_FIRST(eh)); 979 } 980