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 assert(length); 589 *length = 0; 590 591 res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_END); 592 if (res < 0) 593 return res; 594 595 file_len = res; 596 597 res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_SET); 598 if (res < 0) 599 return res; 600 601 *length = file_len; 602 return 0; 603 } 604 605 static void get_meta_filepath(const char *file, int version, 606 char *meta_path) 607 { 608 snprintf(meta_path, REE_FS_NAME_MAX, "%s/meta.%d", 609 file, version); 610 } 611 612 static void get_block_filepath(const char *file, size_t block_num, 613 int version, char *meta_path) 614 { 615 snprintf(meta_path, REE_FS_NAME_MAX, "%s/block%zu.%d", 616 file, block_num, version); 617 } 618 619 static int create_block_file(struct tee_fs_fd *fdp, 620 struct tee_fs_file_meta *new_meta, int block_num) 621 { 622 int fd; 623 int res = -1; 624 char block_path[REE_FS_NAME_MAX]; 625 uint8_t new_version = 626 !get_backup_version_of_block(fdp->meta, block_num); 627 628 get_block_filepath(fdp->filename, block_num, new_version, 629 block_path); 630 631 fd = ree_fs_open_ree(block_path, TEE_FS_O_CREATE | TEE_FS_O_RDWR); 632 if (fd < 0) 633 goto exit; 634 635 res = ree_fs_ftruncate_ree(fd, 0); 636 if (res < 0) 637 goto exit; 638 639 /* 640 * toggle block version in new meta to indicate 641 * we are currently working on new block file 642 */ 643 toggle_backup_version_of_block(new_meta, block_num); 644 res = fd; 645 646 exit: 647 return res; 648 } 649 650 static int __remove_block_file(struct tee_fs_fd *fdp, size_t block_num, 651 bool toggle) 652 { 653 char block_path[REE_FS_NAME_MAX]; 654 uint8_t version = 655 get_backup_version_of_block(fdp->meta, block_num); 656 657 if (toggle) 658 version = !version; 659 660 get_block_filepath(fdp->filename, block_num, version, block_path); 661 DMSG("%s", block_path); 662 663 /* ignore it if file not found */ 664 if (ree_fs_access_ree(block_path, TEE_FS_F_OK)) 665 return 0; 666 667 return ree_fs_unlink_ree(block_path); 668 } 669 670 static int remove_block_file(struct tee_fs_fd *fdp, size_t block_num) 671 { 672 DMSG("remove block%zd", block_num); 673 return __remove_block_file(fdp, block_num, false); 674 } 675 676 static int remove_outdated_block(struct tee_fs_fd *fdp, size_t block_num) 677 { 678 DMSG("remove outdated block%zd", block_num); 679 return __remove_block_file(fdp, block_num, true); 680 } 681 682 /* 683 * encrypted_fek: as input for META_FILE and BLOCK_FILE 684 */ 685 static int encrypt_and_write_file(int fd, 686 enum tee_fs_file_type file_type, 687 void *data_in, size_t data_in_size, 688 uint8_t *encrypted_fek) 689 { 690 TEE_Result tee_res; 691 int res = 0; 692 int bytes; 693 uint8_t *ciphertext; 694 size_t header_size = tee_fs_get_header_size(file_type); 695 size_t ciphertext_size = header_size + data_in_size; 696 697 ciphertext = malloc(ciphertext_size); 698 if (!ciphertext) { 699 EMSG("Failed to allocate ciphertext buffer, size=%zd", 700 ciphertext_size); 701 return -1; 702 } 703 704 tee_res = tee_fs_encrypt_file(file_type, 705 data_in, data_in_size, 706 ciphertext, &ciphertext_size, encrypted_fek); 707 if (tee_res != TEE_SUCCESS) { 708 EMSG("error code=%x", tee_res); 709 res = -1; 710 goto fail; 711 } 712 713 bytes = ree_fs_write_ree(fd, ciphertext, ciphertext_size); 714 if (bytes != (int)ciphertext_size) { 715 EMSG("bytes(%d) != ciphertext size(%zu)", 716 bytes, ciphertext_size); 717 res = -1; 718 goto fail; 719 } 720 721 fail: 722 free(ciphertext); 723 724 return res; 725 } 726 727 /* 728 * encrypted_fek: as output for META_FILE 729 * as input for BLOCK_FILE 730 */ 731 static int read_and_decrypt_file(int fd, 732 enum tee_fs_file_type file_type, 733 void *data_out, size_t *data_out_size, 734 uint8_t *encrypted_fek) 735 { 736 TEE_Result tee_res; 737 int res; 738 int bytes; 739 void *ciphertext = NULL; 740 size_t file_size; 741 size_t header_size = tee_fs_get_header_size(file_type); 742 743 res = get_file_length(fd, &file_size); 744 if (res < 0) 745 return res; 746 747 TEE_ASSERT(file_size >= header_size); 748 749 ciphertext = malloc(file_size); 750 if (!ciphertext) { 751 EMSG("Failed to allocate file data buffer, size=%zd", 752 file_size); 753 return -1; 754 } 755 756 bytes = ree_fs_read_ree(fd, ciphertext, file_size); 757 if (bytes != (int)file_size) { 758 EMSG("return bytes(%d) != file_size(%zd)", 759 bytes, file_size); 760 res = -1; 761 goto fail; 762 } 763 764 tee_res = tee_fs_decrypt_file(file_type, 765 ciphertext, file_size, 766 data_out, data_out_size, 767 encrypted_fek); 768 if (tee_res != TEE_SUCCESS) { 769 EMSG("Failed to decrypt file, res=0x%x", tee_res); 770 res = -1; 771 } 772 773 fail: 774 free(ciphertext); 775 776 return (res < 0) ? res : 0; 777 } 778 779 static struct tee_fs_file_meta *duplicate_meta( 780 struct tee_fs_fd *fdp) 781 { 782 struct tee_fs_file_meta *new_meta = NULL; 783 784 new_meta = malloc(sizeof(*new_meta)); 785 if (!new_meta) { 786 EMSG("Failed to allocate memory for new meta"); 787 goto exit; 788 } 789 790 memcpy(new_meta, fdp->meta, sizeof(*new_meta)); 791 792 exit: 793 return new_meta; 794 } 795 796 static int write_meta_file(const char *filename, 797 struct tee_fs_file_meta *meta) 798 { 799 int res, fd = -1; 800 char meta_path[REE_FS_NAME_MAX]; 801 802 get_meta_filepath(filename, meta->backup_version, meta_path); 803 804 fd = ree_fs_open_ree(meta_path, TEE_FS_O_CREATE | 805 TEE_FS_O_TRUNC | TEE_FS_O_WRONLY); 806 if (fd < 0) 807 return -1; 808 809 res = encrypt_and_write_file(fd, META_FILE, 810 (void *)&meta->info, sizeof(meta->info), 811 meta->encrypted_fek); 812 813 ree_fs_close_ree(fd); 814 return res; 815 } 816 817 static struct tee_fs_file_meta *create_meta_file(const char *file) 818 { 819 TEE_Result tee_res; 820 struct tee_fs_file_meta *meta = NULL; 821 int res; 822 const uint8_t default_backup_version = 0; 823 824 meta = malloc(sizeof(struct tee_fs_file_meta)); 825 if (!meta) { 826 EMSG("Failed to allocate memory"); 827 goto exit; 828 } 829 830 memset(&meta->info.backup_version_table, 0xff, 831 sizeof(meta->info.backup_version_table)); 832 meta->info.length = 0; 833 834 tee_res = tee_fs_generate_fek(meta->encrypted_fek, TEE_FS_KM_FEK_SIZE); 835 if (tee_res != TEE_SUCCESS) 836 goto exit; 837 838 meta->backup_version = default_backup_version; 839 840 res = write_meta_file(file, meta); 841 if (res < 0) 842 goto exit; 843 844 return meta; 845 846 exit: 847 free(meta); 848 849 return NULL; 850 } 851 852 static int commit_meta_file(struct tee_fs_fd *fdp, 853 struct tee_fs_file_meta *new_meta) 854 { 855 int res; 856 uint8_t old_version; 857 char meta_path[REE_FS_NAME_MAX]; 858 859 old_version = new_meta->backup_version; 860 new_meta->backup_version = !new_meta->backup_version; 861 862 res = write_meta_file(fdp->filename, new_meta); 863 864 if (res < 0) 865 return res; 866 867 /* 868 * From now on the new meta is successfully committed, 869 * change tee_fs_fd accordingly 870 */ 871 memcpy(fdp->meta, new_meta, sizeof(*new_meta)); 872 873 /* 874 * Remove outdated meta file, there is nothing we can 875 * do if we fail here, but that is OK because both 876 * new & old version of block files are kept. The context 877 * of the file is still consistent. 878 */ 879 get_meta_filepath(fdp->filename, old_version, meta_path); 880 ree_fs_unlink_ree(meta_path); 881 882 return res; 883 } 884 885 static int read_meta_file(const char *meta_path, 886 struct tee_fs_file_meta *meta) 887 { 888 int res, fd; 889 size_t meta_info_size = sizeof(struct tee_fs_file_info); 890 891 res = ree_fs_open_ree(meta_path, TEE_FS_O_RDWR); 892 if (res < 0) 893 return res; 894 895 fd = res; 896 897 res = read_and_decrypt_file(fd, META_FILE, 898 (void *)&meta->info, &meta_info_size, 899 meta->encrypted_fek); 900 901 ree_fs_close_ree(fd); 902 903 return res; 904 } 905 906 static struct tee_fs_file_meta *open_meta_file( 907 const char *file, int version) 908 { 909 int res; 910 char meta_path[REE_FS_NAME_MAX]; 911 struct tee_fs_file_meta *meta = NULL; 912 913 meta = malloc(sizeof(struct tee_fs_file_meta)); 914 if (!meta) 915 return NULL; 916 917 get_meta_filepath(file, version, meta_path); 918 res = read_meta_file(meta_path, meta); 919 if (res < 0) 920 goto exit_free_meta; 921 922 meta->backup_version = version; 923 924 return meta; 925 926 exit_free_meta: 927 free(meta); 928 return NULL; 929 } 930 931 static bool is_block_file_exist(struct tee_fs_file_meta *meta, 932 size_t block_num) 933 { 934 size_t file_size = meta->info.length; 935 936 if (file_size == 0) 937 return false; 938 939 return (block_num <= (size_t)get_last_block_num(file_size)); 940 } 941 942 #ifdef CFG_ENC_FS 943 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b) 944 { 945 int fd, res = 0; 946 uint8_t *plaintext = b->data; 947 char block_path[REE_FS_NAME_MAX]; 948 size_t block_file_size = BLOCK_FILE_SIZE; 949 uint8_t version = get_backup_version_of_block(fdp->meta, 950 b->block_num); 951 952 if (!is_block_file_exist(fdp->meta, b->block_num)) 953 goto exit; 954 955 get_block_filepath(fdp->filename, b->block_num, version, 956 block_path); 957 958 fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY); 959 if (fd < 0) 960 return fd; 961 962 res = read_and_decrypt_file(fd, BLOCK_FILE, 963 plaintext, &block_file_size, 964 fdp->meta->encrypted_fek); 965 if (res < 0) { 966 EMSG("Failed to read and decrypt file"); 967 goto fail; 968 } 969 b->data_size = block_file_size; 970 DMSG("Successfully read and decrypt block%d from storage, size=%zd", 971 b->block_num, b->data_size); 972 fail: 973 ree_fs_close_ree(fd); 974 exit: 975 return res; 976 } 977 978 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b, 979 struct tee_fs_file_meta *new_meta) 980 { 981 int fd = -1; 982 int res; 983 size_t block_num = b->block_num; 984 985 fd = create_block_file( 986 fdp, new_meta, block_num); 987 if (fd < 0) { 988 EMSG("Failed to create new version of block"); 989 res = -1; 990 goto fail; 991 } 992 993 res = encrypt_and_write_file(fd, BLOCK_FILE, 994 b->data, b->data_size, 995 new_meta->encrypted_fek); 996 if (res < 0) { 997 EMSG("Failed to encrypt and write block file"); 998 goto fail; 999 } 1000 DMSG("Successfully encrypt and write block%d to storage, size=%zd", 1001 b->block_num, b->data_size); 1002 1003 fail: 1004 if (fd > 0) 1005 ree_fs_close_ree(fd); 1006 1007 return res; 1008 } 1009 #else 1010 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b) 1011 { 1012 int fd, res = 0; 1013 char block_path[REE_FS_NAME_MAX]; 1014 size_t block_file_size = BLOCK_FILE_SIZE; 1015 uint8_t version = get_backup_version_of_block(fdp->meta, 1016 b->block_num); 1017 1018 if (!is_block_file_exist(fdp->meta, b->block_num)) 1019 goto exit; 1020 1021 get_block_filepath(fdp->filename, b->block_num, version, 1022 block_path); 1023 1024 fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY); 1025 if (fd < 0) 1026 return fd; 1027 1028 1029 res = ree_fs_read_ree(fd, b->data, block_file_size); 1030 if (res < 0) { 1031 EMSG("Failed to read block%d (%d)", 1032 b->block_num, res); 1033 goto fail; 1034 } 1035 1036 b->data_size = res; 1037 DMSG("Successfully read block%d from storage, size=%d", 1038 b->block_num, b->data_size); 1039 res = 0; 1040 fail: 1041 ree_fs_close_ree(fd); 1042 exit: 1043 return res; 1044 } 1045 1046 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b, 1047 struct tee_fs_file_meta *new_meta) 1048 { 1049 int fd = -1; 1050 int res; 1051 size_t block_num = b->block_num; 1052 1053 fd = create_block_file( 1054 fdp, new_meta, block_num); 1055 if (fd < 0) { 1056 EMSG("Failed to create new version of block"); 1057 res = -1; 1058 goto fail; 1059 } 1060 1061 res = ree_fs_write_ree(fd, b->data, b->data_size); 1062 if (res < 0) { 1063 EMSG("Failed to write block%d (%d)", 1064 b->block_num, res); 1065 goto fail; 1066 } 1067 DMSG("Successfully writen block%d to storage, size=%d", 1068 b->block_num, b->data_size); 1069 res = 0; 1070 fail: 1071 if (fd > 0) 1072 ree_fs_close_ree(fd); 1073 1074 return res; 1075 } 1076 #endif 1077 1078 static struct block *alloc_block(void) 1079 { 1080 struct block *c; 1081 1082 c = malloc(sizeof(struct block)); 1083 if (!c) 1084 return NULL; 1085 1086 c->data = malloc(BLOCK_FILE_SIZE); 1087 if (!c->data) { 1088 EMSG("unable to alloc memory for block data"); 1089 goto exit; 1090 } 1091 1092 c->block_num = -1; 1093 c->data_size = 0; 1094 1095 return c; 1096 1097 exit: 1098 free(c); 1099 return NULL; 1100 } 1101 1102 #ifdef CFG_FS_BLOCK_CACHE 1103 static void free_block(struct block *b) 1104 { 1105 if (b) { 1106 free(b->data); 1107 free(b); 1108 } 1109 } 1110 1111 static inline bool is_block_data_invalid(struct block *b) 1112 { 1113 return (b->data_size == 0); 1114 } 1115 1116 static void get_block_from_cache(struct block_cache *cache, 1117 int block_num, struct block **out_block) 1118 { 1119 struct block *b, *found = NULL; 1120 1121 DMSG("Try to find block%d in cache", block_num); 1122 TAILQ_FOREACH(b, &cache->block_lru, list) { 1123 if (b->block_num == block_num) { 1124 DMSG("Found in cache"); 1125 found = b; 1126 break; 1127 } 1128 } 1129 1130 if (found) { 1131 TAILQ_REMOVE(&cache->block_lru, found, list); 1132 TAILQ_INSERT_HEAD(&cache->block_lru, found, list); 1133 *out_block = found; 1134 return; 1135 } 1136 1137 DMSG("Not found, reuse oldest block on LRU list"); 1138 b = TAILQ_LAST(&cache->block_lru, block_head); 1139 TAILQ_REMOVE(&cache->block_lru, b, list); 1140 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 1141 b->block_num = block_num; 1142 b->data_size = 0; 1143 *out_block = b; 1144 } 1145 1146 static int init_block_cache(struct block_cache *cache) 1147 { 1148 struct block *b; 1149 1150 TAILQ_INIT(&cache->block_lru); 1151 cache->cached_block_num = 0; 1152 1153 while (cache->cached_block_num < MAX_NUM_CACHED_BLOCKS) { 1154 1155 b = alloc_block(); 1156 if (!b) { 1157 EMSG("Failed to alloc block"); 1158 goto fail; 1159 } else { 1160 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 1161 cache->cached_block_num++; 1162 } 1163 } 1164 return 0; 1165 1166 fail: 1167 TAILQ_FOREACH(b, &cache->block_lru, list) 1168 free_block(b); 1169 return -1; 1170 } 1171 1172 static void destroy_block_cache(struct block_cache *cache) 1173 { 1174 struct block *b, *next; 1175 1176 TAILQ_FOREACH_SAFE(b, &cache->block_lru, list, next) { 1177 TAILQ_REMOVE(&cache->block_lru, b, list); 1178 free_block(b); 1179 } 1180 } 1181 #else 1182 static int init_block_cache(struct block_cache *cache __unused) 1183 { 1184 return 0; 1185 } 1186 1187 static void destroy_block_cache(struct block_cache *cache __unused) 1188 { 1189 } 1190 #endif 1191 1192 static void write_data_to_block(struct block *b, int offset, 1193 void *buf, size_t len) 1194 { 1195 DMSG("Write %zd bytes to block%d", len, b->block_num); 1196 memcpy(b->data + offset, buf, len); 1197 if (offset + len > b->data_size) { 1198 b->data_size = offset + len; 1199 DMSG("Extend block%d size to %zd bytes", 1200 b->block_num, b->data_size); 1201 } 1202 } 1203 1204 static void read_data_from_block(struct block *b, int offset, 1205 void *buf, size_t len) 1206 { 1207 size_t bytes_to_read = len; 1208 1209 DMSG("Read %zd bytes from block%d", len, b->block_num); 1210 if (offset + len > b->data_size) { 1211 bytes_to_read = b->data_size - offset; 1212 DMSG("Exceed block size, update len to %zd bytes", 1213 bytes_to_read); 1214 } 1215 memcpy(buf, b->data + offset, bytes_to_read); 1216 } 1217 1218 #ifdef CFG_FS_BLOCK_CACHE 1219 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num) 1220 { 1221 struct block *b; 1222 1223 get_block_from_cache(&fdp->block_cache, block_num, &b); 1224 if (is_block_data_invalid(b)) 1225 if (read_block_from_storage(fdp, b)) { 1226 EMSG("Unable to read block%d from storage", 1227 block_num); 1228 return NULL; 1229 } 1230 1231 return b; 1232 } 1233 #else 1234 1235 static struct mutex block_mutex = MUTEX_INITIALIZER; 1236 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num) 1237 { 1238 static struct block *b; 1239 int res; 1240 1241 mutex_lock(&block_mutex); 1242 if (!b) 1243 b = alloc_block(); 1244 b->block_num = block_num; 1245 1246 res = read_block_from_storage(fdp, b); 1247 if (res) 1248 EMSG("Unable to read block%d from storage", 1249 block_num); 1250 mutex_unlock(&block_mutex); 1251 1252 return res ? NULL : b; 1253 } 1254 #endif 1255 1256 static struct block_operations block_ops = { 1257 #ifdef CFG_FS_BLOCK_CACHE 1258 .read = read_block_with_cache, 1259 #else 1260 .read = read_block_no_cache, 1261 #endif 1262 .write = flush_block_to_storage, 1263 }; 1264 1265 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf, 1266 size_t len, struct tee_fs_file_meta *new_meta) 1267 { 1268 int start_block_num = pos_to_block_num(fdp->pos); 1269 int end_block_num = pos_to_block_num(fdp->pos + len - 1); 1270 size_t remain_bytes = len; 1271 uint8_t *data_ptr = (uint8_t *)buf; 1272 int orig_pos = fdp->pos; 1273 1274 while (start_block_num <= end_block_num) { 1275 int offset = fdp->pos % BLOCK_FILE_SIZE; 1276 struct block *b; 1277 size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ? 1278 BLOCK_FILE_SIZE : remain_bytes; 1279 1280 if (size_to_write + offset > BLOCK_FILE_SIZE) 1281 size_to_write = BLOCK_FILE_SIZE - offset; 1282 1283 b = block_ops.read(fdp, start_block_num); 1284 if (!b) 1285 goto failed; 1286 1287 DMSG("Write data, offset: %d, size_to_write: %zd", 1288 offset, size_to_write); 1289 write_data_to_block(b, offset, data_ptr, size_to_write); 1290 1291 if (block_ops.write(fdp, b, new_meta)) { 1292 EMSG("Unable to wrtie block%d to storage", 1293 b->block_num); 1294 goto failed; 1295 } 1296 1297 data_ptr += size_to_write; 1298 remain_bytes -= size_to_write; 1299 start_block_num++; 1300 fdp->pos += size_to_write; 1301 } 1302 1303 if (fdp->pos > (tee_fs_off_t)new_meta->info.length) 1304 new_meta->info.length = fdp->pos; 1305 1306 return 0; 1307 failed: 1308 fdp->pos = orig_pos; 1309 return -1; 1310 } 1311 1312 static inline int create_hard_link(const char *old_dir, 1313 const char *new_dir, 1314 const char *filename) 1315 { 1316 char old_path[REE_FS_NAME_MAX]; 1317 char new_path[REE_FS_NAME_MAX]; 1318 1319 snprintf(old_path, REE_FS_NAME_MAX, "%s/%s", 1320 old_dir, filename); 1321 snprintf(new_path, REE_FS_NAME_MAX, "%s/%s", 1322 new_dir, filename); 1323 1324 DMSG("%s -> %s", old_path, new_path); 1325 return ree_fs_link_ree(old_path, new_path); 1326 } 1327 1328 static int unlink_tee_file(const char *file) 1329 { 1330 int res = -1; 1331 size_t len = strlen(file) + 1; 1332 struct tee_fs_dirent *dirent; 1333 struct tee_fs_dir *dir; 1334 1335 DMSG("file=%s", file); 1336 1337 if (len > TEE_FS_NAME_MAX) 1338 goto exit; 1339 1340 dir = ree_fs_opendir_ree(file); 1341 if (!dir) 1342 goto exit; 1343 1344 dirent = ree_fs_readdir_ree(dir); 1345 while (dirent) { 1346 char path[REE_FS_NAME_MAX]; 1347 1348 snprintf(path, REE_FS_NAME_MAX, "%s/%s", 1349 file, dirent->d_name); 1350 1351 DMSG("unlink %s", path); 1352 res = ree_fs_unlink_ree(path); 1353 if (res) { 1354 ree_fs_closedir_ree(dir); 1355 goto exit; 1356 } 1357 1358 dirent = ree_fs_readdir_ree(dir); 1359 } 1360 1361 res = ree_fs_closedir_ree(dir); 1362 if (res) 1363 goto exit; 1364 1365 res = ree_fs_rmdir_ree(file); 1366 exit: 1367 return res; 1368 } 1369 1370 static bool tee_file_exists(const char *file) 1371 { 1372 char meta_path[REE_FS_NAME_MAX]; 1373 1374 get_meta_filepath(file, 0, meta_path); 1375 if (ree_fs_access_ree(meta_path, TEE_FS_F_OK)) { 1376 get_meta_filepath(file, 1, meta_path); 1377 if (ree_fs_access_ree(meta_path, TEE_FS_F_OK)) 1378 return false; 1379 } 1380 1381 return true; 1382 } 1383 1384 static struct tee_fs_file_meta *create_tee_file(const char *file) 1385 { 1386 struct tee_fs_file_meta *meta = NULL; 1387 int res; 1388 1389 DMSG("Creating TEE file=%s", file); 1390 1391 /* create TEE file directory if not exist */ 1392 if (ree_fs_access_ree(file, TEE_FS_F_OK)) { 1393 res = ree_fs_mkdir_ree(file, 1394 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); 1395 if (res) { 1396 EMSG("Failed to create TEE file directory, res=%d", 1397 res); 1398 goto exit; 1399 } 1400 } 1401 1402 /* create meta file in TEE file directory */ 1403 meta = create_meta_file(file); 1404 if (!meta) 1405 EMSG("Failed to create new meta file"); 1406 1407 exit: 1408 return meta; 1409 } 1410 1411 static struct tee_fs_file_meta *open_tee_file(const char *file) 1412 { 1413 struct tee_fs_file_meta *meta = NULL; 1414 int backup_version = 0; 1415 1416 DMSG("Opening TEE file=%s", file); 1417 1418 meta = open_meta_file(file, backup_version); 1419 if (!meta) { 1420 meta = open_meta_file(file, !backup_version); 1421 if (!meta) { 1422 /* 1423 * cannot open meta file, assumed the TEE file 1424 * is corrupted 1425 */ 1426 EMSG("Can not open meta file"); 1427 } 1428 } 1429 1430 return meta; 1431 } 1432 1433 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1434 tee_fs_off_t new_file_len); 1435 1436 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...) 1437 { 1438 int res = -1; 1439 size_t len; 1440 struct tee_fs_file_meta *meta = NULL; 1441 struct tee_fs_fd *fdp = NULL; 1442 bool file_exist; 1443 1444 assert(errno); 1445 *errno = TEE_SUCCESS; 1446 1447 if (!file) { 1448 *errno = TEE_ERROR_BAD_PARAMETERS; 1449 goto exit; 1450 } 1451 1452 len = strlen(file) + 1; 1453 if (len > TEE_FS_NAME_MAX) { 1454 *errno = TEE_ERROR_BAD_PARAMETERS; 1455 goto exit; 1456 } 1457 1458 file_exist = tee_file_exists(file); 1459 if (flags & TEE_FS_O_CREATE) { 1460 if ((flags & TEE_FS_O_EXCL) && file_exist) { 1461 DMSG("tee file already exists"); 1462 *errno = TEE_ERROR_ACCESS_CONFLICT; 1463 goto exit; 1464 } 1465 1466 if (!file_exist) 1467 meta = create_tee_file(file); 1468 else 1469 meta = open_tee_file(file); 1470 1471 } else { 1472 if (!file_exist) { 1473 DMSG("tee file not exists"); 1474 *errno = TEE_ERROR_ITEM_NOT_FOUND; 1475 goto exit; 1476 } 1477 1478 meta = open_tee_file(file); 1479 } 1480 1481 if (!meta) { 1482 EMSG("Failed to open TEE file"); 1483 *errno = TEE_ERROR_CORRUPT_OBJECT; 1484 goto exit; 1485 } 1486 1487 DMSG("file=%s, length=%zd", file, meta->info.length); 1488 fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd)); 1489 if (!fdp) { 1490 *errno = TEE_ERROR_OUT_OF_MEMORY; 1491 goto exit_free_meta; 1492 } 1493 1494 /* init internal status */ 1495 fdp->flags = flags; 1496 fdp->meta = meta; 1497 fdp->pos = 0; 1498 if (init_block_cache(&fdp->block_cache)) { 1499 res = -1; 1500 goto exit_free_fd; 1501 } 1502 1503 fdp->filename = malloc(len); 1504 if (!fdp->filename) { 1505 res = -1; 1506 *errno = TEE_ERROR_OUT_OF_MEMORY; 1507 goto exit_destroy_block_cache; 1508 } 1509 memcpy(fdp->filename, file, len); 1510 1511 if ((flags & TEE_FS_O_TRUNC) && 1512 (flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) { 1513 res = ree_fs_ftruncate_internal(errno, fdp, 0); 1514 if (res < 0) { 1515 EMSG("Unable to truncate file"); 1516 goto exit_free_filename; 1517 } 1518 } 1519 1520 /* return fd */ 1521 res = handle_get(&fs_handle_db, fdp); 1522 if (res < 0) 1523 goto exit_free_filename; 1524 fdp->fd = res; 1525 goto exit; 1526 1527 exit_free_filename: 1528 free(fdp->filename); 1529 exit_destroy_block_cache: 1530 destroy_block_cache(&fdp->block_cache); 1531 exit_free_fd: 1532 free(fdp); 1533 exit_free_meta: 1534 free(meta); 1535 exit: 1536 return res; 1537 } 1538 1539 static int ree_fs_close(int fd) 1540 { 1541 int res = -1; 1542 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1543 1544 if (!fdp) 1545 return -1; 1546 1547 handle_put(&fs_handle_db, fdp->fd); 1548 1549 destroy_block_cache(&fdp->block_cache); 1550 free(fdp->meta); 1551 free(fdp->filename); 1552 free(fdp); 1553 1554 return res; 1555 } 1556 1557 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd, 1558 tee_fs_off_t offset, int whence) 1559 { 1560 tee_fs_off_t res = -1; 1561 tee_fs_off_t new_pos; 1562 size_t filelen; 1563 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1564 1565 assert(errno); 1566 *errno = TEE_SUCCESS; 1567 1568 if (!fdp) { 1569 *errno = TEE_ERROR_BAD_PARAMETERS; 1570 goto exit; 1571 } 1572 1573 DMSG("offset=%d, whence=%d", (int)offset, whence); 1574 1575 filelen = fdp->meta->info.length; 1576 1577 switch (whence) { 1578 case TEE_FS_SEEK_SET: 1579 new_pos = offset; 1580 break; 1581 1582 case TEE_FS_SEEK_CUR: 1583 new_pos = fdp->pos + offset; 1584 break; 1585 1586 case TEE_FS_SEEK_END: 1587 new_pos = filelen + offset; 1588 break; 1589 1590 default: 1591 *errno = TEE_ERROR_BAD_PARAMETERS; 1592 goto exit; 1593 } 1594 1595 if (new_pos < 0) 1596 new_pos = 0; 1597 1598 if (new_pos > TEE_DATA_MAX_POSITION) { 1599 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 1600 *errno = TEE_ERROR_BAD_PARAMETERS; 1601 goto exit; 1602 } 1603 1604 res = fdp->pos = new_pos; 1605 exit: 1606 return res; 1607 } 1608 1609 /* 1610 * To ensure atomic truncate operation, we can: 1611 * 1612 * - update file length to new length 1613 * - commit new meta 1614 * - free unused blocks 1615 * 1616 * To ensure atomic extend operation, we can: 1617 * 1618 * - update file length to new length 1619 * - allocate and fill zero data to new blocks 1620 * - commit new meta 1621 * 1622 * Any failure before committing new meta is considered as 1623 * update failed, and the file content will not be updated 1624 */ 1625 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1626 tee_fs_off_t new_file_len) 1627 { 1628 int res = -1; 1629 size_t old_file_len = fdp->meta->info.length; 1630 struct tee_fs_file_meta *new_meta = NULL; 1631 uint8_t *buf = NULL; 1632 1633 assert(errno); 1634 *errno = TEE_SUCCESS; 1635 1636 if (!fdp) { 1637 *errno = TEE_ERROR_BAD_PARAMETERS; 1638 res = -1; 1639 goto exit; 1640 } 1641 1642 if (fdp->flags & TEE_FS_O_RDONLY) { 1643 *errno = TEE_ERROR_BAD_PARAMETERS; 1644 EMSG("Read only"); 1645 res = -1; 1646 goto exit; 1647 } 1648 1649 if ((size_t)new_file_len == old_file_len) { 1650 DMSG("Ignore due to file length does not changed"); 1651 res = 0; 1652 goto exit; 1653 } 1654 1655 if (new_file_len > MAX_FILE_SIZE) { 1656 *errno = TEE_ERROR_BAD_PARAMETERS; 1657 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1658 res = -1; 1659 goto exit; 1660 } 1661 1662 new_meta = duplicate_meta(fdp); 1663 if (!new_meta) { 1664 *errno = TEE_ERROR_OUT_OF_MEMORY; 1665 res = -1; 1666 goto free; 1667 } 1668 1669 new_meta->info.length = new_file_len; 1670 1671 if ((size_t)new_file_len < old_file_len) { 1672 int old_block_num = get_last_block_num(old_file_len); 1673 int new_block_num = get_last_block_num(new_file_len); 1674 1675 DMSG("Truncate file length to %zu", (size_t)new_file_len); 1676 1677 res = commit_meta_file(fdp, new_meta); 1678 if (res < 0) { 1679 *errno = TEE_ERROR_CORRUPT_OBJECT; 1680 EMSG("Failed to commit meta file"); 1681 goto free; 1682 } 1683 1684 /* now we are safe to free unused blocks */ 1685 while (old_block_num > new_block_num) { 1686 if (remove_block_file(fdp, old_block_num)) { 1687 IMSG("Warning: Failed to free block: %d", 1688 old_block_num); 1689 } 1690 1691 old_block_num--; 1692 } 1693 1694 } else { 1695 size_t ext_len = new_file_len - old_file_len; 1696 int orig_pos = fdp->pos; 1697 1698 buf = malloc(BLOCK_FILE_SIZE); 1699 if (!buf) { 1700 *errno = TEE_ERROR_OUT_OF_MEMORY; 1701 EMSG("Failed to allocate buffer, size=%d", 1702 BLOCK_FILE_SIZE); 1703 res = -1; 1704 goto free; 1705 } 1706 1707 memset(buf, 0x0, BLOCK_FILE_SIZE); 1708 1709 DMSG("Extend file length to %zu", (size_t)new_file_len); 1710 1711 fdp->pos = old_file_len; 1712 1713 res = 0; 1714 while (ext_len > 0) { 1715 size_t data_len = (ext_len > BLOCK_FILE_SIZE) ? 1716 BLOCK_FILE_SIZE : ext_len; 1717 1718 DMSG("fill len=%zu", data_len); 1719 res = out_of_place_write(fdp, (void *)buf, 1720 data_len, new_meta); 1721 if (res < 0) { 1722 *errno = TEE_ERROR_CORRUPT_OBJECT; 1723 EMSG("Failed to fill data"); 1724 break; 1725 } 1726 1727 ext_len -= data_len; 1728 } 1729 1730 fdp->pos = orig_pos; 1731 1732 if (res == 0) { 1733 res = commit_meta_file(fdp, new_meta); 1734 if (res < 0) { 1735 *errno = TEE_ERROR_CORRUPT_OBJECT; 1736 EMSG("Failed to commit meta file"); 1737 } 1738 } 1739 } 1740 1741 free: 1742 free(new_meta); 1743 free(buf); 1744 1745 exit: 1746 return res; 1747 } 1748 1749 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len) 1750 { 1751 int res = -1; 1752 int start_block_num; 1753 int end_block_num; 1754 size_t remain_bytes = len; 1755 uint8_t *data_ptr = buf; 1756 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1757 1758 assert(errno); 1759 *errno = TEE_SUCCESS; 1760 1761 if (!fdp) { 1762 *errno = TEE_ERROR_BAD_PARAMETERS; 1763 goto exit; 1764 } 1765 1766 if (fdp->pos + len > fdp->meta->info.length) { 1767 len = fdp->meta->info.length - fdp->pos; 1768 DMSG("reached EOF, update read length to %zu", len); 1769 } 1770 1771 if (!len) { 1772 res = 0; 1773 goto exit; 1774 } 1775 1776 if (!buf) { 1777 *errno = TEE_ERROR_BAD_PARAMETERS; 1778 goto exit; 1779 } 1780 1781 if (fdp->flags & TEE_FS_O_WRONLY) { 1782 *errno = TEE_ERROR_ACCESS_CONFLICT; 1783 goto exit; 1784 } 1785 1786 DMSG("%s, data len=%zu", fdp->filename, len); 1787 1788 start_block_num = pos_to_block_num(fdp->pos); 1789 end_block_num = pos_to_block_num(fdp->pos + len - 1); 1790 DMSG("start_block_num:%d, end_block_num:%d", 1791 start_block_num, end_block_num); 1792 1793 while (start_block_num <= end_block_num) { 1794 struct block *b; 1795 int offset = fdp->pos % BLOCK_FILE_SIZE; 1796 size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ? 1797 BLOCK_FILE_SIZE : remain_bytes; 1798 1799 if (size_to_read + offset > BLOCK_FILE_SIZE) 1800 size_to_read = BLOCK_FILE_SIZE - offset; 1801 1802 DMSG("block_num:%d, offset:%d, size_to_read: %zd", 1803 start_block_num, offset, size_to_read); 1804 1805 b = block_ops.read(fdp, start_block_num); 1806 if (!b) { 1807 *errno = TEE_ERROR_CORRUPT_OBJECT; 1808 goto exit; 1809 } 1810 1811 read_data_from_block(b, offset, data_ptr, size_to_read); 1812 data_ptr += size_to_read; 1813 remain_bytes -= size_to_read; 1814 fdp->pos += size_to_read; 1815 1816 start_block_num++; 1817 } 1818 res = 0; 1819 exit: 1820 return (res < 0) ? res : (int)len; 1821 } 1822 1823 /* 1824 * To ensure atomicity of write operation, we need to 1825 * do the following steps: 1826 * (The sequence of operations is very important) 1827 * 1828 * - Create a new backup version of meta file as a copy 1829 * of current meta file. 1830 * - For each blocks to write: 1831 * - Create new backup version for current block. 1832 * - Write data to new backup version. 1833 * - Update the new meta file accordingly. 1834 * - Write the new meta file. 1835 * 1836 * (Any failure in above steps is considered as update failed, 1837 * and the file content will not be updated) 1838 * 1839 * After previous step the update is considered complete, but 1840 * we should do the following clean-up step(s): 1841 * 1842 * - Delete old meta file. 1843 * - Remove old block files. 1844 * 1845 * (Any failure in above steps is considered as a successfully 1846 * update) 1847 */ 1848 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len) 1849 { 1850 int res = -1; 1851 struct tee_fs_file_meta *new_meta = NULL; 1852 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 1853 size_t file_size; 1854 int orig_pos; 1855 1856 assert(errno); 1857 *errno = TEE_SUCCESS; 1858 1859 if (!fdp) { 1860 *errno = TEE_ERROR_BAD_PARAMETERS; 1861 goto exit; 1862 } 1863 if (!len) { 1864 res = 0; 1865 goto exit; 1866 } 1867 if (!buf) { 1868 *errno = TEE_ERROR_BAD_PARAMETERS; 1869 goto exit; 1870 } 1871 1872 file_size = fdp->meta->info.length; 1873 orig_pos = fdp->pos; 1874 1875 if (fdp->flags & TEE_FS_O_RDONLY) { 1876 EMSG("Write to a read-only file, denied"); 1877 *errno = TEE_ERROR_ACCESS_CONFLICT; 1878 goto exit; 1879 } 1880 1881 if ((fdp->pos + len) > MAX_FILE_SIZE) { 1882 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1883 *errno = TEE_ERROR_BAD_PARAMETERS; 1884 goto exit; 1885 } 1886 1887 DMSG("%s, data len=%zu", fdp->filename, len); 1888 if (file_size < (size_t)fdp->pos) { 1889 DMSG("File hole detected, try to extend file size"); 1890 res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos); 1891 if (res < 0) 1892 goto exit; 1893 } 1894 1895 new_meta = duplicate_meta(fdp); 1896 if (!new_meta) { 1897 *errno = TEE_ERROR_OUT_OF_MEMORY; 1898 goto exit; 1899 } 1900 1901 res = out_of_place_write(fdp, buf, len, new_meta); 1902 if (res < 0) { 1903 *errno = TEE_ERROR_CORRUPT_OBJECT; 1904 } else { 1905 int r; 1906 int start_block_num; 1907 int end_block_num; 1908 1909 r = commit_meta_file(fdp, new_meta); 1910 if (r < 0) { 1911 *errno = TEE_ERROR_CORRUPT_OBJECT; 1912 res = -1; 1913 } 1914 1915 /* we are safe to free old blocks */ 1916 start_block_num = pos_to_block_num(orig_pos); 1917 end_block_num = pos_to_block_num(fdp->pos - 1); 1918 while (start_block_num <= end_block_num) { 1919 if (remove_outdated_block(fdp, start_block_num)) 1920 IMSG("Warning: Failed to free old block: %d", 1921 start_block_num); 1922 1923 start_block_num++; 1924 } 1925 } 1926 exit: 1927 free(new_meta); 1928 return (res < 0) ? res : (int)len; 1929 } 1930 1931 /* 1932 * To ensure atomicity of rename operation, we need to 1933 * do the following steps: 1934 * 1935 * - Create a new folder that represents the renamed TEE file 1936 * - For each REE block files, create a hard link under the just 1937 * created folder (new TEE file) 1938 * - Now we are ready to commit meta, create hard link for the 1939 * meta file 1940 * 1941 * (Any failure in above steps is considered as update failed, 1942 * and the file content will not be updated) 1943 * 1944 * After previous step the update is considered complete, but 1945 * we should do the following clean-up step(s): 1946 * 1947 * - Unlink all REE files represents the old TEE file (including 1948 * meta and block files) 1949 * 1950 * (Any failure in above steps is considered as a successfully 1951 * update) 1952 */ 1953 static int ree_fs_rename(const char *old, const char *new) 1954 { 1955 int res = -1; 1956 size_t old_len; 1957 size_t new_len; 1958 size_t meta_count = 0; 1959 struct tee_fs_dir *old_dir; 1960 struct tee_fs_dirent *dirent; 1961 char *meta_filename = NULL; 1962 1963 if (!old || !new) 1964 return -1; 1965 1966 DMSG("old=%s, new=%s", old, new); 1967 1968 old_len = strlen(old) + 1; 1969 new_len = strlen(new) + 1; 1970 1971 if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX) 1972 goto exit; 1973 1974 res = ree_fs_mkdir_ree(new, 1975 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); 1976 if (res) 1977 goto exit; 1978 1979 old_dir = ree_fs_opendir_ree(old); 1980 if (!old_dir) 1981 goto exit; 1982 1983 dirent = ree_fs_readdir_ree(old_dir); 1984 while (dirent) { 1985 if (!strncmp(dirent->d_name, "meta.", 5)) { 1986 meta_filename = strdup(dirent->d_name); 1987 meta_count++; 1988 } else { 1989 res = create_hard_link(old, new, dirent->d_name); 1990 if (res) 1991 goto exit_close_old_dir; 1992 } 1993 1994 dirent = ree_fs_readdir_ree(old_dir); 1995 } 1996 1997 /* finally, link the meta file, rename operation completed */ 1998 TEE_ASSERT(meta_filename); 1999 2000 /* 2001 * TODO: This will cause memory leakage at previous strdup() 2002 * if we accidently have two meta files in a TEE file. 2003 * 2004 * It's not easy to handle the case above (e.g. Which meta file 2005 * should be linked first? What to do if a power cut happened 2006 * during creating links for the two meta files?) 2007 * 2008 * We will solve this issue using another approach: merging 2009 * both meta and block files into a single REE file. This approach 2010 * can completely remove ree_fs_rename(). We can simply 2011 * rename TEE file using REE rename() system call, which is also 2012 * atomic. 2013 */ 2014 if (meta_count > 1) 2015 EMSG("Warning: more than one meta file in your TEE file\n" 2016 "This will cause memory leakage."); 2017 2018 res = create_hard_link(old, new, meta_filename); 2019 if (res) 2020 goto exit_close_old_dir; 2021 2022 /* we are safe now, remove old TEE file */ 2023 unlink_tee_file(old); 2024 2025 exit_close_old_dir: 2026 ree_fs_closedir_ree(old_dir); 2027 exit: 2028 free(meta_filename); 2029 return res; 2030 } 2031 2032 /* 2033 * To ensure atomic unlink operation, we can simply 2034 * split the unlink operation into: 2035 * 2036 * - rename("file", "file.trash"); 2037 * 2038 * (Any failure in above steps is considered as update failed, 2039 * and the file content will not be updated) 2040 * 2041 * After previous step the update is considered complete, but 2042 * we should do the following clean-up step(s): 2043 * 2044 * - unlink("file.trash"); 2045 * 2046 * (Any failure in above steps is considered as a successfully 2047 * update) 2048 */ 2049 static int ree_fs_unlink(const char *file) 2050 { 2051 int res = -1; 2052 char trash_file[TEE_FS_NAME_MAX + 6]; 2053 2054 if (!file) 2055 return -1; 2056 2057 snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash", 2058 file); 2059 2060 res = ree_fs_rename(file, trash_file); 2061 if (res < 0) 2062 return res; 2063 2064 unlink_tee_file(trash_file); 2065 2066 return res; 2067 } 2068 2069 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length) 2070 { 2071 struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd); 2072 2073 return ree_fs_ftruncate_internal(errno, fdp, length); 2074 } 2075 2076 const struct tee_file_operations ree_fs_ops = { 2077 .open = ree_fs_open, 2078 .close = ree_fs_close, 2079 .read = ree_fs_read, 2080 .write = ree_fs_write, 2081 .lseek = ree_fs_lseek, 2082 .ftruncate = ree_fs_ftruncate, 2083 .rename = ree_fs_rename, 2084 .unlink = ree_fs_unlink, 2085 .mkdir = ree_fs_mkdir_ree, 2086 .opendir = ree_fs_opendir_ree, 2087 .closedir = ree_fs_closedir_ree, 2088 .readdir = ree_fs_readdir_ree, 2089 .rmdir = ree_fs_rmdir_ree, 2090 .access = ree_fs_access_ree 2091 }; 2092