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