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/mutex.h> 31 #include <kernel/panic.h> 32 #include <mm/core_memprot.h> 33 #include <optee_msg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <string_ext.h> 38 #include <sys/queue.h> 39 #include <tee/tee_cryp_provider.h> 40 #include <tee/tee_fs.h> 41 #include <tee/tee_fs_defs.h> 42 #include <tee/tee_fs_rpc.h> 43 #include <tee/tee_fs_key_manager.h> 44 #include <trace.h> 45 #include <utee_defines.h> 46 #include <util.h> 47 48 #define BLOCK_FILE_SHIFT 12 49 50 #define BLOCK_FILE_SIZE (1 << BLOCK_FILE_SHIFT) 51 52 #define MAX_NUM_CACHED_BLOCKS 1 53 54 #define NUM_BLOCKS_PER_FILE 1024 55 56 #define MAX_FILE_SIZE (BLOCK_FILE_SIZE * NUM_BLOCKS_PER_FILE) 57 58 struct tee_fs_file_info { 59 size_t length; 60 uint32_t backup_version_table[NUM_BLOCKS_PER_FILE / 32]; 61 }; 62 63 struct tee_fs_file_meta { 64 struct tee_fs_file_info info; 65 uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE]; 66 uint8_t backup_version; 67 }; 68 69 TAILQ_HEAD(block_head, block); 70 71 struct block { 72 TAILQ_ENTRY(block) list; 73 int block_num; 74 uint8_t *data; 75 size_t data_size; 76 }; 77 78 struct block_cache { 79 struct block_head block_lru; 80 uint8_t cached_block_num; 81 }; 82 83 struct tee_fs_fd { 84 struct tee_fs_file_meta meta; 85 tee_fs_off_t pos; 86 uint32_t flags; 87 bool is_new_file; 88 char *filename; 89 struct block_cache block_cache; 90 }; 91 92 static inline int pos_to_block_num(int position) 93 { 94 return position >> BLOCK_FILE_SHIFT; 95 } 96 97 static inline int get_last_block_num(size_t size) 98 { 99 return pos_to_block_num(size - 1); 100 } 101 102 static inline uint8_t get_backup_version_of_block( 103 struct tee_fs_file_meta *meta, 104 size_t block_num) 105 { 106 uint32_t index = (block_num / 32); 107 uint32_t block_mask = 1 << (block_num % 32); 108 109 return !!(meta->info.backup_version_table[index] & block_mask); 110 } 111 112 static inline void toggle_backup_version_of_block( 113 struct tee_fs_file_meta *meta, 114 size_t block_num) 115 { 116 uint32_t index = (block_num / 32); 117 uint32_t block_mask = 1 << (block_num % 32); 118 119 meta->info.backup_version_table[index] ^= block_mask; 120 } 121 122 struct block_operations { 123 124 /* 125 * Read a block from REE File System which is corresponding 126 * to the given block_num. 127 */ 128 struct block *(*read)(struct tee_fs_fd *fdp, int block_num); 129 130 /* 131 * Write the given block to REE File System 132 */ 133 int (*write)(struct tee_fs_fd *fdp, struct block *b, 134 struct tee_fs_file_meta *new_meta); 135 }; 136 137 static struct mutex ree_fs_mutex = MUTEX_INITIALIZER; 138 139 /* 140 * We split a TEE file into multiple blocks and store them 141 * on REE filesystem. A TEE file is represented by a REE file 142 * called meta and a number of REE files called blocks. Meta 143 * file is used for storing file information, e.g. file size 144 * and backup version of each block. 145 * 146 * REE files naming rule is as follows: 147 * 148 * <tee_file_name>/meta.<backup_version> 149 * <tee_file_name>/block0.<backup_version> 150 * ... 151 * <tee_file_name>/block15.<backup_version> 152 * 153 * Backup_version is used to support atomic update operation. 154 * Original file will not be updated, instead we create a new 155 * version of the same file and update the new file instead. 156 * 157 * The backup_version of each block file is stored in meta 158 * file, the meta file itself also has backup_version, the update is 159 * successful after new version of meta has been written. 160 */ 161 #define REE_FS_NAME_MAX (TEE_FS_NAME_MAX + 20) 162 163 164 static int ree_fs_mkdir_rpc(const char *path, tee_fs_mode_t mode) 165 { 166 return tee_fs_rpc_mkdir(OPTEE_MSG_RPC_CMD_FS, path, mode); 167 } 168 169 static TEE_Result ree_fs_opendir_rpc(const char *name, struct tee_fs_dir **d) 170 171 { 172 return tee_fs_rpc_new_opendir(OPTEE_MSG_RPC_CMD_FS, name, d); 173 } 174 175 static void ree_fs_closedir_rpc(struct tee_fs_dir *d) 176 { 177 if (d) 178 tee_fs_rpc_new_closedir(OPTEE_MSG_RPC_CMD_FS, d); 179 } 180 181 static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d, 182 struct tee_fs_dirent **ent) 183 { 184 return tee_fs_rpc_new_readdir(OPTEE_MSG_RPC_CMD_FS, d, ent); 185 } 186 187 static int ree_fs_access_rpc(const char *name, int mode) 188 { 189 return tee_fs_rpc_access(OPTEE_MSG_RPC_CMD_FS, name, mode); 190 } 191 192 static void get_meta_filepath(const char *file, int version, 193 char *meta_path) 194 { 195 snprintf(meta_path, REE_FS_NAME_MAX, "%s/meta.%d", 196 file, version); 197 } 198 199 static void get_block_filepath(const char *file, size_t block_num, 200 int version, char *meta_path) 201 { 202 snprintf(meta_path, REE_FS_NAME_MAX, "%s/block%zu.%d", 203 file, block_num, version); 204 } 205 206 static int __remove_block_file(struct tee_fs_fd *fdp, size_t block_num, 207 bool toggle) 208 { 209 TEE_Result res; 210 char block_path[REE_FS_NAME_MAX]; 211 uint8_t version = get_backup_version_of_block(&fdp->meta, block_num); 212 213 if (toggle) 214 version = !version; 215 216 get_block_filepath(fdp->filename, block_num, version, block_path); 217 DMSG("%s", block_path); 218 219 res = tee_fs_rpc_new_remove(OPTEE_MSG_RPC_CMD_FS, block_path); 220 if (res == TEE_SUCCESS || res == TEE_ERROR_ITEM_NOT_FOUND) 221 return 0; /* ignore it if file not found */ 222 return -1; 223 } 224 225 static int remove_block_file(struct tee_fs_fd *fdp, size_t block_num) 226 { 227 DMSG("remove block%zd", block_num); 228 return __remove_block_file(fdp, block_num, false); 229 } 230 231 static int remove_outdated_block(struct tee_fs_fd *fdp, size_t block_num) 232 { 233 DMSG("remove outdated block%zd", block_num); 234 return __remove_block_file(fdp, block_num, true); 235 } 236 237 /* 238 * encrypted_fek: as input for META_FILE and BLOCK_FILE 239 */ 240 static TEE_Result encrypt_and_write_file(const char *file_name, 241 enum tee_fs_file_type file_type, 242 void *data_in, size_t data_in_size, 243 uint8_t *encrypted_fek) 244 { 245 TEE_Result res; 246 TEE_Result res2; 247 struct tee_fs_rpc_operation op; 248 void *ciphertext; 249 size_t header_size = tee_fs_get_header_size(file_type); 250 size_t ciphertext_size = header_size + data_in_size; 251 int fd; 252 253 res = tee_fs_rpc_new_open(OPTEE_MSG_RPC_CMD_FS, file_name, &fd); 254 if (res != TEE_SUCCESS) { 255 if (res != TEE_ERROR_ITEM_NOT_FOUND) 256 return res; 257 res = tee_fs_rpc_new_create(OPTEE_MSG_RPC_CMD_FS, file_name, 258 &fd); 259 if (res != TEE_SUCCESS) 260 return res; 261 } 262 263 res = tee_fs_rpc_new_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fd, 0, 264 ciphertext_size, &ciphertext); 265 if (res != TEE_SUCCESS) 266 goto out; 267 268 res = tee_fs_encrypt_file(file_type, data_in, data_in_size, 269 ciphertext, &ciphertext_size, encrypted_fek); 270 if (res != TEE_SUCCESS) 271 goto out; 272 273 res = tee_fs_rpc_new_write_final(&op); 274 out: 275 res2 = tee_fs_rpc_new_close(OPTEE_MSG_RPC_CMD_FS, fd); 276 if (res == TEE_SUCCESS) 277 return res2; 278 return res; 279 } 280 281 /* 282 * encrypted_fek: as output for META_FILE 283 * as input for BLOCK_FILE 284 */ 285 static TEE_Result read_and_decrypt_file(const char *file_name, 286 enum tee_fs_file_type file_type, 287 void *data_out, size_t *data_out_size, 288 uint8_t *encrypted_fek) 289 { 290 TEE_Result res; 291 TEE_Result res2; 292 struct tee_fs_rpc_operation op; 293 size_t bytes; 294 void *ciphertext; 295 int fd; 296 297 res = tee_fs_rpc_new_open(OPTEE_MSG_RPC_CMD_FS, file_name, &fd); 298 if (res != TEE_SUCCESS) 299 return res; 300 301 bytes = *data_out_size + tee_fs_get_header_size(file_type); 302 res = tee_fs_rpc_new_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fd, 0, 303 bytes, &ciphertext); 304 if (res != TEE_SUCCESS) 305 goto out; 306 307 res = tee_fs_rpc_new_read_final(&op, &bytes); 308 if (res != TEE_SUCCESS) 309 goto out; 310 311 res = tee_fs_decrypt_file(file_type, ciphertext, bytes, data_out, 312 data_out_size, encrypted_fek); 313 if (res != TEE_SUCCESS) 314 res = TEE_ERROR_CORRUPT_OBJECT; 315 out: 316 res2 = tee_fs_rpc_new_close(OPTEE_MSG_RPC_CMD_FS, fd); 317 if (res == TEE_SUCCESS) 318 return res2; 319 return res; 320 } 321 322 static TEE_Result write_meta_file(const char *filename, 323 struct tee_fs_file_meta *meta) 324 { 325 char meta_path[REE_FS_NAME_MAX]; 326 327 get_meta_filepath(filename, meta->backup_version, meta_path); 328 329 return encrypt_and_write_file(meta_path, META_FILE, 330 (void *)&meta->info, sizeof(meta->info), 331 meta->encrypted_fek); 332 } 333 334 static TEE_Result create_meta(struct tee_fs_fd *fdp) 335 { 336 TEE_Result res; 337 338 memset(fdp->meta.info.backup_version_table, 0xff, 339 sizeof(fdp->meta.info.backup_version_table)); 340 fdp->meta.info.length = 0; 341 342 res = tee_fs_generate_fek(fdp->meta.encrypted_fek, TEE_FS_KM_FEK_SIZE); 343 if (res != TEE_SUCCESS) 344 return res; 345 346 fdp->meta.backup_version = 0; 347 348 return write_meta_file(fdp->filename, &fdp->meta); 349 } 350 351 static TEE_Result commit_meta_file(struct tee_fs_fd *fdp, 352 struct tee_fs_file_meta *new_meta) 353 { 354 TEE_Result res; 355 uint8_t old_version; 356 char meta_path[REE_FS_NAME_MAX]; 357 358 old_version = new_meta->backup_version; 359 new_meta->backup_version = !new_meta->backup_version; 360 361 res = write_meta_file(fdp->filename, new_meta); 362 if (res != TEE_SUCCESS) 363 return res; 364 365 /* 366 * From now on the new meta is successfully committed, 367 * change tee_fs_fd accordingly 368 */ 369 fdp->meta = *new_meta; 370 371 /* 372 * Remove outdated meta file, there is nothing we can 373 * do if we fail here, but that is OK because both 374 * new & old version of block files are kept. The context 375 * of the file is still consistent. 376 */ 377 get_meta_filepath(fdp->filename, old_version, meta_path); 378 tee_fs_rpc_new_remove(OPTEE_MSG_RPC_CMD_FS, meta_path); 379 380 return res; 381 } 382 383 static TEE_Result read_meta_file(const char *meta_path, 384 struct tee_fs_file_meta *meta) 385 { 386 size_t meta_info_size = sizeof(struct tee_fs_file_info); 387 388 return read_and_decrypt_file(meta_path, META_FILE, 389 &meta->info, &meta_info_size, 390 meta->encrypted_fek); 391 } 392 393 static TEE_Result read_meta(struct tee_fs_fd *fdp) 394 { 395 TEE_Result res; 396 char meta_path[REE_FS_NAME_MAX]; 397 398 get_meta_filepath(fdp->filename, fdp->meta.backup_version, meta_path); 399 res = read_meta_file(meta_path, &fdp->meta); 400 if (res != TEE_SUCCESS) { 401 TEE_Result res2; 402 403 fdp->meta.backup_version = !fdp->meta.backup_version; 404 get_meta_filepath(fdp->filename, fdp->meta.backup_version, 405 meta_path); 406 res2 = read_meta_file(meta_path, &fdp->meta); 407 if (res2 != TEE_ERROR_ITEM_NOT_FOUND) 408 return res2; 409 } 410 411 return res; 412 } 413 414 static bool is_block_file_exist(struct tee_fs_file_meta *meta, 415 size_t block_num) 416 { 417 size_t file_size = meta->info.length; 418 419 if (file_size == 0) 420 return false; 421 422 return (block_num <= (size_t)get_last_block_num(file_size)); 423 } 424 425 static TEE_Result read_block_from_storage(struct tee_fs_fd *fdp, 426 struct block *b) 427 { 428 TEE_Result res = TEE_SUCCESS; 429 uint8_t *plaintext = b->data; 430 char block_path[REE_FS_NAME_MAX]; 431 size_t block_file_size = BLOCK_FILE_SIZE; 432 uint8_t version = get_backup_version_of_block(&fdp->meta, b->block_num); 433 434 if (!is_block_file_exist(&fdp->meta, b->block_num)) 435 goto exit; 436 437 get_block_filepath(fdp->filename, b->block_num, version, 438 block_path); 439 440 res = read_and_decrypt_file(block_path, BLOCK_FILE, 441 plaintext, &block_file_size, 442 fdp->meta.encrypted_fek); 443 if (res != TEE_SUCCESS) { 444 EMSG("Failed to read and decrypt file"); 445 goto exit; 446 } 447 b->data_size = block_file_size; 448 DMSG("Successfully read and decrypt block%d from storage, size=%zd", 449 b->block_num, b->data_size); 450 exit: 451 return res; 452 } 453 454 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b, 455 struct tee_fs_file_meta *new_meta) 456 { 457 TEE_Result res; 458 size_t block_num = b->block_num; 459 char block_path[REE_FS_NAME_MAX]; 460 uint8_t new_version = 461 !get_backup_version_of_block(&fdp->meta, block_num); 462 463 get_block_filepath(fdp->filename, block_num, new_version, block_path); 464 465 res = encrypt_and_write_file(block_path, BLOCK_FILE, b->data, 466 b->data_size, new_meta->encrypted_fek); 467 if (res != TEE_SUCCESS) { 468 EMSG("Failed to encrypt and write block file"); 469 goto fail; 470 } 471 472 DMSG("Successfully encrypt and write block%d to storage, size=%zd", 473 b->block_num, b->data_size); 474 toggle_backup_version_of_block(new_meta, block_num); 475 476 return 0; 477 fail: 478 return -1; 479 } 480 481 static struct block *alloc_block(void) 482 { 483 struct block *c; 484 485 c = malloc(sizeof(struct block)); 486 if (!c) 487 return NULL; 488 489 c->data = malloc(BLOCK_FILE_SIZE); 490 if (!c->data) { 491 EMSG("unable to alloc memory for block data"); 492 goto exit; 493 } 494 495 c->block_num = -1; 496 c->data_size = 0; 497 498 return c; 499 500 exit: 501 free(c); 502 return NULL; 503 } 504 505 #ifdef CFG_FS_BLOCK_CACHE 506 static void free_block(struct block *b) 507 { 508 if (b) { 509 free(b->data); 510 free(b); 511 } 512 } 513 514 static inline bool is_block_data_invalid(struct block *b) 515 { 516 return (b->data_size == 0); 517 } 518 519 static void get_block_from_cache(struct block_cache *cache, 520 int block_num, struct block **out_block) 521 { 522 struct block *b, *found = NULL; 523 524 DMSG("Try to find block%d in cache", block_num); 525 TAILQ_FOREACH(b, &cache->block_lru, list) { 526 if (b->block_num == block_num) { 527 DMSG("Found in cache"); 528 found = b; 529 break; 530 } 531 } 532 533 if (found) { 534 TAILQ_REMOVE(&cache->block_lru, found, list); 535 TAILQ_INSERT_HEAD(&cache->block_lru, found, list); 536 *out_block = found; 537 return; 538 } 539 540 DMSG("Not found, reuse oldest block on LRU list"); 541 b = TAILQ_LAST(&cache->block_lru, block_head); 542 TAILQ_REMOVE(&cache->block_lru, b, list); 543 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 544 b->block_num = block_num; 545 b->data_size = 0; 546 *out_block = b; 547 } 548 549 static int init_block_cache(struct block_cache *cache) 550 { 551 struct block *b; 552 553 TAILQ_INIT(&cache->block_lru); 554 cache->cached_block_num = 0; 555 556 while (cache->cached_block_num < MAX_NUM_CACHED_BLOCKS) { 557 558 b = alloc_block(); 559 if (!b) { 560 EMSG("Failed to alloc block"); 561 goto fail; 562 } else { 563 TAILQ_INSERT_HEAD(&cache->block_lru, b, list); 564 cache->cached_block_num++; 565 } 566 } 567 return 0; 568 569 fail: 570 TAILQ_FOREACH(b, &cache->block_lru, list) 571 free_block(b); 572 return -1; 573 } 574 575 static void destroy_block_cache(struct block_cache *cache) 576 { 577 struct block *b, *next; 578 579 TAILQ_FOREACH_SAFE(b, &cache->block_lru, list, next) { 580 TAILQ_REMOVE(&cache->block_lru, b, list); 581 free_block(b); 582 } 583 } 584 #else 585 static int init_block_cache(struct block_cache *cache __unused) 586 { 587 return 0; 588 } 589 590 static void destroy_block_cache(struct block_cache *cache __unused) 591 { 592 } 593 #endif 594 595 static void write_data_to_block(struct block *b, int offset, 596 void *buf, size_t len) 597 { 598 DMSG("Write %zd bytes to block%d", len, b->block_num); 599 memcpy(b->data + offset, buf, len); 600 if (offset + len > b->data_size) { 601 b->data_size = offset + len; 602 DMSG("Extend block%d size to %zd bytes", 603 b->block_num, b->data_size); 604 } 605 } 606 607 static void read_data_from_block(struct block *b, int offset, 608 void *buf, size_t len) 609 { 610 DMSG("Read %zd bytes from block%d", len, b->block_num); 611 if (offset + len > b->data_size) 612 panic("Exceeding block size"); 613 memcpy(buf, b->data + offset, len); 614 } 615 616 #ifdef CFG_FS_BLOCK_CACHE 617 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num) 618 { 619 struct block *b; 620 621 get_block_from_cache(&fdp->block_cache, block_num, &b); 622 if (is_block_data_invalid(b)) 623 if (read_block_from_storage(fdp, b)) { 624 EMSG("Unable to read block%d from storage", 625 block_num); 626 return NULL; 627 } 628 629 return b; 630 } 631 #else 632 633 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num) 634 { 635 static struct block *b; 636 TEE_Result res; 637 638 if (!b) 639 b = alloc_block(); 640 b->block_num = block_num; 641 642 res = read_block_from_storage(fdp, b); 643 if (res != TEE_SUCCESS) 644 EMSG("Unable to read block%d from storage", 645 block_num); 646 647 return res != TEE_SUCCESS ? NULL : b; 648 } 649 #endif 650 651 static struct block_operations block_ops = { 652 #ifdef CFG_FS_BLOCK_CACHE 653 .read = read_block_with_cache, 654 #else 655 .read = read_block_no_cache, 656 #endif 657 .write = flush_block_to_storage, 658 }; 659 660 static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, const void *buf, 661 size_t len, struct tee_fs_file_meta *new_meta) 662 { 663 int start_block_num = pos_to_block_num(fdp->pos); 664 int end_block_num = pos_to_block_num(fdp->pos + len - 1); 665 size_t remain_bytes = len; 666 uint8_t *data_ptr = (uint8_t *)buf; 667 int orig_pos = fdp->pos; 668 669 while (start_block_num <= end_block_num) { 670 int offset = fdp->pos % BLOCK_FILE_SIZE; 671 struct block *b; 672 size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ? 673 BLOCK_FILE_SIZE : remain_bytes; 674 675 if (size_to_write + offset > BLOCK_FILE_SIZE) 676 size_to_write = BLOCK_FILE_SIZE - offset; 677 678 b = block_ops.read(fdp, start_block_num); 679 if (!b) 680 goto failed; 681 682 DMSG("Write data, offset: %d, size_to_write: %zd", 683 offset, size_to_write); 684 write_data_to_block(b, offset, data_ptr, size_to_write); 685 686 if (block_ops.write(fdp, b, new_meta)) { 687 EMSG("Unable to wrtie block%d to storage", 688 b->block_num); 689 goto failed; 690 } 691 692 data_ptr += size_to_write; 693 remain_bytes -= size_to_write; 694 start_block_num++; 695 fdp->pos += size_to_write; 696 } 697 698 if (fdp->pos > (tee_fs_off_t)new_meta->info.length) 699 new_meta->info.length = fdp->pos; 700 701 return TEE_SUCCESS; 702 failed: 703 fdp->pos = orig_pos; 704 return TEE_ERROR_GENERIC; 705 } 706 707 static TEE_Result create_hard_link(const char *old_dir, const char *new_dir, 708 const char *filename) 709 { 710 char old_path[REE_FS_NAME_MAX]; 711 char new_path[REE_FS_NAME_MAX]; 712 713 snprintf(old_path, REE_FS_NAME_MAX, "%s/%s", 714 old_dir, filename); 715 snprintf(new_path, REE_FS_NAME_MAX, "%s/%s", 716 new_dir, filename); 717 718 DMSG("%s -> %s", old_path, new_path); 719 if (tee_fs_rpc_link(OPTEE_MSG_RPC_CMD_FS, old_path, new_path)) 720 return TEE_ERROR_GENERIC; 721 722 return TEE_SUCCESS; 723 } 724 725 static TEE_Result unlink_tee_file(const char *file) 726 { 727 TEE_Result res; 728 size_t len = strlen(file) + 1; 729 struct tee_fs_dirent *dirent; 730 struct tee_fs_dir *dir; 731 732 DMSG("file=%s", file); 733 734 if (len > TEE_FS_NAME_MAX) 735 return TEE_ERROR_GENERIC; 736 737 res = ree_fs_opendir_rpc(file, &dir); 738 if (res != TEE_SUCCESS) 739 return res; 740 741 res = ree_fs_readdir_rpc(dir, &dirent); 742 while (res == TEE_SUCCESS) { 743 char path[REE_FS_NAME_MAX]; 744 745 snprintf(path, REE_FS_NAME_MAX, "%s/%s", 746 file, dirent->d_name); 747 748 DMSG("unlink %s", path); 749 res = tee_fs_rpc_new_remove(OPTEE_MSG_RPC_CMD_FS, path); 750 if (res != TEE_SUCCESS) { 751 ree_fs_closedir_rpc(dir); 752 return res; 753 } 754 res = ree_fs_readdir_rpc(dir, &dirent); 755 } 756 757 ree_fs_closedir_rpc(dir); 758 759 return TEE_SUCCESS; 760 } 761 762 static TEE_Result open_internal(const char *file, bool create, bool overwrite, 763 struct tee_file_handle **fh) 764 { 765 TEE_Result res; 766 size_t len; 767 struct tee_fs_fd *fdp = NULL; 768 769 if (!file) 770 return TEE_ERROR_BAD_PARAMETERS; 771 772 len = strlen(file) + 1; 773 if (len > TEE_FS_NAME_MAX) 774 return TEE_ERROR_BAD_PARAMETERS; 775 776 fdp = calloc(1, sizeof(struct tee_fs_fd)); 777 if (!fdp) 778 return TEE_ERROR_OUT_OF_MEMORY; 779 780 mutex_lock(&ree_fs_mutex); 781 782 /* init internal status */ 783 if (init_block_cache(&fdp->block_cache)) { 784 res = TEE_ERROR_OUT_OF_MEMORY; 785 goto exit_free_fd; 786 } 787 788 fdp->filename = strdup(file); 789 if (!fdp->filename) { 790 res = TEE_ERROR_OUT_OF_MEMORY; 791 goto exit_destroy_block_cache; 792 } 793 794 res = read_meta(fdp); 795 if (res == TEE_SUCCESS) { 796 if (overwrite) { 797 res = TEE_ERROR_ACCESS_CONFLICT; 798 goto exit_free_filename; 799 } 800 } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 801 if (!create) 802 goto exit_free_filename; 803 res = create_meta(fdp); 804 if (res != TEE_SUCCESS) 805 goto exit_free_filename; 806 } else { 807 goto exit_free_filename; 808 } 809 810 *fh = (struct tee_file_handle *)fdp; 811 goto exit; 812 813 exit_free_filename: 814 free(fdp->filename); 815 exit_destroy_block_cache: 816 destroy_block_cache(&fdp->block_cache); 817 exit_free_fd: 818 free(fdp); 819 exit: 820 mutex_unlock(&ree_fs_mutex); 821 return res; 822 } 823 824 static TEE_Result ree_fs_open(const char *file, struct tee_file_handle **fh) 825 { 826 return open_internal(file, false, false, fh); 827 } 828 829 static TEE_Result ree_fs_create(const char *file, bool overwrite, 830 struct tee_file_handle **fh) 831 { 832 return open_internal(file, true, overwrite, fh); 833 } 834 835 static void ree_fs_close(struct tee_file_handle **fh) 836 { 837 struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh; 838 839 if (fdp) { 840 destroy_block_cache(&fdp->block_cache); 841 free(fdp->filename); 842 free(fdp); 843 *fh = NULL; 844 } 845 } 846 847 static TEE_Result ree_fs_seek(struct tee_file_handle *fh, int32_t offset, 848 TEE_Whence whence, int32_t *new_offs) 849 { 850 TEE_Result res; 851 tee_fs_off_t new_pos; 852 size_t filelen; 853 struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; 854 855 mutex_lock(&ree_fs_mutex); 856 857 DMSG("offset=%d, whence=%d", (int)offset, whence); 858 859 filelen = fdp->meta.info.length; 860 861 switch (whence) { 862 case TEE_DATA_SEEK_SET: 863 new_pos = offset; 864 break; 865 866 case TEE_DATA_SEEK_CUR: 867 new_pos = fdp->pos + offset; 868 break; 869 870 case TEE_DATA_SEEK_END: 871 new_pos = filelen + offset; 872 break; 873 874 default: 875 res = TEE_ERROR_BAD_PARAMETERS; 876 goto exit; 877 } 878 879 if (new_pos < 0) 880 new_pos = 0; 881 882 if (new_pos > TEE_DATA_MAX_POSITION) { 883 EMSG("Position is beyond TEE_DATA_MAX_POSITION"); 884 res = TEE_ERROR_BAD_PARAMETERS; 885 goto exit; 886 } 887 888 fdp->pos = new_pos; 889 if (new_offs) 890 *new_offs = new_pos; 891 res = TEE_SUCCESS; 892 exit: 893 mutex_unlock(&ree_fs_mutex); 894 return res; 895 } 896 897 /* 898 * To ensure atomic truncate operation, we can: 899 * 900 * - update file length to new length 901 * - commit new meta 902 * - free unused blocks 903 * 904 * To ensure atomic extend operation, we can: 905 * 906 * - update file length to new length 907 * - allocate and fill zero data to new blocks 908 * - commit new meta 909 * 910 * Any failure before committing new meta is considered as 911 * update failed, and the file content will not be updated 912 */ 913 static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp, 914 tee_fs_off_t new_file_len) 915 { 916 TEE_Result res; 917 size_t old_file_len = fdp->meta.info.length; 918 struct tee_fs_file_meta new_meta; 919 920 if ((size_t)new_file_len == old_file_len) { 921 DMSG("Ignore due to file length does not changed"); 922 return TEE_SUCCESS; 923 } 924 925 if (new_file_len > MAX_FILE_SIZE) { 926 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 927 return TEE_ERROR_BAD_PARAMETERS; 928 } 929 930 new_meta = fdp->meta; 931 new_meta.info.length = new_file_len; 932 933 if ((size_t)new_file_len < old_file_len) { 934 int old_block_num = get_last_block_num(old_file_len); 935 int new_block_num = get_last_block_num(new_file_len); 936 937 DMSG("Truncate file length to %zu", (size_t)new_file_len); 938 939 res = commit_meta_file(fdp, &new_meta); 940 if (res != TEE_SUCCESS) 941 return res; 942 943 /* now we are safe to free unused blocks */ 944 while (old_block_num > new_block_num) { 945 if (remove_block_file(fdp, old_block_num)) { 946 IMSG("Warning: Failed to free block: %d", 947 old_block_num); 948 } 949 950 old_block_num--; 951 } 952 953 } else { 954 size_t ext_len = new_file_len - old_file_len; 955 int orig_pos = fdp->pos; 956 uint8_t *buf; 957 958 buf = calloc(1, BLOCK_FILE_SIZE); 959 if (!buf) { 960 EMSG("Failed to allocate buffer, size=%d", 961 BLOCK_FILE_SIZE); 962 return TEE_ERROR_OUT_OF_MEMORY; 963 } 964 965 DMSG("Extend file length to %zu", (size_t)new_file_len); 966 967 fdp->pos = old_file_len; 968 969 res = TEE_SUCCESS; 970 while (ext_len > 0) { 971 size_t data_len = (ext_len > BLOCK_FILE_SIZE) ? 972 BLOCK_FILE_SIZE : ext_len; 973 974 DMSG("fill len=%zu", data_len); 975 res = out_of_place_write(fdp, buf, data_len, &new_meta); 976 if (res != TEE_SUCCESS) { 977 EMSG("Failed to fill data"); 978 break; 979 } 980 981 ext_len -= data_len; 982 } 983 984 free(buf); 985 fdp->pos = orig_pos; 986 987 if (res == TEE_SUCCESS) { 988 res = commit_meta_file(fdp, &new_meta); 989 if (res != TEE_SUCCESS) 990 EMSG("Failed to commit meta file"); 991 } 992 } 993 994 return res; 995 } 996 997 static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf, 998 size_t *len) 999 { 1000 TEE_Result res; 1001 int start_block_num; 1002 int end_block_num; 1003 size_t remain_bytes; 1004 uint8_t *data_ptr = buf; 1005 struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; 1006 1007 mutex_lock(&ree_fs_mutex); 1008 1009 remain_bytes = *len; 1010 if ((fdp->pos + remain_bytes) < remain_bytes || 1011 fdp->pos > (tee_fs_off_t)fdp->meta.info.length) 1012 remain_bytes = 0; 1013 else if (fdp->pos + remain_bytes > fdp->meta.info.length) 1014 remain_bytes = fdp->meta.info.length - fdp->pos; 1015 1016 *len = remain_bytes; 1017 1018 if (!remain_bytes) { 1019 res = TEE_SUCCESS; 1020 goto exit; 1021 } 1022 1023 DMSG("%s, data len=%zu", fdp->filename, remain_bytes); 1024 1025 start_block_num = pos_to_block_num(fdp->pos); 1026 end_block_num = pos_to_block_num(fdp->pos + remain_bytes - 1); 1027 DMSG("start_block_num:%d, end_block_num:%d", 1028 start_block_num, end_block_num); 1029 1030 while (start_block_num <= end_block_num) { 1031 struct block *b; 1032 int offset = fdp->pos % BLOCK_FILE_SIZE; 1033 size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ? 1034 BLOCK_FILE_SIZE : remain_bytes; 1035 1036 if (size_to_read + offset > BLOCK_FILE_SIZE) 1037 size_to_read = BLOCK_FILE_SIZE - offset; 1038 1039 DMSG("block_num:%d, offset:%d, size_to_read: %zd", 1040 start_block_num, offset, size_to_read); 1041 1042 b = block_ops.read(fdp, start_block_num); 1043 if (!b) { 1044 res = TEE_ERROR_CORRUPT_OBJECT; 1045 goto exit; 1046 } 1047 1048 read_data_from_block(b, offset, data_ptr, size_to_read); 1049 data_ptr += size_to_read; 1050 remain_bytes -= size_to_read; 1051 fdp->pos += size_to_read; 1052 1053 start_block_num++; 1054 } 1055 res = TEE_SUCCESS; 1056 exit: 1057 mutex_unlock(&ree_fs_mutex); 1058 return res; 1059 } 1060 1061 /* 1062 * To ensure atomicity of write operation, we need to 1063 * do the following steps: 1064 * (The sequence of operations is very important) 1065 * 1066 * - Create a new backup version of meta file as a copy 1067 * of current meta file. 1068 * - For each blocks to write: 1069 * - Create new backup version for current block. 1070 * - Write data to new backup version. 1071 * - Update the new meta file accordingly. 1072 * - Write the new meta file. 1073 * 1074 * (Any failure in above steps is considered as update failed, 1075 * and the file content will not be updated) 1076 * 1077 * After previous step the update is considered complete, but 1078 * we should do the following clean-up step(s): 1079 * 1080 * - Delete old meta file. 1081 * - Remove old block files. 1082 * 1083 * (Any failure in above steps is considered as a successfully 1084 * update) 1085 */ 1086 static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf, 1087 size_t len) 1088 { 1089 TEE_Result res; 1090 struct tee_fs_file_meta new_meta; 1091 struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; 1092 size_t file_size; 1093 tee_fs_off_t orig_pos; 1094 int start_block_num; 1095 int end_block_num; 1096 1097 1098 if (!len) 1099 return TEE_SUCCESS; 1100 1101 mutex_lock(&ree_fs_mutex); 1102 1103 file_size = fdp->meta.info.length; 1104 orig_pos = fdp->pos; 1105 1106 if ((fdp->pos + len) > MAX_FILE_SIZE || (fdp->pos + len) < len) { 1107 EMSG("Over maximum file size(%d)", MAX_FILE_SIZE); 1108 res = TEE_ERROR_BAD_PARAMETERS; 1109 goto exit; 1110 } 1111 1112 DMSG("%s, data len=%zu", fdp->filename, len); 1113 if (file_size < (size_t)fdp->pos) { 1114 DMSG("File hole detected, try to extend file size"); 1115 res = ree_fs_ftruncate_internal(fdp, fdp->pos); 1116 if (res != TEE_SUCCESS) 1117 goto exit; 1118 } 1119 1120 new_meta = fdp->meta; 1121 res = out_of_place_write(fdp, buf, len, &new_meta); 1122 if (res != TEE_SUCCESS) 1123 goto exit; 1124 1125 res = commit_meta_file(fdp, &new_meta); 1126 if (res != TEE_SUCCESS) 1127 goto exit; 1128 1129 /* we are safe to free old blocks */ 1130 start_block_num = pos_to_block_num(orig_pos); 1131 end_block_num = pos_to_block_num(fdp->pos - 1); 1132 while (start_block_num <= end_block_num) { 1133 if (remove_outdated_block(fdp, start_block_num)) 1134 IMSG("Warning: Failed to free old block: %d", 1135 start_block_num); 1136 1137 start_block_num++; 1138 } 1139 exit: 1140 mutex_unlock(&ree_fs_mutex); 1141 return res; 1142 } 1143 1144 /* 1145 * To ensure atomicity of rename operation, we need to 1146 * do the following steps: 1147 * 1148 * - Create a new folder that represents the renamed TEE file 1149 * - For each REE block files, create a hard link under the just 1150 * created folder (new TEE file) 1151 * - Now we are ready to commit meta, create hard link for the 1152 * meta file 1153 * 1154 * (Any failure in above steps is considered as update failed, 1155 * and the file content will not be updated) 1156 * 1157 * After previous step the update is considered complete, but 1158 * we should do the following clean-up step(s): 1159 * 1160 * - Unlink all REE files represents the old TEE file (including 1161 * meta and block files) 1162 * 1163 * (Any failure in above steps is considered as a successfully 1164 * update) 1165 */ 1166 static TEE_Result ree_fs_rename_internal(const char *old, const char *new, 1167 bool overwrite) 1168 { 1169 TEE_Result res; 1170 size_t old_len; 1171 size_t new_len; 1172 size_t meta_count = 0; 1173 struct tee_fs_dir *old_dir; 1174 struct tee_fs_dirent *dirent; 1175 char *meta_filename = NULL; 1176 1177 DMSG("old=%s, new=%s", old, new); 1178 1179 old_len = strlen(old) + 1; 1180 new_len = strlen(new) + 1; 1181 1182 if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX) 1183 return TEE_ERROR_BAD_PARAMETERS; 1184 1185 if (!ree_fs_access_rpc(new, TEE_FS_F_OK)) { 1186 if (!overwrite) 1187 return TEE_ERROR_ACCESS_CONFLICT; 1188 unlink_tee_file(new); 1189 } 1190 1191 if (ree_fs_mkdir_rpc(new, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR)) 1192 return TEE_ERROR_GENERIC; 1193 1194 res = ree_fs_opendir_rpc(old, &old_dir); 1195 if (res != TEE_SUCCESS) 1196 return res; 1197 1198 res = ree_fs_readdir_rpc(old_dir, &dirent); 1199 while (res == TEE_SUCCESS) { 1200 if (!strncmp(dirent->d_name, "meta.", 5)) { 1201 meta_filename = strdup(dirent->d_name); 1202 meta_count++; 1203 } else { 1204 res = create_hard_link(old, new, dirent->d_name); 1205 if (res != TEE_SUCCESS) 1206 goto exit_close_old_dir; 1207 } 1208 1209 res = ree_fs_readdir_rpc(old_dir, &dirent); 1210 } 1211 1212 /* finally, link the meta file, rename operation completed */ 1213 if (!meta_filename) 1214 panic("no meta file"); 1215 1216 /* 1217 * TODO: This will cause memory leakage at previous strdup() 1218 * if we accidently have two meta files in a TEE file. 1219 * 1220 * It's not easy to handle the case above (e.g. Which meta file 1221 * should be linked first? What to do if a power cut happened 1222 * during creating links for the two meta files?) 1223 * 1224 * We will solve this issue using another approach: merging 1225 * both meta and block files into a single REE file. This approach 1226 * can completely remove ree_fs_rename(). We can simply 1227 * rename TEE file using REE rename() system call, which is also 1228 * atomic. 1229 */ 1230 if (meta_count > 1) 1231 EMSG("Warning: more than one meta file in your TEE file\n" 1232 "This will cause memory leakage."); 1233 1234 res = create_hard_link(old, new, meta_filename); 1235 if (res != TEE_SUCCESS) 1236 goto exit_close_old_dir; 1237 1238 /* we are safe now, remove old TEE file */ 1239 unlink_tee_file(old); 1240 1241 exit_close_old_dir: 1242 ree_fs_closedir_rpc(old_dir); 1243 free(meta_filename); 1244 return res; 1245 } 1246 1247 static TEE_Result ree_fs_rename(const char *old, const char *new, 1248 bool overwrite) 1249 { 1250 TEE_Result res; 1251 1252 mutex_lock(&ree_fs_mutex); 1253 res = ree_fs_rename_internal(old, new, overwrite); 1254 mutex_unlock(&ree_fs_mutex); 1255 1256 return res; 1257 } 1258 1259 /* 1260 * To ensure atomic unlink operation, we can simply 1261 * split the unlink operation into: 1262 * 1263 * - rename("file", "file.trash"); 1264 * 1265 * (Any failure in above steps is considered as update failed, 1266 * and the file content will not be updated) 1267 * 1268 * After previous step the update is considered complete, but 1269 * we should do the following clean-up step(s): 1270 * 1271 * - unlink("file.trash"); 1272 * 1273 * (Any failure in above steps is considered as a successfully 1274 * update) 1275 */ 1276 static TEE_Result ree_fs_remove(const char *file) 1277 { 1278 TEE_Result res; 1279 char trash_file[TEE_FS_NAME_MAX + 6]; 1280 1281 snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash", file); 1282 1283 mutex_lock(&ree_fs_mutex); 1284 1285 res = ree_fs_rename_internal(file, trash_file, true); 1286 if (res == TEE_SUCCESS) 1287 unlink_tee_file(trash_file); 1288 1289 mutex_unlock(&ree_fs_mutex); 1290 return res; 1291 } 1292 1293 static TEE_Result ree_fs_truncate(struct tee_file_handle *fh, size_t len) 1294 { 1295 TEE_Result res; 1296 struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; 1297 1298 mutex_lock(&ree_fs_mutex); 1299 res = ree_fs_ftruncate_internal(fdp, len); 1300 mutex_unlock(&ree_fs_mutex); 1301 1302 return res; 1303 } 1304 1305 const struct tee_file_operations ree_fs_ops = { 1306 .open = ree_fs_open, 1307 .create = ree_fs_create, 1308 .close = ree_fs_close, 1309 .read = ree_fs_read, 1310 .write = ree_fs_write, 1311 .seek = ree_fs_seek, 1312 .truncate = ree_fs_truncate, 1313 .rename = ree_fs_rename, 1314 .remove = ree_fs_remove, 1315 .opendir = ree_fs_opendir_rpc, 1316 .closedir = ree_fs_closedir_rpc, 1317 .readdir = ree_fs_readdir_rpc, 1318 }; 1319