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