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 tee_fs_off_t 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 DMSG("Read %zd bytes from block%d", len, b->block_num); 831 if (offset + len > b->data_size) 832 panic("Exceeding block size"); 833 memcpy(buf, b->data + offset, len); 834 } 835 836 #ifdef CFG_FS_BLOCK_CACHE 837 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num) 838 { 839 struct block *b; 840 841 get_block_from_cache(&fdp->block_cache, block_num, &b); 842 if (is_block_data_invalid(b)) 843 if (read_block_from_storage(fdp, b)) { 844 EMSG("Unable to read block%d from storage", 845 block_num); 846 return NULL; 847 } 848 849 return b; 850 } 851 #else 852 853 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num) 854 { 855 static struct block *b; 856 int res; 857 858 if (!b) 859 b = alloc_block(); 860 b->block_num = block_num; 861 862 res = read_block_from_storage(fdp, b); 863 if (res) 864 EMSG("Unable to read block%d from storage", 865 block_num); 866 867 return res ? NULL : b; 868 } 869 #endif 870 871 static struct block_operations block_ops = { 872 #ifdef CFG_FS_BLOCK_CACHE 873 .read = read_block_with_cache, 874 #else 875 .read = read_block_no_cache, 876 #endif 877 .write = flush_block_to_storage, 878 }; 879 880 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf, 881 size_t len, struct tee_fs_file_meta *new_meta) 882 { 883 int start_block_num = pos_to_block_num(fdp->pos); 884 int end_block_num = pos_to_block_num(fdp->pos + len - 1); 885 size_t remain_bytes = len; 886 uint8_t *data_ptr = (uint8_t *)buf; 887 int orig_pos = fdp->pos; 888 889 while (start_block_num <= end_block_num) { 890 int offset = fdp->pos % BLOCK_FILE_SIZE; 891 struct block *b; 892 size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ? 893 BLOCK_FILE_SIZE : remain_bytes; 894 895 if (size_to_write + offset > BLOCK_FILE_SIZE) 896 size_to_write = BLOCK_FILE_SIZE - offset; 897 898 b = block_ops.read(fdp, start_block_num); 899 if (!b) 900 goto failed; 901 902 DMSG("Write data, offset: %d, size_to_write: %zd", 903 offset, size_to_write); 904 write_data_to_block(b, offset, data_ptr, size_to_write); 905 906 if (block_ops.write(fdp, b, new_meta)) { 907 EMSG("Unable to wrtie block%d to storage", 908 b->block_num); 909 goto failed; 910 } 911 912 data_ptr += size_to_write; 913 remain_bytes -= size_to_write; 914 start_block_num++; 915 fdp->pos += size_to_write; 916 } 917 918 if (fdp->pos > (tee_fs_off_t)new_meta->info.length) 919 new_meta->info.length = fdp->pos; 920 921 return 0; 922 failed: 923 fdp->pos = orig_pos; 924 return -1; 925 } 926 927 static inline int create_hard_link(const char *old_dir, 928 const char *new_dir, 929 const char *filename) 930 { 931 char old_path[REE_FS_NAME_MAX]; 932 char new_path[REE_FS_NAME_MAX]; 933 934 snprintf(old_path, REE_FS_NAME_MAX, "%s/%s", 935 old_dir, filename); 936 snprintf(new_path, REE_FS_NAME_MAX, "%s/%s", 937 new_dir, filename); 938 939 DMSG("%s -> %s", old_path, new_path); 940 return tee_fs_rpc_link(OPTEE_MSG_RPC_CMD_FS, old_path, new_path); 941 } 942 943 static int unlink_tee_file(const char *file) 944 { 945 int res = -1; 946 size_t len = strlen(file) + 1; 947 struct tee_fs_dirent *dirent; 948 struct tee_fs_dir *dir; 949 950 DMSG("file=%s", file); 951 952 if (len > TEE_FS_NAME_MAX) 953 goto exit; 954 955 dir = ree_fs_opendir_rpc(file); 956 if (!dir) 957 goto exit; 958 959 dirent = ree_fs_readdir_rpc(dir); 960 while (dirent) { 961 char path[REE_FS_NAME_MAX]; 962 963 snprintf(path, REE_FS_NAME_MAX, "%s/%s", 964 file, dirent->d_name); 965 966 DMSG("unlink %s", path); 967 res = tee_fs_rpc_unlink(OPTEE_MSG_RPC_CMD_FS, path); 968 if (res) { 969 ree_fs_closedir_rpc(dir); 970 goto exit; 971 } 972 973 dirent = ree_fs_readdir_rpc(dir); 974 } 975 976 res = ree_fs_closedir_rpc(dir); 977 if (res) 978 goto exit; 979 980 res = ree_fs_rmdir_rpc(file); 981 exit: 982 return res; 983 } 984 985 static bool tee_file_exists(const char *file) 986 { 987 char meta_path[REE_FS_NAME_MAX]; 988 989 get_meta_filepath(file, 0, meta_path); 990 if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK)) { 991 get_meta_filepath(file, 1, meta_path); 992 if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK)) 993 return false; 994 } 995 996 return true; 997 } 998 999 static struct tee_fs_file_meta *create_tee_file(const char *file) 1000 { 1001 struct tee_fs_file_meta *meta = NULL; 1002 int res; 1003 1004 DMSG("Creating TEE file=%s", file); 1005 1006 /* create TEE file directory if not exist */ 1007 if (ree_fs_access_rpc(file, TEE_FS_F_OK)) { 1008 res = ree_fs_mkdir_rpc(file, 1009 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR | TEE_FS_S_IXUSR); 1010 if (res) { 1011 EMSG("Failed to create TEE file directory, res=%d", 1012 res); 1013 goto exit; 1014 } 1015 } 1016 1017 /* create meta file in TEE file directory */ 1018 meta = create_meta_file(file); 1019 if (!meta) 1020 EMSG("Failed to create new meta file"); 1021 1022 exit: 1023 return meta; 1024 } 1025 1026 static struct tee_fs_file_meta *open_tee_file(const char *file) 1027 { 1028 struct tee_fs_file_meta *meta = NULL; 1029 int backup_version = 0; 1030 1031 DMSG("Opening TEE file=%s", file); 1032 1033 meta = open_meta_file(file, backup_version); 1034 if (!meta) { 1035 meta = open_meta_file(file, !backup_version); 1036 if (!meta) { 1037 /* 1038 * cannot open meta file, assumed the TEE file 1039 * is corrupted 1040 */ 1041 EMSG("Can not open meta file"); 1042 } 1043 } 1044 1045 return meta; 1046 } 1047 1048 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1049 tee_fs_off_t new_file_len); 1050 1051 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...) 1052 { 1053 int res = -1; 1054 size_t len; 1055 struct tee_fs_file_meta *meta = NULL; 1056 struct tee_fs_fd *fdp = NULL; 1057 bool file_exist; 1058 1059 mutex_lock(&ree_fs_mutex); 1060 1061 assert(errno); 1062 *errno = TEE_SUCCESS; 1063 1064 if (!file) { 1065 *errno = TEE_ERROR_BAD_PARAMETERS; 1066 goto exit; 1067 } 1068 1069 len = strlen(file) + 1; 1070 if (len > TEE_FS_NAME_MAX) { 1071 *errno = TEE_ERROR_BAD_PARAMETERS; 1072 goto exit; 1073 } 1074 1075 file_exist = tee_file_exists(file); 1076 if (flags & TEE_FS_O_CREATE) { 1077 if ((flags & TEE_FS_O_EXCL) && file_exist) { 1078 DMSG("tee file already exists"); 1079 *errno = TEE_ERROR_ACCESS_CONFLICT; 1080 goto exit; 1081 } 1082 1083 if (!file_exist) 1084 meta = create_tee_file(file); 1085 else 1086 meta = open_tee_file(file); 1087 1088 } else { 1089 if (!file_exist) { 1090 DMSG("tee file not exists"); 1091 *errno = TEE_ERROR_ITEM_NOT_FOUND; 1092 goto exit; 1093 } 1094 1095 meta = open_tee_file(file); 1096 } 1097 1098 if (!meta) { 1099 EMSG("Failed to open TEE file"); 1100 *errno = TEE_ERROR_CORRUPT_OBJECT; 1101 goto exit; 1102 } 1103 1104 DMSG("file=%s, length=%zd", file, meta->info.length); 1105 fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd)); 1106 if (!fdp) { 1107 *errno = TEE_ERROR_OUT_OF_MEMORY; 1108 goto exit_free_meta; 1109 } 1110 1111 /* init internal status */ 1112 fdp->flags = flags; 1113 fdp->meta = meta; 1114 fdp->pos = 0; 1115 if (init_block_cache(&fdp->block_cache)) { 1116 res = -1; 1117 goto exit_free_fd; 1118 } 1119 1120 fdp->filename = malloc(len); 1121 if (!fdp->filename) { 1122 res = -1; 1123 *errno = TEE_ERROR_OUT_OF_MEMORY; 1124 goto exit_destroy_block_cache; 1125 } 1126 memcpy(fdp->filename, file, len); 1127 1128 if ((flags & TEE_FS_O_TRUNC) && 1129 (flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) { 1130 res = ree_fs_ftruncate_internal(errno, fdp, 0); 1131 if (res < 0) { 1132 EMSG("Unable to truncate file"); 1133 goto exit_free_filename; 1134 } 1135 } 1136 1137 /* return fd */ 1138 res = handle_get(&fs_handle_db, fdp); 1139 if (res < 0) 1140 goto exit_free_filename; 1141 fdp->fd = res; 1142 goto exit; 1143 1144 exit_free_filename: 1145 free(fdp->filename); 1146 exit_destroy_block_cache: 1147 destroy_block_cache(&fdp->block_cache); 1148 exit_free_fd: 1149 free(fdp); 1150 exit_free_meta: 1151 free(meta); 1152 exit: 1153 mutex_unlock(&ree_fs_mutex); 1154 return res; 1155 } 1156 1157 static int ree_fs_close(int fd) 1158 { 1159 int res = -1; 1160 struct tee_fs_fd *fdp; 1161 1162 mutex_lock(&ree_fs_mutex); 1163 1164 fdp = handle_lookup(&fs_handle_db, fd); 1165 if (!fdp) 1166 goto exit; 1167 1168 handle_put(&fs_handle_db, fdp->fd); 1169 1170 destroy_block_cache(&fdp->block_cache); 1171 free(fdp->meta); 1172 free(fdp->filename); 1173 free(fdp); 1174 1175 exit: 1176 mutex_unlock(&ree_fs_mutex); 1177 return res; 1178 } 1179 1180 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd, 1181 tee_fs_off_t offset, int whence) 1182 { 1183 tee_fs_off_t res = -1; 1184 tee_fs_off_t new_pos; 1185 size_t filelen; 1186 struct tee_fs_fd *fdp; 1187 1188 mutex_lock(&ree_fs_mutex); 1189 1190 assert(errno); 1191 *errno = TEE_SUCCESS; 1192 1193 fdp = handle_lookup(&fs_handle_db, fd); 1194 if (!fdp) { 1195 *errno = TEE_ERROR_BAD_PARAMETERS; 1196 goto exit; 1197 } 1198 1199 DMSG("offset=%d, whence=%d", (int)offset, whence); 1200 1201 filelen = fdp->meta->info.length; 1202 1203 switch (whence) { 1204 case TEE_FS_SEEK_SET: 1205 new_pos = offset; 1206 break; 1207 1208 case TEE_FS_SEEK_CUR: 1209 new_pos = fdp->pos + offset; 1210 break; 1211 1212 case TEE_FS_SEEK_END: 1213 new_pos = filelen + offset; 1214 break; 1215 1216 default: 1217 *errno = TEE_ERROR_BAD_PARAMETERS; 1218 goto exit; 1219 } 1220 1221 if (new_pos < 0) 1222 new_pos = 0; 1223 1224 if (new_pos > TEE_DATA_MAX_POSITION) { 1225 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 1226 *errno = TEE_ERROR_BAD_PARAMETERS; 1227 goto exit; 1228 } 1229 1230 res = fdp->pos = new_pos; 1231 exit: 1232 mutex_unlock(&ree_fs_mutex); 1233 return res; 1234 } 1235 1236 /* 1237 * To ensure atomic truncate operation, we can: 1238 * 1239 * - update file length to new length 1240 * - commit new meta 1241 * - free unused blocks 1242 * 1243 * To ensure atomic extend operation, we can: 1244 * 1245 * - update file length to new length 1246 * - allocate and fill zero data to new blocks 1247 * - commit new meta 1248 * 1249 * Any failure before committing new meta is considered as 1250 * update failed, and the file content will not be updated 1251 */ 1252 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp, 1253 tee_fs_off_t new_file_len) 1254 { 1255 int res = -1; 1256 size_t old_file_len = fdp->meta->info.length; 1257 struct tee_fs_file_meta *new_meta = NULL; 1258 uint8_t *buf = NULL; 1259 1260 assert(errno); 1261 *errno = TEE_SUCCESS; 1262 1263 if (!fdp) { 1264 *errno = TEE_ERROR_BAD_PARAMETERS; 1265 res = -1; 1266 goto exit; 1267 } 1268 1269 if (fdp->flags & TEE_FS_O_RDONLY) { 1270 *errno = TEE_ERROR_BAD_PARAMETERS; 1271 EMSG("Read only"); 1272 res = -1; 1273 goto exit; 1274 } 1275 1276 if ((size_t)new_file_len == old_file_len) { 1277 DMSG("Ignore due to file length does not changed"); 1278 res = 0; 1279 goto exit; 1280 } 1281 1282 if (new_file_len > MAX_FILE_SIZE) { 1283 *errno = TEE_ERROR_BAD_PARAMETERS; 1284 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1285 res = -1; 1286 goto exit; 1287 } 1288 1289 new_meta = duplicate_meta(fdp); 1290 if (!new_meta) { 1291 *errno = TEE_ERROR_OUT_OF_MEMORY; 1292 res = -1; 1293 goto free; 1294 } 1295 1296 new_meta->info.length = new_file_len; 1297 1298 if ((size_t)new_file_len < old_file_len) { 1299 int old_block_num = get_last_block_num(old_file_len); 1300 int new_block_num = get_last_block_num(new_file_len); 1301 1302 DMSG("Truncate file length to %zu", (size_t)new_file_len); 1303 1304 res = commit_meta_file(fdp, new_meta); 1305 if (res < 0) { 1306 *errno = TEE_ERROR_CORRUPT_OBJECT; 1307 EMSG("Failed to commit meta file"); 1308 goto free; 1309 } 1310 1311 /* now we are safe to free unused blocks */ 1312 while (old_block_num > new_block_num) { 1313 if (remove_block_file(fdp, old_block_num)) { 1314 IMSG("Warning: Failed to free block: %d", 1315 old_block_num); 1316 } 1317 1318 old_block_num--; 1319 } 1320 1321 } else { 1322 size_t ext_len = new_file_len - old_file_len; 1323 int orig_pos = fdp->pos; 1324 1325 buf = malloc(BLOCK_FILE_SIZE); 1326 if (!buf) { 1327 *errno = TEE_ERROR_OUT_OF_MEMORY; 1328 EMSG("Failed to allocate buffer, size=%d", 1329 BLOCK_FILE_SIZE); 1330 res = -1; 1331 goto free; 1332 } 1333 1334 memset(buf, 0x0, BLOCK_FILE_SIZE); 1335 1336 DMSG("Extend file length to %zu", (size_t)new_file_len); 1337 1338 fdp->pos = old_file_len; 1339 1340 res = 0; 1341 while (ext_len > 0) { 1342 size_t data_len = (ext_len > BLOCK_FILE_SIZE) ? 1343 BLOCK_FILE_SIZE : ext_len; 1344 1345 DMSG("fill len=%zu", data_len); 1346 res = out_of_place_write(fdp, (void *)buf, 1347 data_len, new_meta); 1348 if (res < 0) { 1349 *errno = TEE_ERROR_CORRUPT_OBJECT; 1350 EMSG("Failed to fill data"); 1351 break; 1352 } 1353 1354 ext_len -= data_len; 1355 } 1356 1357 fdp->pos = orig_pos; 1358 1359 if (res == 0) { 1360 res = commit_meta_file(fdp, new_meta); 1361 if (res < 0) { 1362 *errno = TEE_ERROR_CORRUPT_OBJECT; 1363 EMSG("Failed to commit meta file"); 1364 } 1365 } 1366 } 1367 1368 free: 1369 free(new_meta); 1370 free(buf); 1371 1372 exit: 1373 return res; 1374 } 1375 1376 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len) 1377 { 1378 int res = -1; 1379 int start_block_num; 1380 int end_block_num; 1381 size_t remain_bytes = len; 1382 uint8_t *data_ptr = buf; 1383 struct tee_fs_fd *fdp; 1384 1385 mutex_lock(&ree_fs_mutex); 1386 1387 assert(errno); 1388 *errno = TEE_SUCCESS; 1389 1390 fdp = handle_lookup(&fs_handle_db, fd); 1391 if (!fdp) { 1392 *errno = TEE_ERROR_BAD_PARAMETERS; 1393 goto exit; 1394 } 1395 1396 if ((fdp->pos + len) < len || 1397 fdp->pos > (tee_fs_off_t)fdp->meta->info.length) 1398 len = 0; 1399 else if (fdp->pos + len > fdp->meta->info.length) 1400 len = fdp->meta->info.length - fdp->pos; 1401 1402 if (!len) { 1403 res = 0; 1404 goto exit; 1405 } 1406 1407 if (!buf) { 1408 *errno = TEE_ERROR_BAD_PARAMETERS; 1409 goto exit; 1410 } 1411 1412 if (fdp->flags & TEE_FS_O_WRONLY) { 1413 *errno = TEE_ERROR_ACCESS_CONFLICT; 1414 goto exit; 1415 } 1416 1417 DMSG("%s, data len=%zu", fdp->filename, len); 1418 1419 start_block_num = pos_to_block_num(fdp->pos); 1420 end_block_num = pos_to_block_num(fdp->pos + len - 1); 1421 DMSG("start_block_num:%d, end_block_num:%d", 1422 start_block_num, end_block_num); 1423 1424 while (start_block_num <= end_block_num) { 1425 struct block *b; 1426 int offset = fdp->pos % BLOCK_FILE_SIZE; 1427 size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ? 1428 BLOCK_FILE_SIZE : remain_bytes; 1429 1430 if (size_to_read + offset > BLOCK_FILE_SIZE) 1431 size_to_read = BLOCK_FILE_SIZE - offset; 1432 1433 DMSG("block_num:%d, offset:%d, size_to_read: %zd", 1434 start_block_num, offset, size_to_read); 1435 1436 b = block_ops.read(fdp, start_block_num); 1437 if (!b) { 1438 *errno = TEE_ERROR_CORRUPT_OBJECT; 1439 goto exit; 1440 } 1441 1442 read_data_from_block(b, offset, data_ptr, size_to_read); 1443 data_ptr += size_to_read; 1444 remain_bytes -= size_to_read; 1445 fdp->pos += size_to_read; 1446 1447 start_block_num++; 1448 } 1449 res = 0; 1450 exit: 1451 mutex_unlock(&ree_fs_mutex); 1452 return (res < 0) ? res : (int)len; 1453 } 1454 1455 /* 1456 * To ensure atomicity of write operation, we need to 1457 * do the following steps: 1458 * (The sequence of operations is very important) 1459 * 1460 * - Create a new backup version of meta file as a copy 1461 * of current meta file. 1462 * - For each blocks to write: 1463 * - Create new backup version for current block. 1464 * - Write data to new backup version. 1465 * - Update the new meta file accordingly. 1466 * - Write the new meta file. 1467 * 1468 * (Any failure in above steps is considered as update failed, 1469 * and the file content will not be updated) 1470 * 1471 * After previous step the update is considered complete, but 1472 * we should do the following clean-up step(s): 1473 * 1474 * - Delete old meta file. 1475 * - Remove old block files. 1476 * 1477 * (Any failure in above steps is considered as a successfully 1478 * update) 1479 */ 1480 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len) 1481 { 1482 int res = -1; 1483 struct tee_fs_file_meta *new_meta = NULL; 1484 struct tee_fs_fd *fdp; 1485 size_t file_size; 1486 int orig_pos; 1487 1488 mutex_lock(&ree_fs_mutex); 1489 1490 assert(errno); 1491 *errno = TEE_SUCCESS; 1492 1493 fdp = handle_lookup(&fs_handle_db, fd); 1494 if (!fdp) { 1495 *errno = TEE_ERROR_BAD_PARAMETERS; 1496 goto exit; 1497 } 1498 if (!len) { 1499 res = 0; 1500 goto exit; 1501 } 1502 if (!buf) { 1503 *errno = TEE_ERROR_BAD_PARAMETERS; 1504 goto exit; 1505 } 1506 1507 file_size = fdp->meta->info.length; 1508 orig_pos = fdp->pos; 1509 1510 if (fdp->flags & TEE_FS_O_RDONLY) { 1511 EMSG("Write to a read-only file, denied"); 1512 *errno = TEE_ERROR_ACCESS_CONFLICT; 1513 goto exit; 1514 } 1515 1516 if ((fdp->pos + len) > MAX_FILE_SIZE) { 1517 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1518 *errno = TEE_ERROR_BAD_PARAMETERS; 1519 goto exit; 1520 } 1521 1522 DMSG("%s, data len=%zu", fdp->filename, len); 1523 if (file_size < (size_t)fdp->pos) { 1524 DMSG("File hole detected, try to extend file size"); 1525 res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos); 1526 if (res < 0) 1527 goto exit; 1528 } 1529 1530 new_meta = duplicate_meta(fdp); 1531 if (!new_meta) { 1532 *errno = TEE_ERROR_OUT_OF_MEMORY; 1533 goto exit; 1534 } 1535 1536 res = out_of_place_write(fdp, buf, len, new_meta); 1537 if (res < 0) { 1538 *errno = TEE_ERROR_CORRUPT_OBJECT; 1539 } else { 1540 int r; 1541 int start_block_num; 1542 int end_block_num; 1543 1544 r = commit_meta_file(fdp, new_meta); 1545 if (r < 0) { 1546 *errno = TEE_ERROR_CORRUPT_OBJECT; 1547 res = -1; 1548 } 1549 1550 /* we are safe to free old blocks */ 1551 start_block_num = pos_to_block_num(orig_pos); 1552 end_block_num = pos_to_block_num(fdp->pos - 1); 1553 while (start_block_num <= end_block_num) { 1554 if (remove_outdated_block(fdp, start_block_num)) 1555 IMSG("Warning: Failed to free old block: %d", 1556 start_block_num); 1557 1558 start_block_num++; 1559 } 1560 } 1561 exit: 1562 mutex_unlock(&ree_fs_mutex); 1563 free(new_meta); 1564 return (res < 0) ? res : (int)len; 1565 } 1566 1567 /* 1568 * To ensure atomicity of rename operation, we need to 1569 * do the following steps: 1570 * 1571 * - Create a new folder that represents the renamed TEE file 1572 * - For each REE block files, create a hard link under the just 1573 * created folder (new TEE file) 1574 * - Now we are ready to commit meta, create hard link for the 1575 * meta file 1576 * 1577 * (Any failure in above steps is considered as update failed, 1578 * and the file content will not be updated) 1579 * 1580 * After previous step the update is considered complete, but 1581 * we should do the following clean-up step(s): 1582 * 1583 * - Unlink all REE files represents the old TEE file (including 1584 * meta and block files) 1585 * 1586 * (Any failure in above steps is considered as a successfully 1587 * update) 1588 */ 1589 static int ree_fs_rename_internal(const char *old, const char *new) 1590 { 1591 int res = -1; 1592 size_t old_len; 1593 size_t new_len; 1594 size_t meta_count = 0; 1595 struct tee_fs_dir *old_dir; 1596 struct tee_fs_dirent *dirent; 1597 char *meta_filename = NULL; 1598 1599 if (!old || !new) 1600 return -1; 1601 1602 DMSG("old=%s, new=%s", old, new); 1603 1604 old_len = strlen(old) + 1; 1605 new_len = strlen(new) + 1; 1606 1607 if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX) 1608 goto exit; 1609 1610 res = ree_fs_mkdir_rpc(new, 1611 TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); 1612 if (res) 1613 goto exit; 1614 1615 old_dir = ree_fs_opendir_rpc(old); 1616 if (!old_dir) 1617 goto exit; 1618 1619 dirent = ree_fs_readdir_rpc(old_dir); 1620 while (dirent) { 1621 if (!strncmp(dirent->d_name, "meta.", 5)) { 1622 meta_filename = strdup(dirent->d_name); 1623 meta_count++; 1624 } else { 1625 res = create_hard_link(old, new, dirent->d_name); 1626 if (res) 1627 goto exit_close_old_dir; 1628 } 1629 1630 dirent = ree_fs_readdir_rpc(old_dir); 1631 } 1632 1633 /* finally, link the meta file, rename operation completed */ 1634 if (!meta_filename) 1635 panic("no meta file"); 1636 1637 /* 1638 * TODO: This will cause memory leakage at previous strdup() 1639 * if we accidently have two meta files in a TEE file. 1640 * 1641 * It's not easy to handle the case above (e.g. Which meta file 1642 * should be linked first? What to do if a power cut happened 1643 * during creating links for the two meta files?) 1644 * 1645 * We will solve this issue using another approach: merging 1646 * both meta and block files into a single REE file. This approach 1647 * can completely remove ree_fs_rename(). We can simply 1648 * rename TEE file using REE rename() system call, which is also 1649 * atomic. 1650 */ 1651 if (meta_count > 1) 1652 EMSG("Warning: more than one meta file in your TEE file\n" 1653 "This will cause memory leakage."); 1654 1655 res = create_hard_link(old, new, meta_filename); 1656 if (res) 1657 goto exit_close_old_dir; 1658 1659 /* we are safe now, remove old TEE file */ 1660 unlink_tee_file(old); 1661 1662 exit_close_old_dir: 1663 ree_fs_closedir_rpc(old_dir); 1664 exit: 1665 free(meta_filename); 1666 return res; 1667 } 1668 1669 static int ree_fs_rename(const char *old, const char *new) 1670 { 1671 int res; 1672 1673 mutex_lock(&ree_fs_mutex); 1674 res = ree_fs_rename_internal(old, new); 1675 mutex_unlock(&ree_fs_mutex); 1676 1677 return res; 1678 } 1679 1680 /* 1681 * To ensure atomic unlink operation, we can simply 1682 * split the unlink operation into: 1683 * 1684 * - rename("file", "file.trash"); 1685 * 1686 * (Any failure in above steps is considered as update failed, 1687 * and the file content will not be updated) 1688 * 1689 * After previous step the update is considered complete, but 1690 * we should do the following clean-up step(s): 1691 * 1692 * - unlink("file.trash"); 1693 * 1694 * (Any failure in above steps is considered as a successfully 1695 * update) 1696 */ 1697 static int ree_fs_unlink(const char *file) 1698 { 1699 int res = -1; 1700 char trash_file[TEE_FS_NAME_MAX + 6]; 1701 1702 if (!file) 1703 return -1; 1704 1705 snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash", 1706 file); 1707 1708 mutex_lock(&ree_fs_mutex); 1709 1710 res = ree_fs_rename_internal(file, trash_file); 1711 if (res < 0) 1712 goto exit; 1713 1714 unlink_tee_file(trash_file); 1715 1716 exit: 1717 mutex_unlock(&ree_fs_mutex); 1718 return res; 1719 } 1720 1721 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length) 1722 { 1723 struct tee_fs_fd *fdp; 1724 int res; 1725 1726 mutex_lock(&ree_fs_mutex); 1727 fdp = handle_lookup(&fs_handle_db, fd); 1728 res = ree_fs_ftruncate_internal(errno, fdp, length); 1729 mutex_unlock(&ree_fs_mutex); 1730 1731 return res; 1732 } 1733 1734 const struct tee_file_operations ree_fs_ops = { 1735 .open = ree_fs_open, 1736 .close = ree_fs_close, 1737 .read = ree_fs_read, 1738 .write = ree_fs_write, 1739 .lseek = ree_fs_lseek, 1740 .ftruncate = ree_fs_ftruncate, 1741 .rename = ree_fs_rename, 1742 .unlink = ree_fs_unlink, 1743 .mkdir = ree_fs_mkdir_rpc, 1744 .opendir = ree_fs_opendir_rpc, 1745 .closedir = ree_fs_closedir_rpc, 1746 .readdir = ree_fs_readdir_rpc, 1747 .rmdir = ree_fs_rmdir_rpc, 1748 .access = ree_fs_access_rpc 1749 }; 1750