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