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