1 /* 2 * Copyright (c) 2015, Linaro Limited 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <assert.h> 29 #include <kernel/tee_common_unpg.h> 30 #include <kernel/thread.h> 31 #include <kernel/handle.h> 32 #include <kernel/mutex.h> 33 #include <mm/core_memprot.h> 34 #include <optee_msg.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <string_ext.h> 39 #include <sys/queue.h> 40 #include <tee/tee_cryp_provider.h> 41 #include <tee/tee_fs.h> 42 #include <tee/tee_fs_defs.h> 43 #include <tee/tee_fs_key_manager.h> 44 #include <trace.h> 45 #include <utee_defines.h> 46 #include <util.h> 47 48 /* TEE FS operation */ 49 #define TEE_FS_OPEN 1 50 #define TEE_FS_CLOSE 2 51 #define TEE_FS_READ 3 52 #define TEE_FS_WRITE 4 53 #define TEE_FS_SEEK 5 54 #define TEE_FS_UNLINK 6 55 #define TEE_FS_RENAME 7 56 #define TEE_FS_TRUNC 8 57 #define TEE_FS_MKDIR 9 58 #define TEE_FS_OPENDIR 10 59 #define TEE_FS_CLOSEDIR 11 60 #define TEE_FS_READDIR 12 61 #define TEE_FS_RMDIR 13 62 #define TEE_FS_ACCESS 14 63 #define TEE_FS_LINK 15 64 65 #define BLOCK_FILE_SHIFT 12 66 67 #define BLOCK_FILE_SIZE (1 << BLOCK_FILE_SHIFT) 68 69 #define MAX_NUM_CACHED_BLOCKS 1 70 71 #define NUM_BLOCKS_PER_FILE 1024 72 73 #define MAX_FILE_SIZE (BLOCK_FILE_SIZE * NUM_BLOCKS_PER_FILE) 74 75 struct tee_fs_file_info { 76 size_t length; 77 uint32_t backup_version_table[NUM_BLOCKS_PER_FILE / 32]; 78 }; 79 80 struct tee_fs_file_meta { 81 struct tee_fs_file_info info; 82 uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE]; 83 uint8_t backup_version; 84 }; 85 86 TAILQ_HEAD(block_head, block); 87 88 struct block { 89 TAILQ_ENTRY(block) list; 90 int block_num; 91 uint8_t *data; 92 size_t data_size; 93 }; 94 95 struct block_cache { 96 struct block_head block_lru; 97 uint8_t cached_block_num; 98 }; 99 100 struct tee_fs_fd { 101 struct tee_fs_file_meta *meta; 102 int pos; 103 uint32_t flags; 104 int fd; 105 bool is_new_file; 106 char *filename; 107 struct block_cache block_cache; 108 }; 109 110 struct tee_fs_dir { 111 int nw_dir; 112 struct tee_fs_dirent d; 113 }; 114 115 static inline int pos_to_block_num(int position) 116 { 117 return position >> BLOCK_FILE_SHIFT; 118 } 119 120 static inline int get_last_block_num(size_t size) 121 { 122 return pos_to_block_num(size - 1); 123 } 124 125 static inline uint8_t get_backup_version_of_block( 126 struct tee_fs_file_meta *meta, 127 size_t block_num) 128 { 129 uint32_t index = (block_num / 32); 130 uint32_t block_mask = 1 << (block_num % 32); 131 132 return !!(meta->info.backup_version_table[index] & block_mask); 133 } 134 135 static inline void toggle_backup_version_of_block( 136 struct tee_fs_file_meta *meta, 137 size_t block_num) 138 { 139 uint32_t index = (block_num / 32); 140 uint32_t block_mask = 1 << (block_num % 32); 141 142 meta->info.backup_version_table[index] ^= block_mask; 143 } 144 145 struct block_operations { 146 147 /* 148 * Read a block from REE File System which is corresponding 149 * to the given block_num. 150 */ 151 struct block *(*read)(struct tee_fs_fd *fdp, int block_num); 152 153 /* 154 * Write the given block to REE File System 155 */ 156 int (*write)(struct tee_fs_fd *fdp, struct block *b, 157 struct tee_fs_file_meta *new_meta); 158 }; 159 160 static struct handle_db fs_handle_db = HANDLE_DB_INITIALIZER; 161 162 struct tee_fs_rpc { 163 int op; 164 int flags; 165 int arg; 166 int fd; 167 uint32_t len; 168 int res; 169 }; 170 171 static int tee_fs_send_cmd(struct tee_fs_rpc *bf_cmd, void *data, uint32_t len, 172 uint32_t mode) 173 { 174 TEE_Result ret; 175 struct optee_msg_param params; 176 paddr_t phpayload = 0; 177 uint64_t cpayload = 0; 178 struct tee_fs_rpc *bf; 179 int res = -1; 180 181 thread_rpc_alloc_payload(sizeof(struct tee_fs_rpc) + len, 182 &phpayload, &cpayload); 183 if (!phpayload) 184 return -1; 185 186 if (!ALIGNMENT_IS_OK(phpayload, struct tee_fs_rpc)) 187 goto exit; 188 189 bf = phys_to_virt(phpayload, MEM_AREA_NSEC_SHM); 190 if (!bf) 191 goto exit; 192 193 memset(¶ms, 0, sizeof(params)); 194 params.attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT; 195 params.u.tmem.buf_ptr = phpayload; 196 params.u.tmem.size = sizeof(struct tee_fs_rpc) + len; 197 params.u.tmem.shm_ref = cpayload; 198 199 /* fill in parameters */ 200 *bf = *bf_cmd; 201 202 if (mode & TEE_FS_MODE_IN) 203 memcpy((void *)(bf + 1), data, len); 204 205 ret = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_FS, 1, ¶ms); 206 /* update result */ 207 *bf_cmd = *bf; 208 if (ret != TEE_SUCCESS) 209 goto exit; 210 211 if (mode & TEE_FS_MODE_OUT) { 212 uint32_t olen = MIN(len, bf->len); 213 214 memcpy(data, (void *)(bf + 1), olen); 215 } 216 217 res = 0; 218 219 exit: 220 thread_rpc_free_payload(cpayload); 221 return res; 222 } 223 224 /* 225 * We split a TEE file into multiple blocks and store them 226 * on REE filesystem. A TEE file is represented by a REE file 227 * called meta and a number of REE files called blocks. Meta 228 * file is used for storing file information, e.g. file size 229 * and backup version of each block. 230 * 231 * REE files naming rule is as follows: 232 * 233 * <tee_file_name>/meta.<backup_version> 234 * <tee_file_name>/block0.<backup_version> 235 * ... 236 * <tee_file_name>/block15.<backup_version> 237 * 238 * Backup_version is used to support atomic update operation. 239 * Original file will not be updated, instead we create a new 240 * version of the same file and update the new file instead. 241 * 242 * The backup_version of each block file is stored in meta 243 * file, the meta file itself also has backup_version, the update is 244 * successful after new version of meta has been written. 245 */ 246 #define REE_FS_NAME_MAX (TEE_FS_NAME_MAX + 20) 247 248 static int ree_fs_open_ree(const char *file, int flags, ...) 249 { 250 int res = -1; 251 struct tee_fs_rpc head = { 0 }; 252 size_t len; 253 254 len = strlen(file) + 1; 255 if (len > REE_FS_NAME_MAX) 256 goto exit; 257 258 /* fill in parameters */ 259 head.op = TEE_FS_OPEN; 260 head.flags = flags; 261 head.fd = 0; 262 263 res = tee_fs_send_cmd(&head, (void *)file, len, TEE_FS_MODE_IN); 264 if (!res) 265 res = head.res; 266 267 exit: 268 return res; 269 } 270 271 static int ree_fs_read_ree(int fd, void *buf, size_t len) 272 { 273 int res = -1; 274 struct tee_fs_rpc head = { 0 }; 275 276 if (!len) { 277 res = 0; 278 goto exit; 279 } 280 281 if (!buf) 282 goto exit; 283 284 /* fill in parameters */ 285 head.op = TEE_FS_READ; 286 head.fd = fd; 287 head.len = (uint32_t) len; 288 289 res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_OUT); 290 if (!res) 291 res = head.res; 292 exit: 293 return res; 294 } 295 296 static int ree_fs_write_ree(int fd, 297 const void *buf, size_t len) 298 { 299 int res = -1; 300 struct tee_fs_rpc head = { 0 }; 301 302 if (!len) { 303 res = 0; 304 goto exit; 305 } 306 307 if (!buf) 308 goto exit; 309 310 /* fill in parameters */ 311 head.op = TEE_FS_WRITE; 312 head.fd = fd; 313 head.len = (uint32_t) len; 314 315 res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_IN); 316 if (!res) 317 res = head.res; 318 exit: 319 return res; 320 } 321 322 static int ree_fs_ftruncate_ree(int fd, tee_fs_off_t length) 323 { 324 int res = -1; 325 struct tee_fs_rpc head = { 0 }; 326 327 head.op = TEE_FS_TRUNC; 328 head.fd = fd; 329 head.arg = length; 330 331 res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); 332 if (!res) 333 res = head.res; 334 335 return res; 336 } 337 338 static int ree_fs_close_ree(int fd) 339 { 340 int res = -1; 341 struct tee_fs_rpc head = { 0 }; 342 343 /* fill in parameters */ 344 head.op = TEE_FS_CLOSE; 345 head.fd = fd; 346 347 res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); 348 if (!res) 349 res = head.res; 350 351 return res; 352 } 353 354 static tee_fs_off_t ree_fs_lseek_ree(int fd, tee_fs_off_t offset, int whence) 355 { 356 tee_fs_off_t res = -1; 357 struct tee_fs_rpc head = { 0 }; 358 359 /* fill in parameters */ 360 head.op = TEE_FS_SEEK; 361 head.fd = fd; 362 head.arg = offset; 363 head.flags = whence; 364 365 res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); 366 if (!res) 367 res = head.res; 368 369 return res; 370 } 371 372 static int ree_fs_mkdir_ree(const char *path, tee_fs_mode_t mode) 373 { 374 int res = -1; 375 struct tee_fs_rpc head = { 0 }; 376 uint32_t len; 377 378 if (!path) 379 return -1; 380 381 len = strlen(path) + 1; 382 if (len > REE_FS_NAME_MAX) 383 goto exit; 384 385 head.op = TEE_FS_MKDIR; 386 head.flags = mode; 387 388 res = tee_fs_send_cmd(&head, (void *)path, len, TEE_FS_MODE_IN); 389 if (!res) 390 res = head.res; 391 392 exit: 393 return res; 394 } 395 396 static struct tee_fs_dir *ree_fs_opendir_ree(const char *name) 397 { 398 struct tee_fs_rpc head = { 0 }; 399 uint32_t len; 400 struct tee_fs_dir *dir = NULL; 401 402 if (!name) 403 goto exit; 404 405 len = strlen(name) + 1; 406 if (len > TEE_FS_NAME_MAX) 407 goto exit; 408 409 head.op = TEE_FS_OPENDIR; 410 411 if (tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN)) 412 goto exit; 413 414 if (head.res < 0) 415 goto exit; 416 417 dir = malloc(sizeof(struct tee_fs_dir)); 418 if (!dir) { 419 int nw_dir = head.res; 420 421 memset(&head, 0, sizeof(head)); 422 head.op = TEE_FS_CLOSEDIR; 423 head.arg = nw_dir; 424 tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); 425 goto exit; 426 } 427 428 dir->nw_dir = head.res; 429 dir->d.d_name = NULL; 430 431 exit: 432 return dir; 433 } 434 435 static int ree_fs_closedir_ree(struct tee_fs_dir *d) 436 { 437 int res = -1; 438 struct tee_fs_rpc head = { 0 }; 439 440 if (!d) { 441 res = 0; 442 goto exit; 443 } 444 445 head.op = TEE_FS_CLOSEDIR; 446 head.arg = (int)d->nw_dir; 447 448 res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); 449 if (!res) 450 res = head.res; 451 452 exit: 453 if (d) 454 free(d->d.d_name); 455 free(d); 456 457 return res; 458 } 459 460 static struct tee_fs_dirent *ree_fs_readdir_ree(struct tee_fs_dir *d) 461 { 462 struct tee_fs_dirent *res = NULL; 463 struct tee_fs_rpc head = { 0 }; 464 char fname[TEE_FS_NAME_MAX + 1]; 465 466 if (!d) 467 goto exit; 468 469 head.op = TEE_FS_READDIR; 470 head.arg = (int)d->nw_dir; 471 472 if (tee_fs_send_cmd(&head, fname, sizeof(fname), TEE_FS_MODE_OUT)) 473 goto exit; 474 475 if (head.res < 0) 476 goto exit; 477 478 if (!head.len || head.len > sizeof(fname)) 479 goto exit; 480 481 fname[head.len - 1] = '\0'; /* make sure it's zero terminated */ 482 free(d->d.d_name); 483 d->d.d_name = strdup(fname); 484 if (!d->d.d_name) 485 goto exit; 486 487 res = &d->d; 488 exit: 489 return res; 490 } 491 492 static int ree_fs_rmdir_ree(const char *name) 493 { 494 int res = -1; 495 struct tee_fs_rpc head = { 0 }; 496 uint32_t len; 497 498 len = strlen(name) + 1; 499 if (len > REE_FS_NAME_MAX) 500 goto exit; 501 502 head.op = TEE_FS_RMDIR; 503 504 res = tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN); 505 if (!res) 506 res = head.res; 507 508 exit: 509 return res; 510 } 511 512 static int ree_fs_link_ree(const char *old, const char *new) 513 { 514 int res = -1; 515 char *tmp = NULL; 516 struct tee_fs_rpc head = { 0 }; 517 size_t len_old = strlen(old) + 1; 518 size_t len_new = strlen(new) + 1; 519 size_t len = len_old + len_new; 520 521 if (len_old > REE_FS_NAME_MAX || len_new > REE_FS_NAME_MAX) 522 goto exit; 523 524 tmp = malloc(len); 525 if (!tmp) 526 goto exit; 527 memcpy(tmp, old, len_old); 528 memcpy(tmp + len_old, new, len_new); 529 530 head.op = TEE_FS_LINK; 531 532 res = tee_fs_send_cmd(&head, tmp, len, TEE_FS_MODE_IN); 533 if (!res) 534 res = head.res; 535 536 exit: 537 free(tmp); 538 return res; 539 } 540 541 static int ree_fs_unlink_ree(const char *file) 542 { 543 int res = -1; 544 struct tee_fs_rpc head = { 0 }; 545 size_t len = strlen(file) + 1; 546 547 if (len > REE_FS_NAME_MAX) 548 goto exit; 549 550 head.op = TEE_FS_UNLINK; 551 552 res = tee_fs_send_cmd(&head, (void *)file, len, TEE_FS_MODE_IN); 553 if (!res) 554 res = head.res; 555 exit: 556 return res; 557 } 558 559 static int ree_fs_access_ree(const char *name, int mode) 560 { 561 int res = -1; 562 struct tee_fs_rpc head = { 0 }; 563 uint32_t len; 564 565 if (!name) 566 goto exit; 567 568 len = strlen(name) + 1; 569 if (len > TEE_FS_NAME_MAX) 570 goto exit; 571 572 head.op = TEE_FS_ACCESS; 573 head.flags = mode; 574 575 res = tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN); 576 if (!res) 577 res = head.res; 578 579 exit: 580 return res; 581 } 582 583 static int get_file_length(int fd, size_t *length) 584 { 585 size_t file_len; 586 int res; 587 588 TEE_ASSERT(length); 589 590 *length = 0; 591 592 res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_END); 593 if (res < 0) 594 return res; 595 596 file_len = res; 597 598 res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_SET); 599 if (res < 0) 600 return res; 601 602 *length = file_len; 603 return 0; 604 } 605 606 static void get_meta_filepath(const char *file, int version, 607 char *meta_path) 608 { 609 snprintf(meta_path, REE_FS_NAME_MAX, "%s/meta.%d", 610 file, version); 611 } 612 613 static void get_block_filepath(const char *file, size_t block_num, 614 int version, char *meta_path) 615 { 616 snprintf(meta_path, REE_FS_NAME_MAX, "%s/block%zu.%d", 617 file, block_num, version); 618 } 619 620 static int create_block_file(struct tee_fs_fd *fdp, 621 struct tee_fs_file_meta *new_meta, int block_num) 622 { 623 int fd; 624 int res = -1; 625 char block_path[REE_FS_NAME_MAX]; 626 uint8_t new_version = 627 !get_backup_version_of_block(fdp->meta, block_num); 628 629 get_block_filepath(fdp->filename, block_num, new_version, 630 block_path); 631 632 fd = ree_fs_open_ree(block_path, TEE_FS_O_CREATE | TEE_FS_O_RDWR); 633 if (fd < 0) 634 goto exit; 635 636 res = ree_fs_ftruncate_ree(fd, 0); 637 if (res < 0) 638 goto exit; 639 640 /* 641 * toggle block version in new meta to indicate 642 * we are currently working on new block file 643 */ 644 toggle_backup_version_of_block(new_meta, block_num); 645 res = fd; 646 647 exit: 648 return res; 649 } 650 651 static int __remove_block_file(struct tee_fs_fd *fdp, size_t block_num, 652 bool toggle) 653 { 654 char block_path[REE_FS_NAME_MAX]; 655 uint8_t version = 656 get_backup_version_of_block(fdp->meta, block_num); 657 658 if (toggle) 659 version = !version; 660 661 get_block_filepath(fdp->filename, block_num, version, block_path); 662 DMSG("%s", block_path); 663 664 /* ignore it if file not found */ 665 if (ree_fs_access_ree(block_path, TEE_FS_F_OK)) 666 return 0; 667 668 return ree_fs_unlink_ree(block_path); 669 } 670 671 static int remove_block_file(struct tee_fs_fd *fdp, size_t block_num) 672 { 673 DMSG("remove block%zd", block_num); 674 return __remove_block_file(fdp, block_num, false); 675 } 676 677 static int remove_outdated_block(struct tee_fs_fd *fdp, size_t block_num) 678 { 679 DMSG("remove outdated block%zd", block_num); 680 return __remove_block_file(fdp, block_num, true); 681 } 682 683 /* 684 * encrypted_fek: as input for META_FILE and BLOCK_FILE 685 */ 686 static int encrypt_and_write_file(int fd, 687 enum tee_fs_file_type file_type, 688 void *data_in, size_t data_in_size, 689 uint8_t *encrypted_fek) 690 { 691 TEE_Result tee_res; 692 int res = 0; 693 int bytes; 694 uint8_t *ciphertext; 695 size_t header_size = tee_fs_get_header_size(file_type); 696 size_t ciphertext_size = header_size + data_in_size; 697 698 ciphertext = malloc(ciphertext_size); 699 if (!ciphertext) { 700 EMSG("Failed to allocate ciphertext buffer, size=%zd", 701 ciphertext_size); 702 return -1; 703 } 704 705 tee_res = tee_fs_encrypt_file(file_type, 706 data_in, data_in_size, 707 ciphertext, &ciphertext_size, encrypted_fek); 708 if (tee_res != TEE_SUCCESS) { 709 EMSG("error code=%x", tee_res); 710 res = -1; 711 goto fail; 712 } 713 714 bytes = ree_fs_write_ree(fd, ciphertext, ciphertext_size); 715 if (bytes != (int)ciphertext_size) { 716 EMSG("bytes(%d) != ciphertext size(%zu)", 717 bytes, ciphertext_size); 718 res = -1; 719 goto fail; 720 } 721 722 fail: 723 free(ciphertext); 724 725 return res; 726 } 727 728 /* 729 * encrypted_fek: as output for META_FILE 730 * as input for BLOCK_FILE 731 */ 732 static int read_and_decrypt_file(int fd, 733 enum tee_fs_file_type file_type, 734 void *data_out, size_t *data_out_size, 735 uint8_t *encrypted_fek) 736 { 737 TEE_Result tee_res; 738 int res; 739 int bytes; 740 void *ciphertext = NULL; 741 size_t file_size; 742 size_t header_size = tee_fs_get_header_size(file_type); 743 744 res = get_file_length(fd, &file_size); 745 if (res < 0) 746 return res; 747 748 TEE_ASSERT(file_size >= header_size); 749 750 ciphertext = malloc(file_size); 751 if (!ciphertext) { 752 EMSG("Failed to allocate file data buffer, size=%zd", 753 file_size); 754 return -1; 755 } 756 757 bytes = ree_fs_read_ree(fd, ciphertext, file_size); 758 if (bytes != (int)file_size) { 759 EMSG("return bytes(%d) != file_size(%zd)", 760 bytes, file_size); 761 res = -1; 762 goto fail; 763 } 764 765 tee_res = tee_fs_decrypt_file(file_type, 766 ciphertext, file_size, 767 data_out, data_out_size, 768 encrypted_fek); 769 if (tee_res != TEE_SUCCESS) { 770 EMSG("Failed to decrypt file, res=0x%x", tee_res); 771 res = -1; 772 } 773 774 fail: 775 free(ciphertext); 776 777 return (res < 0) ? res : 0; 778 } 779 780 static struct tee_fs_file_meta *duplicate_meta( 781 struct tee_fs_fd *fdp) 782 { 783 struct tee_fs_file_meta *new_meta = NULL; 784 785 new_meta = malloc(sizeof(*new_meta)); 786 if (!new_meta) { 787 EMSG("Failed to allocate memory for new meta"); 788 goto exit; 789 } 790 791 memcpy(new_meta, fdp->meta, sizeof(*new_meta)); 792 793 exit: 794 return new_meta; 795 } 796 797 static int write_meta_file(const char *filename, 798 struct tee_fs_file_meta *meta) 799 { 800 int res, fd = -1; 801 char meta_path[REE_FS_NAME_MAX]; 802 803 get_meta_filepath(filename, meta->backup_version, meta_path); 804 805 fd = ree_fs_open_ree(meta_path, TEE_FS_O_CREATE | 806 TEE_FS_O_TRUNC | TEE_FS_O_WRONLY); 807 if (fd < 0) 808 return -1; 809 810 res = encrypt_and_write_file(fd, META_FILE, 811 (void *)&meta->info, sizeof(meta->info), 812 meta->encrypted_fek); 813 814 ree_fs_close_ree(fd); 815 return res; 816 } 817 818 static struct tee_fs_file_meta *create_meta_file(const char *file) 819 { 820 TEE_Result tee_res; 821 struct tee_fs_file_meta *meta = NULL; 822 int res; 823 const uint8_t default_backup_version = 0; 824 825 meta = malloc(sizeof(struct tee_fs_file_meta)); 826 if (!meta) { 827 EMSG("Failed to allocate memory"); 828 goto exit; 829 } 830 831 memset(&meta->info.backup_version_table, 0xff, 832 sizeof(meta->info.backup_version_table)); 833 meta->info.length = 0; 834 835 tee_res = tee_fs_generate_fek(meta->encrypted_fek, TEE_FS_KM_FEK_SIZE); 836 if (tee_res != TEE_SUCCESS) 837 goto exit; 838 839 meta->backup_version = default_backup_version; 840 841 res = write_meta_file(file, meta); 842 if (res < 0) 843 goto exit; 844 845 return meta; 846 847 exit: 848 free(meta); 849 850 return NULL; 851 } 852 853 static int commit_meta_file(struct tee_fs_fd *fdp, 854 struct tee_fs_file_meta *new_meta) 855 { 856 int res; 857 uint8_t old_version; 858 char meta_path[REE_FS_NAME_MAX]; 859 860 old_version = new_meta->backup_version; 861 new_meta->backup_version = !new_meta->backup_version; 862 863 res = write_meta_file(fdp->filename, new_meta); 864 865 if (res < 0) 866 return res; 867 868 /* 869 * From now on the new meta is successfully committed, 870 * change tee_fs_fd accordingly 871 */ 872 memcpy(fdp->meta, new_meta, sizeof(*new_meta)); 873 874 /* 875 * Remove outdated meta file, there is nothing we can 876 * do if we fail here, but that is OK because both 877 * new & old version of block files are kept. The context 878 * of the file is still consistent. 879 */ 880 get_meta_filepath(fdp->filename, old_version, meta_path); 881 ree_fs_unlink_ree(meta_path); 882 883 return res; 884 } 885 886 static int read_meta_file(const char *meta_path, 887 struct tee_fs_file_meta *meta) 888 { 889 int res, fd; 890 size_t meta_info_size = sizeof(struct tee_fs_file_info); 891 892 res = ree_fs_open_ree(meta_path, TEE_FS_O_RDWR); 893 if (res < 0) 894 return res; 895 896 fd = res; 897 898 res = read_and_decrypt_file(fd, META_FILE, 899 (void *)&meta->info, &meta_info_size, 900 meta->encrypted_fek); 901 902 ree_fs_close_ree(fd); 903 904 return res; 905 } 906 907 static struct tee_fs_file_meta *open_meta_file( 908 const char *file, int version) 909 { 910 int res; 911 char meta_path[REE_FS_NAME_MAX]; 912 struct tee_fs_file_meta *meta = NULL; 913 914 meta = malloc(sizeof(struct tee_fs_file_meta)); 915 if (!meta) 916 return NULL; 917 918 get_meta_filepath(file, version, meta_path); 919 res = read_meta_file(meta_path, meta); 920 if (res < 0) 921 goto exit_free_meta; 922 923 meta->backup_version = version; 924 925 return meta; 926 927 exit_free_meta: 928 free(meta); 929 return NULL; 930 } 931 932 static bool is_block_file_exist(struct tee_fs_file_meta *meta, 933 size_t block_num) 934 { 935 size_t file_size = meta->info.length; 936 937 if (file_size == 0) 938 return false; 939 940 return (block_num <= (size_t)get_last_block_num(file_size)); 941 } 942 943 #ifdef CFG_ENC_FS 944 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b) 945 { 946 int fd, res = 0; 947 uint8_t *plaintext = b->data; 948 char block_path[REE_FS_NAME_MAX]; 949 size_t block_file_size = BLOCK_FILE_SIZE; 950 uint8_t version = get_backup_version_of_block(fdp->meta, 951 b->block_num); 952 953 if (!is_block_file_exist(fdp->meta, b->block_num)) 954 goto exit; 955 956 get_block_filepath(fdp->filename, b->block_num, version, 957 block_path); 958 959 fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY); 960 if (fd < 0) 961 return fd; 962 963 res = read_and_decrypt_file(fd, BLOCK_FILE, 964 plaintext, &block_file_size, 965 fdp->meta->encrypted_fek); 966 if (res < 0) { 967 EMSG("Failed to read and decrypt file"); 968 goto fail; 969 } 970 b->data_size = block_file_size; 971 DMSG("Successfully read and decrypt block%d from storage, size=%zd", 972 b->block_num, b->data_size); 973 fail: 974 ree_fs_close_ree(fd); 975 exit: 976 return res; 977 } 978 979 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b, 980 struct tee_fs_file_meta *new_meta) 981 { 982 int fd = -1; 983 int res; 984 size_t block_num = b->block_num; 985 986 fd = create_block_file( 987 fdp, new_meta, block_num); 988 if (fd < 0) { 989 EMSG("Failed to create new version of block"); 990 res = -1; 991 goto fail; 992 } 993 994 res = encrypt_and_write_file(fd, BLOCK_FILE, 995 b->data, b->data_size, 996 new_meta->encrypted_fek); 997 if (res < 0) { 998 EMSG("Failed to encrypt and write block file"); 999 goto fail; 1000 } 1001 DMSG("Successfully encrypt and write block%d to storage, size=%zd", 1002 b->block_num, b->data_size); 1003 1004 fail: 1005 if (fd > 0) 1006 ree_fs_close_ree(fd); 1007 1008 return res; 1009 } 1010 #else 1011 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b) 1012 { 1013 int fd, res = 0; 1014 char block_path[REE_FS_NAME_MAX]; 1015 size_t block_file_size = BLOCK_FILE_SIZE; 1016 uint8_t version = get_backup_version_of_block(fdp->meta, 1017 b->block_num); 1018 1019 if (!is_block_file_exist(fdp->meta, b->block_num)) 1020 goto exit; 1021 1022 get_block_filepath(fdp->filename, b->block_num, version, 1023 block_path); 1024 1025 fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY); 1026 if (fd < 0) 1027 return fd; 1028 1029 1030 res = ree_fs_read_ree(fd, b->data, block_file_size); 1031 if (res < 0) { 1032 EMSG("Failed to read block%d (%d)", 1033 b->block_num, res); 1034 goto fail; 1035 } 1036 1037 b->data_size = res; 1038 DMSG("Successfully read block%d from storage, size=%d", 1039 b->block_num, b->data_size); 1040 res = 0; 1041 fail: 1042 ree_fs_close_ree(fd); 1043 exit: 1044 return res; 1045 } 1046 1047 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b, 1048 struct tee_fs_file_meta *new_meta) 1049 { 1050 int fd = -1; 1051 int res; 1052 size_t block_num = b->block_num; 1053 1054 fd = create_block_file( 1055 fdp, new_meta, block_num); 1056 if (fd < 0) { 1057 EMSG("Failed to create new version of block"); 1058 res = -1; 1059 goto fail; 1060 } 1061 1062 res = ree_fs_write_ree(fd, b->data, b->data_size); 1063 if (res < 0) { 1064 EMSG("Failed to write block%d (%d)", 1065 b->block_num, res); 1066 goto fail; 1067 } 1068 DMSG("Successfully writen block%d to storage, size=%d", 1069 b->block_num, b->data_size); 1070 res = 0; 1071 fail: 1072 if (fd > 0) 1073 ree_fs_close_ree(fd); 1074 1075 return res; 1076 } 1077 #endif 1078 1079 static struct block *alloc_block(void) 1080 { 1081 struct block *c; 1082 1083 c = malloc(sizeof(struct block)); 1084 if (!c) 1085 return NULL; 1086 1087 c->data = malloc(BLOCK_FILE_SIZE); 1088 if (!c->data) { 1089 EMSG("unable to alloc memory for block data"); 1090 goto exit; 1091 } 1092 1093 c->block_num = -1; 1094 c->data_size = 0; 1095 1096 return c; 1097 1098 exit: 1099 free(c); 1100 return NULL; 1101 } 1102 1103 #ifdef CFG_FS_BLOCK_CACHE 1104 static void free_block(struct block *b) 1105 { 1106 if (b) { 1107 free(b->data); 1108 free(b); 1109 } 1110 } 1111 1112 static inline bool is_block_data_invalid(struct block *b) 1113 { 1114 return (b->data_size == 0); 1115 } 1116 1117 static void get_block_from_cache(struct block_cache *cache, 1118 int block_num, struct block **out_block) 1119 { 1120 struct block *b, *found = NULL; 1121 1122 DMSG("Try to find block%d in cache", block_num); 1123 TAILQ_FOREACH(b, &cache->block_lru, list) { 1124 if (b->block_num == block_num) { 1125 DMSG("Found in cache"); 1126 found = b; 1127 break; 1128 } 1129 } 1130 1131 if (found) { 1132 TAILQ_REMOVE(&cache->block_lru, found, list); 1133 TAILQ_INSERT_HEAD(&cache->block_lru, found, list); 1134 *out_block = found; 1135 return; 1136 } 1137 1138 DMSG("Not found, reuse oldest block on LRU list"); 1139 b = TAILQ_LAST(&cache->block_lru, block_head); 1140 TAILQ_REMOVE(&cache->block_lru, b, list); 1141 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 1142 b->block_num = block_num; 1143 b->data_size = 0; 1144 *out_block = b; 1145 } 1146 1147 static int init_block_cache(struct block_cache *cache) 1148 { 1149 struct block *b; 1150 1151 TAILQ_INIT(&cache->block_lru); 1152 cache->cached_block_num = 0; 1153 1154 while (cache->cached_block_num < MAX_NUM_CACHED_BLOCKS) { 1155 1156 b = alloc_block(); 1157 if (!b) { 1158 EMSG("Failed to alloc block"); 1159 goto fail; 1160 } else { 1161 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 1162 cache->cached_block_num++; 1163 } 1164 } 1165 return 0; 1166 1167 fail: 1168 TAILQ_FOREACH(b, &cache->block_lru, list) 1169 free_block(b); 1170 return -1; 1171 } 1172 1173 static void destroy_block_cache(struct block_cache *cache) 1174 { 1175 struct block *b, *next; 1176 1177 TAILQ_FOREACH_SAFE(b, &cache->block_lru, list, next) { 1178 TAILQ_REMOVE(&cache->block_lru, b, list); 1179 free_block(b); 1180 } 1181 } 1182 #else 1183 static int init_block_cache(struct block_cache *cache __unused) 1184 { 1185 return 0; 1186 } 1187 1188 static void destroy_block_cache(struct block_cache *cache __unused) 1189 { 1190 } 1191 #endif 1192 1193 static void write_data_to_block(struct block *b, int offset, 1194 void *buf, size_t len) 1195 { 1196 DMSG("Write %zd bytes to block%d", len, b->block_num); 1197 memcpy(b->data + offset, buf, len); 1198 if (offset + len > b->data_size) { 1199 b->data_size = offset + len; 1200 DMSG("Extend block%d size to %zd bytes", 1201 b->block_num, b->data_size); 1202 } 1203 } 1204 1205 static void read_data_from_block(struct block *b, int offset, 1206 void *buf, size_t len) 1207 { 1208 size_t bytes_to_read = len; 1209 1210 DMSG("Read %zd bytes from block%d", len, b->block_num); 1211 if (offset + len > b->data_size) { 1212 bytes_to_read = b->data_size - offset; 1213 DMSG("Exceed block size, update len to %zd bytes", 1214 bytes_to_read); 1215 } 1216 memcpy(buf, b->data + offset, bytes_to_read); 1217 } 1218 1219 #ifdef CFG_FS_BLOCK_CACHE 1220 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num) 1221 { 1222 struct block *b; 1223 1224 get_block_from_cache(&fdp->block_cache, block_num, &b); 1225 if (is_block_data_invalid(b)) 1226 if (read_block_from_storage(fdp, b)) { 1227 EMSG("Unable to read block%d from storage", 1228 block_num); 1229 return NULL; 1230 } 1231 1232 return b; 1233 } 1234 #else 1235 1236 static struct mutex block_mutex = MUTEX_INITIALIZER; 1237 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num) 1238 { 1239 static struct block *b; 1240 int res; 1241 1242 mutex_lock(&block_mutex); 1243 if (!b) 1244 b = alloc_block(); 1245 b->block_num = block_num; 1246 1247 res = read_block_from_storage(fdp, b); 1248 if (res) 1249 EMSG("Unable to read block%d from storage", 1250 block_num); 1251 mutex_unlock(&block_mutex); 1252 1253 return res ? NULL : b; 1254 } 1255 #endif 1256 1257 static struct block_operations block_ops = { 1258 #ifdef CFG_FS_BLOCK_CACHE 1259 .read = read_block_with_cache, 1260 #else 1261 .read = read_block_no_cache, 1262 #endif 1263 .write = flush_block_to_storage, 1264 }; 1265 1266 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf, 1267 size_t len, struct tee_fs_file_meta *new_meta) 1268 { 1269 int start_block_num = pos_to_block_num(fdp->pos); 1270 int end_block_num = pos_to_block_num(fdp->pos + len - 1); 1271 size_t remain_bytes = len; 1272 uint8_t *data_ptr = (uint8_t *)buf; 1273 int orig_pos = fdp->pos; 1274 1275 while (start_block_num <= end_block_num) { 1276 int offset = fdp->pos % BLOCK_FILE_SIZE; 1277 struct block *b; 1278 size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ? 1279 BLOCK_FILE_SIZE : remain_bytes; 1280 1281 if (size_to_write + offset > BLOCK_FILE_SIZE) 1282 size_to_write = BLOCK_FILE_SIZE - offset; 1283 1284 b = block_ops.read(fdp, start_block_num); 1285 if (!b) 1286 goto failed; 1287 1288 DMSG("Write data, offset: %d, size_to_write: %zd", 1289 offset, size_to_write); 1290 write_data_to_block(b, offset, data_ptr, size_to_write); 1291 1292 if (block_ops.write(fdp, b, new_meta)) { 1293 EMSG("Unable to wrtie block%d to storage", 1294 b->block_num); 1295 goto failed; 1296 } 1297 1298 data_ptr += size_to_write; 1299 remain_bytes -= size_to_write; 1300 start_block_num++; 1301 fdp->pos += size_to_write; 1302 } 1303 1304 if (fdp->pos > (tee_fs_off_t)new_meta->info.length) 1305 new_meta->info.length = fdp->pos; 1306 1307 return 0; 1308 failed: 1309 fdp->pos = orig_pos; 1310 return -1; 1311 } 1312 1313 static inline int create_hard_link(const char *old_dir, 1314 const char *new_dir, 1315 const char *filename) 1316 { 1317 char old_path[REE_FS_NAME_MAX]; 1318 char new_path[REE_FS_NAME_MAX]; 1319 1320 snprintf(old_path, REE_FS_NAME_MAX, "%s/%s", 1321 old_dir, filename); 1322 snprintf(new_path, REE_FS_NAME_MAX, "%s/%s", 1323 new_dir, filename); 1324 1325 DMSG("%s -> %s", old_path, new_path); 1326 return ree_fs_link_ree(old_path, new_path); 1327 } 1328 1329 static int unlink_tee_file(const char *file) 1330 { 1331 int res = -1; 1332 size_t len = strlen(file) + 1; 1333 struct tee_fs_dirent *dirent; 1334 struct tee_fs_dir *dir; 1335 1336 DMSG("file=%s", file); 1337 1338 if (len > TEE_FS_NAME_MAX) 1339 goto exit; 1340 1341 dir = ree_fs_opendir_ree(file); 1342 if (!dir) 1343 goto exit; 1344 1345 dirent = ree_fs_readdir_ree(dir); 1346 while (dirent) { 1347 char path[REE_FS_NAME_MAX]; 1348 1349 snprintf(path, REE_FS_NAME_MAX, "%s/%s", 1350 file, dirent->d_name); 1351 1352 DMSG("unlink %s", path); 1353 res = ree_fs_unlink_ree(path); 1354 if (res) { 1355 ree_fs_closedir_ree(dir); 1356 goto exit; 1357 } 1358 1359 dirent = ree_fs_readdir_ree(dir); 1360 } 1361 1362 res = ree_fs_closedir_ree(dir); 1363 if (res) 1364 goto exit; 1365 1366 res = ree_fs_rmdir_ree(file); 1367 exit: 1368 return res; 1369 } 1370 1371 static bool tee_file_exists(const char *file) 1372 { 1373 char meta_path[REE_FS_NAME_MAX]; 1374 1375 get_meta_filepath(file, 0, meta_path); 1376 if (ree_fs_access_ree(meta_path, TEE_FS_F_OK)) { 1377 get_meta_filepath(file, 1, meta_path); 1378 if (ree_fs_access_ree(meta_path, TEE_FS_F_OK)) 1379 return false; 1380 } 1381 1382 return true; 1383 } 1384 1385 static struct tee_fs_file_meta *create_tee_file(const char *file) 1386 { 1387 struct tee_fs_file_meta *meta = NULL; 1388 int res; 1389 1390 DMSG("Creating TEE file=%s", file); 1391 1392 /* create TEE file directory if not exist */ 1393 if (ree_fs_access_ree(file, TEE_FS_F_OK)) { 1394 res = ree_fs_mkdir_ree(file, 1395 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); 1396 if (res) { 1397 EMSG("Failed to create TEE file directory, res=%d", 1398 res); 1399 goto exit; 1400 } 1401 } 1402 1403 /* create meta file in TEE file directory */ 1404 meta = create_meta_file(file); 1405 if (!meta) 1406 EMSG("Failed to create new meta file"); 1407 1408 exit: 1409 return meta; 1410 } 1411 1412 static struct tee_fs_file_meta *open_tee_file(const char *file) 1413 { 1414 struct tee_fs_file_meta *meta = NULL; 1415 int backup_version = 0; 1416 1417 DMSG("Opening TEE file=%s", file); 1418 1419 meta = open_meta_file(file, backup_version); 1420 if (!meta) { 1421 meta = open_meta_file(file, !backup_version); 1422 if (!meta) { 1423 /* 1424 * cannot open meta file, assumed the TEE file 1425 * is corrupted 1426 */ 1427 EMSG("Can not open meta file"); 1428 } 1429 } 1430 1431 return meta; 1432 } 1433 1434 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1435 tee_fs_off_t new_file_len); 1436 1437 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...) 1438 { 1439 int res = -1; 1440 size_t len; 1441 struct tee_fs_file_meta *meta = NULL; 1442 struct tee_fs_fd *fdp = NULL; 1443 bool file_exist; 1444 1445 assert(errno != NULL); 1446 *errno = TEE_SUCCESS; 1447 1448 if (!file) { 1449 *errno = TEE_ERROR_BAD_PARAMETERS; 1450 goto exit; 1451 } 1452 1453 len = strlen(file) + 1; 1454 if (len > TEE_FS_NAME_MAX) { 1455 *errno = TEE_ERROR_BAD_PARAMETERS; 1456 goto exit; 1457 } 1458 1459 file_exist = tee_file_exists(file); 1460 if (flags & TEE_FS_O_CREATE) { 1461 if ((flags & TEE_FS_O_EXCL) && file_exist) { 1462 DMSG("tee file already exists"); 1463 *errno = TEE_ERROR_ACCESS_CONFLICT; 1464 goto exit; 1465 } 1466 1467 if (!file_exist) 1468 meta = create_tee_file(file); 1469 else 1470 meta = open_tee_file(file); 1471 1472 } else { 1473 if (!file_exist) { 1474 DMSG("tee file not exists"); 1475 *errno = TEE_ERROR_ITEM_NOT_FOUND; 1476 goto exit; 1477 } 1478 1479 meta = open_tee_file(file); 1480 } 1481 1482 if (!meta) { 1483 EMSG("Failed to open TEE file"); 1484 *errno = TEE_ERROR_CORRUPT_OBJECT; 1485 goto exit; 1486 } 1487 1488 DMSG("file=%s, length=%zd", file, meta->info.length); 1489 fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd)); 1490 if (!fdp) { 1491 *errno = TEE_ERROR_OUT_OF_MEMORY; 1492 goto exit_free_meta; 1493 } 1494 1495 /* init internal status */ 1496 fdp->flags = flags; 1497 fdp->meta = meta; 1498 fdp->pos = 0; 1499 if (init_block_cache(&fdp->block_cache)) { 1500 res = -1; 1501 goto exit_free_fd; 1502 } 1503 1504 fdp->filename = malloc(len); 1505 if (!fdp->filename) { 1506 res = -1; 1507 *errno = TEE_ERROR_OUT_OF_MEMORY; 1508 goto exit_destroy_block_cache; 1509 } 1510 memcpy(fdp->filename, file, len); 1511 1512 if ((flags & TEE_FS_O_TRUNC) && 1513 (flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) { 1514 res = ree_fs_ftruncate_internal(errno, fdp, 0); 1515 if (res < 0) { 1516 EMSG("Unable to truncate file"); 1517 goto exit_free_filename; 1518 } 1519 } 1520 1521 /* return fd */ 1522 res = handle_get(&fs_handle_db, fdp); 1523 if (res < 0) 1524 goto exit_free_filename; 1525 fdp->fd = res; 1526 goto exit; 1527 1528 exit_free_filename: 1529 free(fdp->filename); 1530 exit_destroy_block_cache: 1531 destroy_block_cache(&fdp->block_cache); 1532 exit_free_fd: 1533 free(fdp); 1534 exit_free_meta: 1535 free(meta); 1536 exit: 1537 return res; 1538 } 1539 1540 static int ree_fs_close(int fd) 1541 { 1542 int res = -1; 1543 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1544 1545 if (!fdp) 1546 return -1; 1547 1548 handle_put(&fs_handle_db, fdp->fd); 1549 1550 destroy_block_cache(&fdp->block_cache); 1551 free(fdp->meta); 1552 free(fdp->filename); 1553 free(fdp); 1554 1555 return res; 1556 } 1557 1558 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd, 1559 tee_fs_off_t offset, int whence) 1560 { 1561 tee_fs_off_t res = -1; 1562 tee_fs_off_t new_pos; 1563 size_t filelen; 1564 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1565 1566 assert(errno != NULL); 1567 *errno = TEE_SUCCESS; 1568 1569 if (!fdp) { 1570 *errno = TEE_ERROR_BAD_PARAMETERS; 1571 goto exit; 1572 } 1573 1574 DMSG("offset=%d, whence=%d", (int)offset, whence); 1575 1576 filelen = fdp->meta->info.length; 1577 1578 switch (whence) { 1579 case TEE_FS_SEEK_SET: 1580 new_pos = offset; 1581 break; 1582 1583 case TEE_FS_SEEK_CUR: 1584 new_pos = fdp->pos + offset; 1585 break; 1586 1587 case TEE_FS_SEEK_END: 1588 new_pos = filelen + offset; 1589 break; 1590 1591 default: 1592 *errno = TEE_ERROR_BAD_PARAMETERS; 1593 goto exit; 1594 } 1595 1596 if (new_pos < 0) 1597 new_pos = 0; 1598 1599 if (new_pos > TEE_DATA_MAX_POSITION) { 1600 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 1601 *errno = TEE_ERROR_BAD_PARAMETERS; 1602 goto exit; 1603 } 1604 1605 res = fdp->pos = new_pos; 1606 exit: 1607 return res; 1608 } 1609 1610 /* 1611 * To ensure atomic truncate operation, we can: 1612 * 1613 * - update file length to new length 1614 * - commit new meta 1615 * - free unused blocks 1616 * 1617 * To ensure atomic extend operation, we can: 1618 * 1619 * - update file length to new length 1620 * - allocate and fill zero data to new blocks 1621 * - commit new meta 1622 * 1623 * Any failure before committing new meta is considered as 1624 * update failed, and the file content will not be updated 1625 */ 1626 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1627 tee_fs_off_t new_file_len) 1628 { 1629 int res = -1; 1630 size_t old_file_len = fdp->meta->info.length; 1631 struct tee_fs_file_meta *new_meta = NULL; 1632 uint8_t *buf = NULL; 1633 1634 assert(errno != NULL); 1635 *errno = TEE_SUCCESS; 1636 1637 if (!fdp) { 1638 *errno = TEE_ERROR_BAD_PARAMETERS; 1639 res = -1; 1640 goto exit; 1641 } 1642 1643 if (fdp->flags & TEE_FS_O_RDONLY) { 1644 *errno = TEE_ERROR_BAD_PARAMETERS; 1645 EMSG("Read only"); 1646 res = -1; 1647 goto exit; 1648 } 1649 1650 if ((size_t)new_file_len == old_file_len) { 1651 DMSG("Ignore due to file length does not changed"); 1652 res = 0; 1653 goto exit; 1654 } 1655 1656 if (new_file_len > MAX_FILE_SIZE) { 1657 *errno = TEE_ERROR_BAD_PARAMETERS; 1658 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1659 res = -1; 1660 goto exit; 1661 } 1662 1663 new_meta = duplicate_meta(fdp); 1664 if (!new_meta) { 1665 *errno = TEE_ERROR_OUT_OF_MEMORY; 1666 res = -1; 1667 goto free; 1668 } 1669 1670 new_meta->info.length = new_file_len; 1671 1672 if ((size_t)new_file_len < old_file_len) { 1673 int old_block_num = get_last_block_num(old_file_len); 1674 int new_block_num = get_last_block_num(new_file_len); 1675 1676 DMSG("Truncate file length to %zu", (size_t)new_file_len); 1677 1678 res = commit_meta_file(fdp, new_meta); 1679 if (res < 0) { 1680 *errno = TEE_ERROR_CORRUPT_OBJECT; 1681 EMSG("Failed to commit meta file"); 1682 goto free; 1683 } 1684 1685 /* now we are safe to free unused blocks */ 1686 while (old_block_num > new_block_num) { 1687 if (remove_block_file(fdp, old_block_num)) { 1688 IMSG("Warning: Failed to free block: %d", 1689 old_block_num); 1690 } 1691 1692 old_block_num--; 1693 } 1694 1695 } else { 1696 size_t ext_len = new_file_len - old_file_len; 1697 int orig_pos = fdp->pos; 1698 1699 buf = malloc(BLOCK_FILE_SIZE); 1700 if (!buf) { 1701 *errno = TEE_ERROR_OUT_OF_MEMORY; 1702 EMSG("Failed to allocate buffer, size=%d", 1703 BLOCK_FILE_SIZE); 1704 res = -1; 1705 goto free; 1706 } 1707 1708 memset(buf, 0x0, BLOCK_FILE_SIZE); 1709 1710 DMSG("Extend file length to %zu", (size_t)new_file_len); 1711 1712 fdp->pos = old_file_len; 1713 1714 res = 0; 1715 while (ext_len > 0) { 1716 size_t data_len = (ext_len > BLOCK_FILE_SIZE) ? 1717 BLOCK_FILE_SIZE : ext_len; 1718 1719 DMSG("fill len=%zu", data_len); 1720 res = out_of_place_write(fdp, (void *)buf, 1721 data_len, new_meta); 1722 if (res < 0) { 1723 *errno = TEE_ERROR_CORRUPT_OBJECT; 1724 EMSG("Failed to fill data"); 1725 break; 1726 } 1727 1728 ext_len -= data_len; 1729 } 1730 1731 fdp->pos = orig_pos; 1732 1733 if (res == 0) { 1734 res = commit_meta_file(fdp, new_meta); 1735 if (res < 0) { 1736 *errno = TEE_ERROR_CORRUPT_OBJECT; 1737 EMSG("Failed to commit meta file"); 1738 } 1739 } 1740 } 1741 1742 free: 1743 free(new_meta); 1744 free(buf); 1745 1746 exit: 1747 return res; 1748 } 1749 1750 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len) 1751 { 1752 int res = -1; 1753 int start_block_num; 1754 int end_block_num; 1755 size_t remain_bytes = len; 1756 uint8_t *data_ptr = buf; 1757 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1758 1759 assert(errno != NULL); 1760 *errno = TEE_SUCCESS; 1761 1762 if (!fdp) { 1763 *errno = TEE_ERROR_BAD_PARAMETERS; 1764 goto exit; 1765 } 1766 1767 if (fdp->pos + len > fdp->meta->info.length) { 1768 len = fdp->meta->info.length - fdp->pos; 1769 DMSG("reached EOF, update read length to %zu", len); 1770 } 1771 1772 if (!len) { 1773 res = 0; 1774 goto exit; 1775 } 1776 1777 if (!buf) { 1778 *errno = TEE_ERROR_BAD_PARAMETERS; 1779 goto exit; 1780 } 1781 1782 if (fdp->flags & TEE_FS_O_WRONLY) { 1783 *errno = TEE_ERROR_ACCESS_CONFLICT; 1784 goto exit; 1785 } 1786 1787 DMSG("%s, data len=%zu", fdp->filename, len); 1788 1789 start_block_num = pos_to_block_num(fdp->pos); 1790 end_block_num = pos_to_block_num(fdp->pos + len - 1); 1791 DMSG("start_block_num:%d, end_block_num:%d", 1792 start_block_num, end_block_num); 1793 1794 while (start_block_num <= end_block_num) { 1795 struct block *b; 1796 int offset = fdp->pos % BLOCK_FILE_SIZE; 1797 size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ? 1798 BLOCK_FILE_SIZE : remain_bytes; 1799 1800 if (size_to_read + offset > BLOCK_FILE_SIZE) 1801 size_to_read = BLOCK_FILE_SIZE - offset; 1802 1803 DMSG("block_num:%d, offset:%d, size_to_read: %zd", 1804 start_block_num, offset, size_to_read); 1805 1806 b = block_ops.read(fdp, start_block_num); 1807 if (!b) { 1808 *errno = TEE_ERROR_CORRUPT_OBJECT; 1809 goto exit; 1810 } 1811 1812 read_data_from_block(b, offset, data_ptr, size_to_read); 1813 data_ptr += size_to_read; 1814 remain_bytes -= size_to_read; 1815 fdp->pos += size_to_read; 1816 1817 start_block_num++; 1818 } 1819 res = 0; 1820 exit: 1821 return (res < 0) ? res : (int)len; 1822 } 1823 1824 /* 1825 * To ensure atomicity of write operation, we need to 1826 * do the following steps: 1827 * (The sequence of operations is very important) 1828 * 1829 * - Create a new backup version of meta file as a copy 1830 * of current meta file. 1831 * - For each blocks to write: 1832 * - Create new backup version for current block. 1833 * - Write data to new backup version. 1834 * - Update the new meta file accordingly. 1835 * - Write the new meta file. 1836 * 1837 * (Any failure in above steps is considered as update failed, 1838 * and the file content will not be updated) 1839 * 1840 * After previous step the update is considered complete, but 1841 * we should do the following clean-up step(s): 1842 * 1843 * - Delete old meta file. 1844 * - Remove old block files. 1845 * 1846 * (Any failure in above steps is considered as a successfully 1847 * update) 1848 */ 1849 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len) 1850 { 1851 int res = -1; 1852 struct tee_fs_file_meta *new_meta = NULL; 1853 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1854 size_t file_size; 1855 int orig_pos; 1856 1857 assert(errno != NULL); 1858 *errno = TEE_SUCCESS; 1859 1860 if (!fdp) { 1861 *errno = TEE_ERROR_BAD_PARAMETERS; 1862 goto exit; 1863 } 1864 if (!len) { 1865 res = 0; 1866 goto exit; 1867 } 1868 if (!buf) { 1869 *errno = TEE_ERROR_BAD_PARAMETERS; 1870 goto exit; 1871 } 1872 1873 file_size = fdp->meta->info.length; 1874 orig_pos = fdp->pos; 1875 1876 if (fdp->flags & TEE_FS_O_RDONLY) { 1877 EMSG("Write to a read-only file, denied"); 1878 *errno = TEE_ERROR_ACCESS_CONFLICT; 1879 goto exit; 1880 } 1881 1882 if ((fdp->pos + len) > MAX_FILE_SIZE) { 1883 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1884 *errno = TEE_ERROR_BAD_PARAMETERS; 1885 goto exit; 1886 } 1887 1888 DMSG("%s, data len=%zu", fdp->filename, len); 1889 if (file_size < (size_t)fdp->pos) { 1890 DMSG("File hole detected, try to extend file size"); 1891 res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos); 1892 if (res < 0) 1893 goto exit; 1894 } 1895 1896 new_meta = duplicate_meta(fdp); 1897 if (!new_meta) { 1898 *errno = TEE_ERROR_OUT_OF_MEMORY; 1899 goto exit; 1900 } 1901 1902 res = out_of_place_write(fdp, buf, len, new_meta); 1903 if (res < 0) { 1904 *errno = TEE_ERROR_CORRUPT_OBJECT; 1905 } else { 1906 int r; 1907 int start_block_num; 1908 int end_block_num; 1909 1910 r = commit_meta_file(fdp, new_meta); 1911 if (r < 0) { 1912 *errno = TEE_ERROR_CORRUPT_OBJECT; 1913 res = -1; 1914 } 1915 1916 /* we are safe to free old blocks */ 1917 start_block_num = pos_to_block_num(orig_pos); 1918 end_block_num = pos_to_block_num(fdp->pos - 1); 1919 while (start_block_num <= end_block_num) { 1920 if (remove_outdated_block(fdp, start_block_num)) 1921 IMSG("Warning: Failed to free old block: %d", 1922 start_block_num); 1923 1924 start_block_num++; 1925 } 1926 } 1927 exit: 1928 free(new_meta); 1929 return (res < 0) ? res : (int)len; 1930 } 1931 1932 /* 1933 * To ensure atomicity of rename operation, we need to 1934 * do the following steps: 1935 * 1936 * - Create a new folder that represents the renamed TEE file 1937 * - For each REE block files, create a hard link under the just 1938 * created folder (new TEE file) 1939 * - Now we are ready to commit meta, create hard link for the 1940 * meta file 1941 * 1942 * (Any failure in above steps is considered as update failed, 1943 * and the file content will not be updated) 1944 * 1945 * After previous step the update is considered complete, but 1946 * we should do the following clean-up step(s): 1947 * 1948 * - Unlink all REE files represents the old TEE file (including 1949 * meta and block files) 1950 * 1951 * (Any failure in above steps is considered as a successfully 1952 * update) 1953 */ 1954 static int ree_fs_rename(const char *old, const char *new) 1955 { 1956 int res = -1; 1957 size_t old_len; 1958 size_t new_len; 1959 size_t meta_count = 0; 1960 struct tee_fs_dir *old_dir; 1961 struct tee_fs_dirent *dirent; 1962 char *meta_filename = NULL; 1963 1964 if (!old || !new) 1965 return -1; 1966 1967 DMSG("old=%s, new=%s", old, new); 1968 1969 old_len = strlen(old) + 1; 1970 new_len = strlen(new) + 1; 1971 1972 if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX) 1973 goto exit; 1974 1975 res = ree_fs_mkdir_ree(new, 1976 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); 1977 if (res) 1978 goto exit; 1979 1980 old_dir = ree_fs_opendir_ree(old); 1981 if (!old_dir) 1982 goto exit; 1983 1984 dirent = ree_fs_readdir_ree(old_dir); 1985 while (dirent) { 1986 if (!strncmp(dirent->d_name, "meta.", 5)) { 1987 meta_filename = strdup(dirent->d_name); 1988 meta_count++; 1989 } else { 1990 res = create_hard_link(old, new, dirent->d_name); 1991 if (res) 1992 goto exit_close_old_dir; 1993 } 1994 1995 dirent = ree_fs_readdir_ree(old_dir); 1996 } 1997 1998 /* finally, link the meta file, rename operation completed */ 1999 TEE_ASSERT(meta_filename); 2000 2001 /* 2002 * TODO: This will cause memory leakage at previous strdup() 2003 * if we accidently have two meta files in a TEE file. 2004 * 2005 * It's not easy to handle the case above (e.g. Which meta file 2006 * should be linked first? What to do if a power cut happened 2007 * during creating links for the two meta files?) 2008 * 2009 * We will solve this issue using another approach: merging 2010 * both meta and block files into a single REE file. This approach 2011 * can completely remove ree_fs_rename(). We can simply 2012 * rename TEE file using REE rename() system call, which is also 2013 * atomic. 2014 */ 2015 if (meta_count > 1) 2016 EMSG("Warning: more than one meta file in your TEE file\n" 2017 "This will cause memory leakage."); 2018 2019 res = create_hard_link(old, new, meta_filename); 2020 if (res) 2021 goto exit_close_old_dir; 2022 2023 /* we are safe now, remove old TEE file */ 2024 unlink_tee_file(old); 2025 2026 exit_close_old_dir: 2027 ree_fs_closedir_ree(old_dir); 2028 exit: 2029 free(meta_filename); 2030 return res; 2031 } 2032 2033 /* 2034 * To ensure atomic unlink operation, we can simply 2035 * split the unlink operation into: 2036 * 2037 * - rename("file", "file.trash"); 2038 * 2039 * (Any failure in above steps is considered as update failed, 2040 * and the file content will not be updated) 2041 * 2042 * After previous step the update is considered complete, but 2043 * we should do the following clean-up step(s): 2044 * 2045 * - unlink("file.trash"); 2046 * 2047 * (Any failure in above steps is considered as a successfully 2048 * update) 2049 */ 2050 static int ree_fs_unlink(const char *file) 2051 { 2052 int res = -1; 2053 char trash_file[TEE_FS_NAME_MAX + 6]; 2054 2055 if (!file) 2056 return -1; 2057 2058 snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash", 2059 file); 2060 2061 res = ree_fs_rename(file, trash_file); 2062 if (res < 0) 2063 return res; 2064 2065 unlink_tee_file(trash_file); 2066 2067 return res; 2068 } 2069 2070 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length) 2071 { 2072 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 2073 2074 return ree_fs_ftruncate_internal(errno, fdp, length); 2075 } 2076 2077 const struct tee_file_operations ree_fs_ops = { 2078 .open = ree_fs_open, 2079 .close = ree_fs_close, 2080 .read = ree_fs_read, 2081 .write = ree_fs_write, 2082 .lseek = ree_fs_lseek, 2083 .ftruncate = ree_fs_ftruncate, 2084 .rename = ree_fs_rename, 2085 .unlink = ree_fs_unlink, 2086 .mkdir = ree_fs_mkdir_ree, 2087 .opendir = ree_fs_opendir_ree, 2088 .closedir = ree_fs_closedir_ree, 2089 .readdir = ree_fs_readdir_ree, 2090 .rmdir = ree_fs_rmdir_ree, 2091 .access = ree_fs_access_ree 2092 }; 2093