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