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