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