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