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