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