xref: /optee_os/core/tee/tee_ree_fs.c (revision 8ddf5a4e3ce277adee040d90758ec08b429e9e4f)
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 	assert(length);
589 	*length = 0;
590 
591 	res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_END);
592 	if (res < 0)
593 		return res;
594 
595 	file_len = res;
596 
597 	res = ree_fs_lseek_ree(fd, 0, TEE_FS_SEEK_SET);
598 	if (res < 0)
599 		return res;
600 
601 	*length = file_len;
602 	return 0;
603 }
604 
605 static void get_meta_filepath(const char *file, int version,
606 				char *meta_path)
607 {
608 	snprintf(meta_path, REE_FS_NAME_MAX, "%s/meta.%d",
609 			file, version);
610 }
611 
612 static void get_block_filepath(const char *file, size_t block_num,
613 				int version, char *meta_path)
614 {
615 	snprintf(meta_path, REE_FS_NAME_MAX, "%s/block%zu.%d",
616 			file, block_num, version);
617 }
618 
619 static int create_block_file(struct tee_fs_fd *fdp,
620 		struct tee_fs_file_meta *new_meta, int block_num)
621 {
622 	int fd;
623 	int res = -1;
624 	char block_path[REE_FS_NAME_MAX];
625 	uint8_t new_version =
626 		!get_backup_version_of_block(fdp->meta, block_num);
627 
628 	get_block_filepath(fdp->filename, block_num, new_version,
629 			block_path);
630 
631 	fd = ree_fs_open_ree(block_path, TEE_FS_O_CREATE | TEE_FS_O_RDWR);
632 	if (fd < 0)
633 		goto exit;
634 
635 	res = ree_fs_ftruncate_ree(fd, 0);
636 	if (res < 0)
637 		goto exit;
638 
639 	/*
640 	 * toggle block version in new meta to indicate
641 	 * we are currently working on new block file
642 	 */
643 	toggle_backup_version_of_block(new_meta, block_num);
644 	res = fd;
645 
646 exit:
647 	return res;
648 }
649 
650 static int __remove_block_file(struct tee_fs_fd *fdp, size_t block_num,
651 				bool toggle)
652 {
653 	char block_path[REE_FS_NAME_MAX];
654 	uint8_t version =
655 		get_backup_version_of_block(fdp->meta, block_num);
656 
657 	if (toggle)
658 		version = !version;
659 
660 	get_block_filepath(fdp->filename, block_num, version, block_path);
661 	DMSG("%s", block_path);
662 
663 	/* ignore it if file not found */
664 	if (ree_fs_access_ree(block_path, TEE_FS_F_OK))
665 		return 0;
666 
667 	return ree_fs_unlink_ree(block_path);
668 }
669 
670 static int remove_block_file(struct tee_fs_fd *fdp, size_t block_num)
671 {
672 	DMSG("remove block%zd", block_num);
673 	return __remove_block_file(fdp, block_num, false);
674 }
675 
676 static int remove_outdated_block(struct tee_fs_fd *fdp, size_t block_num)
677 {
678 	DMSG("remove outdated block%zd", block_num);
679 	return __remove_block_file(fdp, block_num, true);
680 }
681 
682 /*
683  * encrypted_fek: as input for META_FILE and BLOCK_FILE
684  */
685 static int encrypt_and_write_file(int fd,
686 		enum tee_fs_file_type file_type,
687 		void *data_in, size_t data_in_size,
688 		uint8_t *encrypted_fek)
689 {
690 	TEE_Result tee_res;
691 	int res = 0;
692 	int bytes;
693 	uint8_t *ciphertext;
694 	size_t header_size = tee_fs_get_header_size(file_type);
695 	size_t ciphertext_size = header_size + data_in_size;
696 
697 	ciphertext = malloc(ciphertext_size);
698 	if (!ciphertext) {
699 		EMSG("Failed to allocate ciphertext buffer, size=%zd",
700 				ciphertext_size);
701 		return -1;
702 	}
703 
704 	tee_res = tee_fs_encrypt_file(file_type,
705 			data_in, data_in_size,
706 			ciphertext, &ciphertext_size, encrypted_fek);
707 	if (tee_res != TEE_SUCCESS) {
708 		EMSG("error code=%x", tee_res);
709 		res = -1;
710 		goto fail;
711 	}
712 
713 	bytes = ree_fs_write_ree(fd, ciphertext, ciphertext_size);
714 	if (bytes != (int)ciphertext_size) {
715 		EMSG("bytes(%d) != ciphertext size(%zu)",
716 				bytes, ciphertext_size);
717 		res = -1;
718 		goto fail;
719 	}
720 
721 fail:
722 	free(ciphertext);
723 
724 	return res;
725 }
726 
727 /*
728  * encrypted_fek: as output for META_FILE
729  *                as input for BLOCK_FILE
730  */
731 static int read_and_decrypt_file(int fd,
732 		enum tee_fs_file_type file_type,
733 		void *data_out, size_t *data_out_size,
734 		uint8_t *encrypted_fek)
735 {
736 	TEE_Result tee_res;
737 	int res;
738 	int bytes;
739 	void *ciphertext = NULL;
740 	size_t file_size;
741 	size_t header_size = tee_fs_get_header_size(file_type);
742 
743 	res = get_file_length(fd, &file_size);
744 	if (res < 0)
745 		return res;
746 
747 	TEE_ASSERT(file_size >= header_size);
748 
749 	ciphertext = malloc(file_size);
750 	if (!ciphertext) {
751 		EMSG("Failed to allocate file data buffer, size=%zd",
752 				file_size);
753 		return -1;
754 	}
755 
756 	bytes = ree_fs_read_ree(fd, ciphertext, file_size);
757 	if (bytes != (int)file_size) {
758 		EMSG("return bytes(%d) != file_size(%zd)",
759 				bytes, file_size);
760 		res = -1;
761 		goto fail;
762 	}
763 
764 	tee_res = tee_fs_decrypt_file(file_type,
765 			ciphertext, file_size,
766 			data_out, data_out_size,
767 			encrypted_fek);
768 	if (tee_res != TEE_SUCCESS) {
769 		EMSG("Failed to decrypt file, res=0x%x", tee_res);
770 		res = -1;
771 	}
772 
773 fail:
774 	free(ciphertext);
775 
776 	return (res < 0) ? res : 0;
777 }
778 
779 static struct tee_fs_file_meta *duplicate_meta(
780 		struct tee_fs_fd *fdp)
781 {
782 	struct tee_fs_file_meta *new_meta = NULL;
783 
784 	new_meta = malloc(sizeof(*new_meta));
785 	if (!new_meta) {
786 		EMSG("Failed to allocate memory for new meta");
787 		goto exit;
788 	}
789 
790 	memcpy(new_meta, fdp->meta, sizeof(*new_meta));
791 
792 exit:
793 	return new_meta;
794 }
795 
796 static int write_meta_file(const char *filename,
797 		struct tee_fs_file_meta *meta)
798 {
799 	int res, fd = -1;
800 	char meta_path[REE_FS_NAME_MAX];
801 
802 	get_meta_filepath(filename, meta->backup_version, meta_path);
803 
804 	fd = ree_fs_open_ree(meta_path, TEE_FS_O_CREATE |
805 			     TEE_FS_O_TRUNC | TEE_FS_O_WRONLY);
806 	if (fd < 0)
807 		return -1;
808 
809 	res = encrypt_and_write_file(fd, META_FILE,
810 			(void *)&meta->info, sizeof(meta->info),
811 			meta->encrypted_fek);
812 
813 	ree_fs_close_ree(fd);
814 	return res;
815 }
816 
817 static struct tee_fs_file_meta *create_meta_file(const char *file)
818 {
819 	TEE_Result tee_res;
820 	struct tee_fs_file_meta *meta = NULL;
821 	int res;
822 	const uint8_t default_backup_version = 0;
823 
824 	meta = malloc(sizeof(struct tee_fs_file_meta));
825 	if (!meta) {
826 		EMSG("Failed to allocate memory");
827 		goto exit;
828 	}
829 
830 	memset(&meta->info.backup_version_table, 0xff,
831 		sizeof(meta->info.backup_version_table));
832 	meta->info.length = 0;
833 
834 	tee_res = tee_fs_generate_fek(meta->encrypted_fek, TEE_FS_KM_FEK_SIZE);
835 	if (tee_res != TEE_SUCCESS)
836 		goto exit;
837 
838 	meta->backup_version = default_backup_version;
839 
840 	res = write_meta_file(file, meta);
841 	if (res < 0)
842 		goto exit;
843 
844 	return meta;
845 
846 exit:
847 	free(meta);
848 
849 	return NULL;
850 }
851 
852 static int commit_meta_file(struct tee_fs_fd *fdp,
853 		struct tee_fs_file_meta *new_meta)
854 {
855 	int res;
856 	uint8_t old_version;
857 	char meta_path[REE_FS_NAME_MAX];
858 
859 	old_version = new_meta->backup_version;
860 	new_meta->backup_version = !new_meta->backup_version;
861 
862 	res = write_meta_file(fdp->filename, new_meta);
863 
864 	if (res < 0)
865 		return res;
866 
867 	/*
868 	 * From now on the new meta is successfully committed,
869 	 * change tee_fs_fd accordingly
870 	 */
871 	memcpy(fdp->meta, new_meta, sizeof(*new_meta));
872 
873 	/*
874 	 * Remove outdated meta file, there is nothing we can
875 	 * do if we fail here, but that is OK because both
876 	 * new & old version of block files are kept. The context
877 	 * of the file is still consistent.
878 	 */
879 	get_meta_filepath(fdp->filename, old_version, meta_path);
880 	ree_fs_unlink_ree(meta_path);
881 
882 	return res;
883 }
884 
885 static int read_meta_file(const char *meta_path,
886 		struct tee_fs_file_meta *meta)
887 {
888 	int res, fd;
889 	size_t meta_info_size = sizeof(struct tee_fs_file_info);
890 
891 	res = ree_fs_open_ree(meta_path, TEE_FS_O_RDWR);
892 	if (res < 0)
893 		return res;
894 
895 	fd = res;
896 
897 	res = read_and_decrypt_file(fd, META_FILE,
898 			(void *)&meta->info, &meta_info_size,
899 			meta->encrypted_fek);
900 
901 	ree_fs_close_ree(fd);
902 
903 	return res;
904 }
905 
906 static struct tee_fs_file_meta *open_meta_file(
907 		const char *file, int version)
908 {
909 	int res;
910 	char meta_path[REE_FS_NAME_MAX];
911 	struct tee_fs_file_meta *meta = NULL;
912 
913 	meta = malloc(sizeof(struct tee_fs_file_meta));
914 	if (!meta)
915 		return NULL;
916 
917 	get_meta_filepath(file, version, meta_path);
918 	res = read_meta_file(meta_path, meta);
919 	if (res < 0)
920 		goto exit_free_meta;
921 
922 	meta->backup_version = version;
923 
924 	return meta;
925 
926 exit_free_meta:
927 	free(meta);
928 	return NULL;
929 }
930 
931 static bool is_block_file_exist(struct tee_fs_file_meta *meta,
932 					size_t block_num)
933 {
934 	size_t file_size = meta->info.length;
935 
936 	if (file_size == 0)
937 		return false;
938 
939 	return (block_num <= (size_t)get_last_block_num(file_size));
940 }
941 
942 #ifdef CFG_ENC_FS
943 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b)
944 {
945 	int fd, res = 0;
946 	uint8_t *plaintext = b->data;
947 	char block_path[REE_FS_NAME_MAX];
948 	size_t block_file_size = BLOCK_FILE_SIZE;
949 	uint8_t version = get_backup_version_of_block(fdp->meta,
950 			b->block_num);
951 
952 	if (!is_block_file_exist(fdp->meta, b->block_num))
953 		goto exit;
954 
955 	get_block_filepath(fdp->filename, b->block_num, version,
956 			block_path);
957 
958 	fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY);
959 	if (fd < 0)
960 		return fd;
961 
962 	res = read_and_decrypt_file(fd, BLOCK_FILE,
963 			plaintext, &block_file_size,
964 			fdp->meta->encrypted_fek);
965 	if (res < 0) {
966 		EMSG("Failed to read and decrypt file");
967 		goto fail;
968 	}
969 	b->data_size = block_file_size;
970 	DMSG("Successfully read and decrypt block%d from storage, size=%zd",
971 		b->block_num, b->data_size);
972 fail:
973 	ree_fs_close_ree(fd);
974 exit:
975 	return res;
976 }
977 
978 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b,
979 		struct tee_fs_file_meta *new_meta)
980 {
981 	int fd = -1;
982 	int res;
983 	size_t block_num = b->block_num;
984 
985 	fd = create_block_file(
986 			fdp, new_meta, block_num);
987 	if (fd < 0) {
988 		EMSG("Failed to create new version of block");
989 		res = -1;
990 		goto fail;
991 	}
992 
993 	res = encrypt_and_write_file(fd, BLOCK_FILE,
994 			b->data, b->data_size,
995 			new_meta->encrypted_fek);
996 	if (res < 0) {
997 		EMSG("Failed to encrypt and write block file");
998 		goto fail;
999 	}
1000 	DMSG("Successfully encrypt and write block%d to storage, size=%zd",
1001 		b->block_num, b->data_size);
1002 
1003 fail:
1004 	if (fd > 0)
1005 		ree_fs_close_ree(fd);
1006 
1007 	return res;
1008 }
1009 #else
1010 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b)
1011 {
1012 	int fd, res = 0;
1013 	char block_path[REE_FS_NAME_MAX];
1014 	size_t block_file_size = BLOCK_FILE_SIZE;
1015 	uint8_t version = get_backup_version_of_block(fdp->meta,
1016 			b->block_num);
1017 
1018 	if (!is_block_file_exist(fdp->meta, b->block_num))
1019 		goto exit;
1020 
1021 	get_block_filepath(fdp->filename, b->block_num, version,
1022 			block_path);
1023 
1024 	fd = ree_fs_open_ree(block_path, TEE_FS_O_RDONLY);
1025 	if (fd < 0)
1026 		return fd;
1027 
1028 
1029 	res = ree_fs_read_ree(fd, b->data, block_file_size);
1030 	if (res < 0) {
1031 		EMSG("Failed to read block%d (%d)",
1032 			b->block_num, res);
1033 		goto fail;
1034 	}
1035 
1036 	b->data_size = res;
1037 	DMSG("Successfully read block%d from storage, size=%d",
1038 		b->block_num, b->data_size);
1039 	res = 0;
1040 fail:
1041 	ree_fs_close_ree(fd);
1042 exit:
1043 	return res;
1044 }
1045 
1046 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b,
1047 		struct tee_fs_file_meta *new_meta)
1048 {
1049 	int fd = -1;
1050 	int res;
1051 	size_t block_num = b->block_num;
1052 
1053 	fd = create_block_file(
1054 			fdp, new_meta, block_num);
1055 	if (fd < 0) {
1056 		EMSG("Failed to create new version of block");
1057 		res = -1;
1058 		goto fail;
1059 	}
1060 
1061 	res = ree_fs_write_ree(fd, b->data, b->data_size);
1062 	if (res < 0) {
1063 		EMSG("Failed to write block%d (%d)",
1064 			b->block_num, res);
1065 		goto fail;
1066 	}
1067 	DMSG("Successfully writen block%d to storage, size=%d",
1068 		b->block_num, b->data_size);
1069 	res = 0;
1070 fail:
1071 	if (fd > 0)
1072 		ree_fs_close_ree(fd);
1073 
1074 	return res;
1075 }
1076 #endif
1077 
1078 static struct block *alloc_block(void)
1079 {
1080 	struct block *c;
1081 
1082 	c = malloc(sizeof(struct block));
1083 	if (!c)
1084 		return NULL;
1085 
1086 	c->data = malloc(BLOCK_FILE_SIZE);
1087 	if (!c->data) {
1088 		EMSG("unable to alloc memory for block data");
1089 		goto exit;
1090 	}
1091 
1092 	c->block_num = -1;
1093 	c->data_size = 0;
1094 
1095 	return c;
1096 
1097 exit:
1098 	free(c);
1099 	return NULL;
1100 }
1101 
1102 #ifdef CFG_FS_BLOCK_CACHE
1103 static void free_block(struct block *b)
1104 {
1105 	if (b) {
1106 		free(b->data);
1107 		free(b);
1108 	}
1109 }
1110 
1111 static inline bool is_block_data_invalid(struct block *b)
1112 {
1113 	return (b->data_size == 0);
1114 }
1115 
1116 static void get_block_from_cache(struct block_cache *cache,
1117 			int block_num, struct block **out_block)
1118 {
1119 	struct block *b, *found = NULL;
1120 
1121 	DMSG("Try to find block%d in cache", block_num);
1122 	TAILQ_FOREACH(b, &cache->block_lru, list) {
1123 		if (b->block_num == block_num) {
1124 			DMSG("Found in cache");
1125 			found = b;
1126 			break;
1127 		}
1128 	}
1129 
1130 	if (found) {
1131 		TAILQ_REMOVE(&cache->block_lru, found, list);
1132 		TAILQ_INSERT_HEAD(&cache->block_lru, found, list);
1133 		*out_block = found;
1134 		return;
1135 	}
1136 
1137 	DMSG("Not found, reuse oldest block on LRU list");
1138 	b = TAILQ_LAST(&cache->block_lru, block_head);
1139 	TAILQ_REMOVE(&cache->block_lru, b, list);
1140 	TAILQ_INSERT_HEAD(&cache->block_lru, b, list);
1141 	b->block_num = block_num;
1142 	b->data_size = 0;
1143 	*out_block = b;
1144 }
1145 
1146 static int init_block_cache(struct block_cache *cache)
1147 {
1148 	struct block *b;
1149 
1150 	TAILQ_INIT(&cache->block_lru);
1151 	cache->cached_block_num = 0;
1152 
1153 	while (cache->cached_block_num < MAX_NUM_CACHED_BLOCKS) {
1154 
1155 		b = alloc_block();
1156 		if (!b) {
1157 			EMSG("Failed to alloc block");
1158 			goto fail;
1159 		} else {
1160 			TAILQ_INSERT_HEAD(&cache->block_lru, b, list);
1161 			cache->cached_block_num++;
1162 		}
1163 	}
1164 	return 0;
1165 
1166 fail:
1167 	TAILQ_FOREACH(b, &cache->block_lru, list)
1168 		free_block(b);
1169 	return -1;
1170 }
1171 
1172 static void destroy_block_cache(struct block_cache *cache)
1173 {
1174 	struct block *b, *next;
1175 
1176 	TAILQ_FOREACH_SAFE(b, &cache->block_lru, list, next) {
1177 		TAILQ_REMOVE(&cache->block_lru, b, list);
1178 		free_block(b);
1179 	}
1180 }
1181 #else
1182 static int init_block_cache(struct block_cache *cache __unused)
1183 {
1184 	return 0;
1185 }
1186 
1187 static void destroy_block_cache(struct block_cache *cache __unused)
1188 {
1189 }
1190 #endif
1191 
1192 static void write_data_to_block(struct block *b, int offset,
1193 				void *buf, size_t len)
1194 {
1195 	DMSG("Write %zd bytes to block%d", len, b->block_num);
1196 	memcpy(b->data + offset, buf, len);
1197 	if (offset + len > b->data_size) {
1198 		b->data_size = offset + len;
1199 		DMSG("Extend block%d size to %zd bytes",
1200 				b->block_num, b->data_size);
1201 	}
1202 }
1203 
1204 static void read_data_from_block(struct block *b, int offset,
1205 				void *buf, size_t len)
1206 {
1207 	size_t bytes_to_read = len;
1208 
1209 	DMSG("Read %zd bytes from block%d", len, b->block_num);
1210 	if (offset + len > b->data_size) {
1211 		bytes_to_read = b->data_size - offset;
1212 		DMSG("Exceed block size, update len to %zd bytes",
1213 			bytes_to_read);
1214 	}
1215 	memcpy(buf, b->data + offset, bytes_to_read);
1216 }
1217 
1218 #ifdef CFG_FS_BLOCK_CACHE
1219 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num)
1220 {
1221 	struct block *b;
1222 
1223 	get_block_from_cache(&fdp->block_cache, block_num, &b);
1224 	if (is_block_data_invalid(b))
1225 		if (read_block_from_storage(fdp, b)) {
1226 			EMSG("Unable to read block%d from storage",
1227 					block_num);
1228 			return NULL;
1229 		}
1230 
1231 	return b;
1232 }
1233 #else
1234 
1235 static struct mutex block_mutex = MUTEX_INITIALIZER;
1236 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num)
1237 {
1238 	static struct block *b;
1239 	int res;
1240 
1241 	mutex_lock(&block_mutex);
1242 	if (!b)
1243 		b = alloc_block();
1244 	b->block_num = block_num;
1245 
1246 	res = read_block_from_storage(fdp, b);
1247 	if (res)
1248 		EMSG("Unable to read block%d from storage",
1249 				block_num);
1250 	mutex_unlock(&block_mutex);
1251 
1252 	return res ? NULL : b;
1253 }
1254 #endif
1255 
1256 static struct block_operations block_ops = {
1257 #ifdef CFG_FS_BLOCK_CACHE
1258 	.read = read_block_with_cache,
1259 #else
1260 	.read = read_block_no_cache,
1261 #endif
1262 	.write = flush_block_to_storage,
1263 };
1264 
1265 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
1266 		size_t len, struct tee_fs_file_meta *new_meta)
1267 {
1268 	int start_block_num = pos_to_block_num(fdp->pos);
1269 	int end_block_num = pos_to_block_num(fdp->pos + len - 1);
1270 	size_t remain_bytes = len;
1271 	uint8_t *data_ptr = (uint8_t *)buf;
1272 	int orig_pos = fdp->pos;
1273 
1274 	while (start_block_num <= end_block_num) {
1275 		int offset = fdp->pos % BLOCK_FILE_SIZE;
1276 		struct block *b;
1277 		size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ?
1278 			BLOCK_FILE_SIZE : remain_bytes;
1279 
1280 		if (size_to_write + offset > BLOCK_FILE_SIZE)
1281 			size_to_write = BLOCK_FILE_SIZE - offset;
1282 
1283 		b = block_ops.read(fdp, start_block_num);
1284 		if (!b)
1285 			goto failed;
1286 
1287 		DMSG("Write data, offset: %d, size_to_write: %zd",
1288 			offset, size_to_write);
1289 		write_data_to_block(b, offset, data_ptr, size_to_write);
1290 
1291 		if (block_ops.write(fdp, b, new_meta)) {
1292 			EMSG("Unable to wrtie block%d to storage",
1293 					b->block_num);
1294 			goto failed;
1295 		}
1296 
1297 		data_ptr += size_to_write;
1298 		remain_bytes -= size_to_write;
1299 		start_block_num++;
1300 		fdp->pos += size_to_write;
1301 	}
1302 
1303 	if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
1304 		new_meta->info.length = fdp->pos;
1305 
1306 	return 0;
1307 failed:
1308 	fdp->pos = orig_pos;
1309 	return -1;
1310 }
1311 
1312 static inline int create_hard_link(const char *old_dir,
1313 			const char *new_dir,
1314 			const char *filename)
1315 {
1316 	char old_path[REE_FS_NAME_MAX];
1317 	char new_path[REE_FS_NAME_MAX];
1318 
1319 	snprintf(old_path, REE_FS_NAME_MAX, "%s/%s",
1320 			old_dir, filename);
1321 	snprintf(new_path, REE_FS_NAME_MAX, "%s/%s",
1322 			new_dir, filename);
1323 
1324 	DMSG("%s -> %s", old_path, new_path);
1325 	return ree_fs_link_ree(old_path, new_path);
1326 }
1327 
1328 static int unlink_tee_file(const char *file)
1329 {
1330 	int res = -1;
1331 	size_t len = strlen(file) + 1;
1332 	struct tee_fs_dirent *dirent;
1333 	struct tee_fs_dir *dir;
1334 
1335 	DMSG("file=%s", file);
1336 
1337 	if (len > TEE_FS_NAME_MAX)
1338 		goto exit;
1339 
1340 	dir = ree_fs_opendir_ree(file);
1341 	if (!dir)
1342 		goto exit;
1343 
1344 	dirent = ree_fs_readdir_ree(dir);
1345 	while (dirent) {
1346 		char path[REE_FS_NAME_MAX];
1347 
1348 		snprintf(path, REE_FS_NAME_MAX, "%s/%s",
1349 			file, dirent->d_name);
1350 
1351 		DMSG("unlink %s", path);
1352 		res = ree_fs_unlink_ree(path);
1353 		if (res) {
1354 			ree_fs_closedir_ree(dir);
1355 			goto exit;
1356 		}
1357 
1358 		dirent = ree_fs_readdir_ree(dir);
1359 	}
1360 
1361 	res = ree_fs_closedir_ree(dir);
1362 	if (res)
1363 		goto exit;
1364 
1365 	res = ree_fs_rmdir_ree(file);
1366 exit:
1367 	return res;
1368 }
1369 
1370 static bool tee_file_exists(const char *file)
1371 {
1372 	char meta_path[REE_FS_NAME_MAX];
1373 
1374 	get_meta_filepath(file, 0, meta_path);
1375 	if (ree_fs_access_ree(meta_path, TEE_FS_F_OK)) {
1376 		get_meta_filepath(file, 1, meta_path);
1377 		if (ree_fs_access_ree(meta_path, TEE_FS_F_OK))
1378 			return false;
1379 	}
1380 
1381 	return true;
1382 }
1383 
1384 static struct tee_fs_file_meta *create_tee_file(const char *file)
1385 {
1386 	struct tee_fs_file_meta *meta = NULL;
1387 	int res;
1388 
1389 	DMSG("Creating TEE file=%s", file);
1390 
1391 	/* create TEE file directory if not exist */
1392 	if (ree_fs_access_ree(file, TEE_FS_F_OK)) {
1393 		res = ree_fs_mkdir_ree(file,
1394 				TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
1395 		if (res) {
1396 			EMSG("Failed to create TEE file directory, res=%d",
1397 				res);
1398 			goto exit;
1399 		}
1400 	}
1401 
1402 	/* create meta file in TEE file directory */
1403 	meta = create_meta_file(file);
1404 	if (!meta)
1405 		EMSG("Failed to create new meta file");
1406 
1407 exit:
1408 	return meta;
1409 }
1410 
1411 static struct tee_fs_file_meta *open_tee_file(const char *file)
1412 {
1413 	struct tee_fs_file_meta *meta = NULL;
1414 	int backup_version = 0;
1415 
1416 	DMSG("Opening TEE file=%s", file);
1417 
1418 	meta = open_meta_file(file, backup_version);
1419 	if (!meta) {
1420 		meta = open_meta_file(file, !backup_version);
1421 		if (!meta) {
1422 			/*
1423 			 * cannot open meta file, assumed the TEE file
1424 			 * is corrupted
1425 			 */
1426 			EMSG("Can not open meta file");
1427 		}
1428 	}
1429 
1430 	return meta;
1431 }
1432 
1433 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
1434 				   tee_fs_off_t new_file_len);
1435 
1436 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...)
1437 {
1438 	int res = -1;
1439 	size_t len;
1440 	struct tee_fs_file_meta *meta = NULL;
1441 	struct tee_fs_fd *fdp = NULL;
1442 	bool file_exist;
1443 
1444 	assert(errno);
1445 	*errno = TEE_SUCCESS;
1446 
1447 	if (!file) {
1448 		*errno = TEE_ERROR_BAD_PARAMETERS;
1449 		goto exit;
1450 	}
1451 
1452 	len = strlen(file) + 1;
1453 	if (len > TEE_FS_NAME_MAX) {
1454 		*errno = TEE_ERROR_BAD_PARAMETERS;
1455 		goto exit;
1456 	}
1457 
1458 	file_exist = tee_file_exists(file);
1459 	if (flags & TEE_FS_O_CREATE) {
1460 		if ((flags & TEE_FS_O_EXCL) && file_exist) {
1461 			DMSG("tee file already exists");
1462 			*errno = TEE_ERROR_ACCESS_CONFLICT;
1463 			goto exit;
1464 		}
1465 
1466 		if (!file_exist)
1467 			meta = create_tee_file(file);
1468 		else
1469 			meta = open_tee_file(file);
1470 
1471 	} else {
1472 		if (!file_exist) {
1473 			DMSG("tee file not exists");
1474 			*errno = TEE_ERROR_ITEM_NOT_FOUND;
1475 			goto exit;
1476 		}
1477 
1478 		meta = open_tee_file(file);
1479 	}
1480 
1481 	if (!meta) {
1482 		EMSG("Failed to open TEE file");
1483 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1484 		goto exit;
1485 	}
1486 
1487 	DMSG("file=%s, length=%zd", file, meta->info.length);
1488 	fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd));
1489 	if (!fdp) {
1490 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1491 		goto exit_free_meta;
1492 	}
1493 
1494 	/* init internal status */
1495 	fdp->flags = flags;
1496 	fdp->meta = meta;
1497 	fdp->pos = 0;
1498 	if (init_block_cache(&fdp->block_cache)) {
1499 		res = -1;
1500 		goto exit_free_fd;
1501 	}
1502 
1503 	fdp->filename = malloc(len);
1504 	if (!fdp->filename) {
1505 		res = -1;
1506 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1507 		goto exit_destroy_block_cache;
1508 	}
1509 	memcpy(fdp->filename, file, len);
1510 
1511 	if ((flags & TEE_FS_O_TRUNC) &&
1512 		(flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) {
1513 		res = ree_fs_ftruncate_internal(errno, fdp, 0);
1514 		if (res < 0) {
1515 			EMSG("Unable to truncate file");
1516 			goto exit_free_filename;
1517 		}
1518 	}
1519 
1520 	/* return fd */
1521 	res = handle_get(&fs_handle_db, fdp);
1522 	if (res < 0)
1523 		goto exit_free_filename;
1524 	fdp->fd = res;
1525 	goto exit;
1526 
1527 exit_free_filename:
1528 	free(fdp->filename);
1529 exit_destroy_block_cache:
1530 	destroy_block_cache(&fdp->block_cache);
1531 exit_free_fd:
1532 	free(fdp);
1533 exit_free_meta:
1534 	free(meta);
1535 exit:
1536 	return res;
1537 }
1538 
1539 static int ree_fs_close(int fd)
1540 {
1541 	int res = -1;
1542 	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
1543 
1544 	if (!fdp)
1545 		return -1;
1546 
1547 	handle_put(&fs_handle_db, fdp->fd);
1548 
1549 	destroy_block_cache(&fdp->block_cache);
1550 	free(fdp->meta);
1551 	free(fdp->filename);
1552 	free(fdp);
1553 
1554 	return res;
1555 }
1556 
1557 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd,
1558 				 tee_fs_off_t offset, int whence)
1559 {
1560 	tee_fs_off_t res = -1;
1561 	tee_fs_off_t new_pos;
1562 	size_t filelen;
1563 	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
1564 
1565 	assert(errno);
1566 	*errno = TEE_SUCCESS;
1567 
1568 	if (!fdp) {
1569 		*errno = TEE_ERROR_BAD_PARAMETERS;
1570 		goto exit;
1571 	}
1572 
1573 	DMSG("offset=%d, whence=%d", (int)offset, whence);
1574 
1575 	filelen = fdp->meta->info.length;
1576 
1577 	switch (whence) {
1578 	case TEE_FS_SEEK_SET:
1579 		new_pos = offset;
1580 		break;
1581 
1582 	case TEE_FS_SEEK_CUR:
1583 		new_pos = fdp->pos + offset;
1584 		break;
1585 
1586 	case TEE_FS_SEEK_END:
1587 		new_pos = filelen + offset;
1588 		break;
1589 
1590 	default:
1591 		*errno = TEE_ERROR_BAD_PARAMETERS;
1592 		goto exit;
1593 	}
1594 
1595 	if (new_pos < 0)
1596 		new_pos = 0;
1597 
1598 	if (new_pos > TEE_DATA_MAX_POSITION) {
1599 		EMSG("Position is beyond TEE_DATA_MAX_POSITION");
1600 		*errno = TEE_ERROR_BAD_PARAMETERS;
1601 		goto exit;
1602 	}
1603 
1604 	res = fdp->pos = new_pos;
1605 exit:
1606 	return res;
1607 }
1608 
1609 /*
1610  * To ensure atomic truncate operation, we can:
1611  *
1612  *  - update file length to new length
1613  *  - commit new meta
1614  *  - free unused blocks
1615  *
1616  * To ensure atomic extend operation, we can:
1617  *
1618  *  - update file length to new length
1619  *  - allocate and fill zero data to new blocks
1620  *  - commit new meta
1621  *
1622  * Any failure before committing new meta is considered as
1623  * update failed, and the file content will not be updated
1624  */
1625 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
1626 				   tee_fs_off_t new_file_len)
1627 {
1628 	int res = -1;
1629 	size_t old_file_len = fdp->meta->info.length;
1630 	struct tee_fs_file_meta *new_meta = NULL;
1631 	uint8_t *buf = NULL;
1632 
1633 	assert(errno);
1634 	*errno = TEE_SUCCESS;
1635 
1636 	if (!fdp) {
1637 		*errno = TEE_ERROR_BAD_PARAMETERS;
1638 		res = -1;
1639 		goto exit;
1640 	}
1641 
1642 	if (fdp->flags & TEE_FS_O_RDONLY) {
1643 		*errno = TEE_ERROR_BAD_PARAMETERS;
1644 		EMSG("Read only");
1645 		res = -1;
1646 		goto exit;
1647 	}
1648 
1649 	if ((size_t)new_file_len == old_file_len) {
1650 		DMSG("Ignore due to file length does not changed");
1651 		res = 0;
1652 		goto exit;
1653 	}
1654 
1655 	if (new_file_len > MAX_FILE_SIZE) {
1656 		*errno = TEE_ERROR_BAD_PARAMETERS;
1657 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1658 		res = -1;
1659 		goto exit;
1660 	}
1661 
1662 	new_meta = duplicate_meta(fdp);
1663 	if (!new_meta) {
1664 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1665 		res = -1;
1666 		goto free;
1667 	}
1668 
1669 	new_meta->info.length = new_file_len;
1670 
1671 	if ((size_t)new_file_len < old_file_len) {
1672 		int old_block_num = get_last_block_num(old_file_len);
1673 		int new_block_num = get_last_block_num(new_file_len);
1674 
1675 		DMSG("Truncate file length to %zu", (size_t)new_file_len);
1676 
1677 		res = commit_meta_file(fdp, new_meta);
1678 		if (res < 0) {
1679 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1680 			EMSG("Failed to commit meta file");
1681 			goto free;
1682 		}
1683 
1684 		/* now we are safe to free unused blocks */
1685 		while (old_block_num > new_block_num) {
1686 			if (remove_block_file(fdp, old_block_num)) {
1687 				IMSG("Warning: Failed to free block: %d",
1688 						old_block_num);
1689 			}
1690 
1691 			old_block_num--;
1692 		}
1693 
1694 	} else {
1695 		size_t ext_len = new_file_len - old_file_len;
1696 		int orig_pos = fdp->pos;
1697 
1698 		buf = malloc(BLOCK_FILE_SIZE);
1699 		if (!buf) {
1700 			*errno = TEE_ERROR_OUT_OF_MEMORY;
1701 			EMSG("Failed to allocate buffer, size=%d",
1702 					BLOCK_FILE_SIZE);
1703 			res = -1;
1704 			goto free;
1705 		}
1706 
1707 		memset(buf, 0x0, BLOCK_FILE_SIZE);
1708 
1709 		DMSG("Extend file length to %zu", (size_t)new_file_len);
1710 
1711 		fdp->pos = old_file_len;
1712 
1713 		res = 0;
1714 		while (ext_len > 0) {
1715 			size_t data_len = (ext_len > BLOCK_FILE_SIZE) ?
1716 					BLOCK_FILE_SIZE : ext_len;
1717 
1718 			DMSG("fill len=%zu", data_len);
1719 			res = out_of_place_write(fdp, (void *)buf,
1720 					data_len, new_meta);
1721 			if (res < 0) {
1722 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1723 				EMSG("Failed to fill data");
1724 				break;
1725 			}
1726 
1727 			ext_len -= data_len;
1728 		}
1729 
1730 		fdp->pos = orig_pos;
1731 
1732 		if (res == 0) {
1733 			res = commit_meta_file(fdp, new_meta);
1734 			if (res < 0) {
1735 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1736 				EMSG("Failed to commit meta file");
1737 			}
1738 		}
1739 	}
1740 
1741 free:
1742 	free(new_meta);
1743 	free(buf);
1744 
1745 exit:
1746 	return res;
1747 }
1748 
1749 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len)
1750 {
1751 	int res = -1;
1752 	int start_block_num;
1753 	int end_block_num;
1754 	size_t remain_bytes = len;
1755 	uint8_t *data_ptr = buf;
1756 	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
1757 
1758 	assert(errno);
1759 	*errno = TEE_SUCCESS;
1760 
1761 	if (!fdp) {
1762 		*errno = TEE_ERROR_BAD_PARAMETERS;
1763 		goto exit;
1764 	}
1765 
1766 	if (fdp->pos + len > fdp->meta->info.length) {
1767 		len = fdp->meta->info.length - fdp->pos;
1768 		DMSG("reached EOF, update read length to %zu", len);
1769 	}
1770 
1771 	if (!len) {
1772 		res = 0;
1773 		goto exit;
1774 	}
1775 
1776 	if (!buf) {
1777 		*errno = TEE_ERROR_BAD_PARAMETERS;
1778 		goto exit;
1779 	}
1780 
1781 	if (fdp->flags & TEE_FS_O_WRONLY) {
1782 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1783 		goto exit;
1784 	}
1785 
1786 	DMSG("%s, data len=%zu", fdp->filename, len);
1787 
1788 	start_block_num = pos_to_block_num(fdp->pos);
1789 	end_block_num = pos_to_block_num(fdp->pos + len - 1);
1790 	DMSG("start_block_num:%d, end_block_num:%d",
1791 		start_block_num, end_block_num);
1792 
1793 	while (start_block_num <= end_block_num) {
1794 		struct block *b;
1795 		int offset = fdp->pos % BLOCK_FILE_SIZE;
1796 		size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ?
1797 			BLOCK_FILE_SIZE : remain_bytes;
1798 
1799 		if (size_to_read + offset > BLOCK_FILE_SIZE)
1800 			size_to_read = BLOCK_FILE_SIZE - offset;
1801 
1802 		DMSG("block_num:%d, offset:%d, size_to_read: %zd",
1803 			start_block_num, offset, size_to_read);
1804 
1805 		b = block_ops.read(fdp, start_block_num);
1806 		if (!b) {
1807 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1808 			goto exit;
1809 		}
1810 
1811 		read_data_from_block(b, offset, data_ptr, size_to_read);
1812 		data_ptr += size_to_read;
1813 		remain_bytes -= size_to_read;
1814 		fdp->pos += size_to_read;
1815 
1816 		start_block_num++;
1817 	}
1818 	res = 0;
1819 exit:
1820 	return (res < 0) ? res : (int)len;
1821 }
1822 
1823 /*
1824  * To ensure atomicity of write operation, we need to
1825  * do the following steps:
1826  * (The sequence of operations is very important)
1827  *
1828  *  - Create a new backup version of meta file as a copy
1829  *    of current meta file.
1830  *  - For each blocks to write:
1831  *    - Create new backup version for current block.
1832  *    - Write data to new backup version.
1833  *    - Update the new meta file accordingly.
1834  *  - Write the new meta file.
1835  *
1836  * (Any failure in above steps is considered as update failed,
1837  *  and the file content will not be updated)
1838  *
1839  * After previous step the update is considered complete, but
1840  * we should do the following clean-up step(s):
1841  *
1842  *  - Delete old meta file.
1843  *  - Remove old block files.
1844  *
1845  * (Any failure in above steps is considered as a successfully
1846  *  update)
1847  */
1848 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len)
1849 {
1850 	int res = -1;
1851 	struct tee_fs_file_meta *new_meta = NULL;
1852 	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
1853 	size_t file_size;
1854 	int orig_pos;
1855 
1856 	assert(errno);
1857 	*errno = TEE_SUCCESS;
1858 
1859 	if (!fdp) {
1860 		*errno = TEE_ERROR_BAD_PARAMETERS;
1861 		goto exit;
1862 	}
1863 	if (!len) {
1864 		res = 0;
1865 		goto exit;
1866 	}
1867 	if (!buf) {
1868 		*errno = TEE_ERROR_BAD_PARAMETERS;
1869 		goto exit;
1870 	}
1871 
1872 	file_size = fdp->meta->info.length;
1873 	orig_pos = fdp->pos;
1874 
1875 	if (fdp->flags & TEE_FS_O_RDONLY) {
1876 		EMSG("Write to a read-only file, denied");
1877 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1878 		goto exit;
1879 	}
1880 
1881 	if ((fdp->pos + len) > MAX_FILE_SIZE) {
1882 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1883 		*errno = TEE_ERROR_BAD_PARAMETERS;
1884 		goto exit;
1885 	}
1886 
1887 	DMSG("%s, data len=%zu", fdp->filename, len);
1888 	if (file_size < (size_t)fdp->pos) {
1889 		DMSG("File hole detected, try to extend file size");
1890 		res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos);
1891 		if (res < 0)
1892 			goto exit;
1893 	}
1894 
1895 	new_meta = duplicate_meta(fdp);
1896 	if (!new_meta) {
1897 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1898 		goto exit;
1899 	}
1900 
1901 	res = out_of_place_write(fdp, buf, len, new_meta);
1902 	if (res < 0) {
1903 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1904 	} else {
1905 		int r;
1906 		int start_block_num;
1907 		int end_block_num;
1908 
1909 		r = commit_meta_file(fdp, new_meta);
1910 		if (r < 0) {
1911 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1912 			res = -1;
1913 		}
1914 
1915 		/* we are safe to free old blocks */
1916 		start_block_num = pos_to_block_num(orig_pos);
1917 		end_block_num = pos_to_block_num(fdp->pos - 1);
1918 		while (start_block_num <= end_block_num) {
1919 			if (remove_outdated_block(fdp, start_block_num))
1920 				IMSG("Warning: Failed to free old block: %d",
1921 					start_block_num);
1922 
1923 			start_block_num++;
1924 		}
1925 	}
1926 exit:
1927 	free(new_meta);
1928 	return (res < 0) ? res : (int)len;
1929 }
1930 
1931 /*
1932  * To ensure atomicity of rename operation, we need to
1933  * do the following steps:
1934  *
1935  *  - Create a new folder that represents the renamed TEE file
1936  *  - For each REE block files, create a hard link under the just
1937  *    created folder (new TEE file)
1938  *  - Now we are ready to commit meta, create hard link for the
1939  *    meta file
1940  *
1941  * (Any failure in above steps is considered as update failed,
1942  *  and the file content will not be updated)
1943  *
1944  * After previous step the update is considered complete, but
1945  * we should do the following clean-up step(s):
1946  *
1947  *  - Unlink all REE files represents the old TEE file (including
1948  *    meta and block files)
1949  *
1950  * (Any failure in above steps is considered as a successfully
1951  *  update)
1952  */
1953 static int ree_fs_rename(const char *old, const char *new)
1954 {
1955 	int res = -1;
1956 	size_t old_len;
1957 	size_t new_len;
1958 	size_t meta_count = 0;
1959 	struct tee_fs_dir *old_dir;
1960 	struct tee_fs_dirent *dirent;
1961 	char *meta_filename = NULL;
1962 
1963 	if (!old || !new)
1964 		return -1;
1965 
1966 	DMSG("old=%s, new=%s", old, new);
1967 
1968 	old_len = strlen(old) + 1;
1969 	new_len = strlen(new) + 1;
1970 
1971 	if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX)
1972 		goto exit;
1973 
1974 	res = ree_fs_mkdir_ree(new,
1975 			TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
1976 	if (res)
1977 		goto exit;
1978 
1979 	old_dir = ree_fs_opendir_ree(old);
1980 	if (!old_dir)
1981 		goto exit;
1982 
1983 	dirent = ree_fs_readdir_ree(old_dir);
1984 	while (dirent) {
1985 		if (!strncmp(dirent->d_name, "meta.", 5)) {
1986 			meta_filename = strdup(dirent->d_name);
1987 			meta_count++;
1988 		} else {
1989 			res = create_hard_link(old, new, dirent->d_name);
1990 			if (res)
1991 				goto exit_close_old_dir;
1992 		}
1993 
1994 		dirent = ree_fs_readdir_ree(old_dir);
1995 	}
1996 
1997 	/* finally, link the meta file, rename operation completed */
1998 	TEE_ASSERT(meta_filename);
1999 
2000 	/*
2001 	 * TODO: This will cause memory leakage at previous strdup()
2002 	 * if we accidently have two meta files in a TEE file.
2003 	 *
2004 	 * It's not easy to handle the case above (e.g. Which meta file
2005 	 * should be linked first? What to do if a power cut happened
2006 	 * during creating links for the two meta files?)
2007 	 *
2008 	 * We will solve this issue using another approach: merging
2009 	 * both meta and block files into a single REE file. This approach
2010 	 * can completely remove ree_fs_rename(). We can simply
2011 	 * rename TEE file using REE rename() system call, which is also
2012 	 * atomic.
2013 	 */
2014 	if (meta_count > 1)
2015 		EMSG("Warning: more than one meta file in your TEE file\n"
2016 		     "This will cause memory leakage.");
2017 
2018 	res = create_hard_link(old, new, meta_filename);
2019 	if (res)
2020 		goto exit_close_old_dir;
2021 
2022 	/* we are safe now, remove old TEE file */
2023 	unlink_tee_file(old);
2024 
2025 exit_close_old_dir:
2026 	ree_fs_closedir_ree(old_dir);
2027 exit:
2028 	free(meta_filename);
2029 	return res;
2030 }
2031 
2032 /*
2033  * To ensure atomic unlink operation, we can simply
2034  * split the unlink operation into:
2035  *
2036  *  - rename("file", "file.trash");
2037  *
2038  * (Any failure in above steps is considered as update failed,
2039  *  and the file content will not be updated)
2040  *
2041  * After previous step the update is considered complete, but
2042  * we should do the following clean-up step(s):
2043  *
2044  *  - unlink("file.trash");
2045  *
2046  * (Any failure in above steps is considered as a successfully
2047  *  update)
2048  */
2049 static int ree_fs_unlink(const char *file)
2050 {
2051 	int res = -1;
2052 	char trash_file[TEE_FS_NAME_MAX + 6];
2053 
2054 	if (!file)
2055 		return -1;
2056 
2057 	snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash",
2058 		file);
2059 
2060 	res = ree_fs_rename(file, trash_file);
2061 	if (res < 0)
2062 		return res;
2063 
2064 	unlink_tee_file(trash_file);
2065 
2066 	return res;
2067 }
2068 
2069 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length)
2070 {
2071 	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
2072 
2073 	return ree_fs_ftruncate_internal(errno, fdp, length);
2074 }
2075 
2076 const struct tee_file_operations ree_fs_ops = {
2077 	.open = ree_fs_open,
2078 	.close = ree_fs_close,
2079 	.read = ree_fs_read,
2080 	.write = ree_fs_write,
2081 	.lseek = ree_fs_lseek,
2082 	.ftruncate = ree_fs_ftruncate,
2083 	.rename = ree_fs_rename,
2084 	.unlink = ree_fs_unlink,
2085 	.mkdir = ree_fs_mkdir_ree,
2086 	.opendir = ree_fs_opendir_ree,
2087 	.closedir = ree_fs_closedir_ree,
2088 	.readdir = ree_fs_readdir_ree,
2089 	.rmdir = ree_fs_rmdir_ree,
2090 	.access = ree_fs_access_ree
2091 };
2092