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