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