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