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