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