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