xref: /optee_os/core/tee/tee_ree_fs.c (revision 8dceff9b18e7c2e0cb879ea458e85a1806dff447)
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 static int read_block_from_storage(struct tee_fs_fd *fdp, struct block *b)
562 {
563 	int fd, res = 0;
564 	uint8_t *plaintext = b->data;
565 	char block_path[REE_FS_NAME_MAX];
566 	size_t block_file_size = BLOCK_FILE_SIZE;
567 	uint8_t version = get_backup_version_of_block(fdp->meta,
568 			b->block_num);
569 
570 	if (!is_block_file_exist(fdp->meta, b->block_num))
571 		goto exit;
572 
573 	get_block_filepath(fdp->filename, b->block_num, version,
574 			block_path);
575 
576 	fd = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_FS, block_path,
577 			     TEE_FS_O_RDONLY);
578 	if (fd < 0)
579 		return fd;
580 
581 	res = read_and_decrypt_file(fd, BLOCK_FILE,
582 			plaintext, &block_file_size,
583 			fdp->meta->encrypted_fek);
584 	if (res < 0) {
585 		EMSG("Failed to read and decrypt file");
586 		goto fail;
587 	}
588 	b->data_size = block_file_size;
589 	DMSG("Successfully read and decrypt block%d from storage, size=%zd",
590 		b->block_num, b->data_size);
591 fail:
592 	tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fd);
593 exit:
594 	return res;
595 }
596 
597 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b,
598 		struct tee_fs_file_meta *new_meta)
599 {
600 	int fd = -1;
601 	int res;
602 	size_t block_num = b->block_num;
603 
604 	fd = create_block_file(
605 			fdp, new_meta, block_num);
606 	if (fd < 0) {
607 		EMSG("Failed to create new version of block");
608 		res = -1;
609 		goto fail;
610 	}
611 
612 	res = encrypt_and_write_file(fd, BLOCK_FILE,
613 			b->data, b->data_size,
614 			new_meta->encrypted_fek);
615 	if (res < 0) {
616 		EMSG("Failed to encrypt and write block file");
617 		goto fail;
618 	}
619 	DMSG("Successfully encrypt and write block%d to storage, size=%zd",
620 		b->block_num, b->data_size);
621 
622 fail:
623 	if (fd > 0)
624 		tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fd);
625 
626 	return res;
627 }
628 
629 static struct block *alloc_block(void)
630 {
631 	struct block *c;
632 
633 	c = malloc(sizeof(struct block));
634 	if (!c)
635 		return NULL;
636 
637 	c->data = malloc(BLOCK_FILE_SIZE);
638 	if (!c->data) {
639 		EMSG("unable to alloc memory for block data");
640 		goto exit;
641 	}
642 
643 	c->block_num = -1;
644 	c->data_size = 0;
645 
646 	return c;
647 
648 exit:
649 	free(c);
650 	return NULL;
651 }
652 
653 #ifdef CFG_FS_BLOCK_CACHE
654 static void free_block(struct block *b)
655 {
656 	if (b) {
657 		free(b->data);
658 		free(b);
659 	}
660 }
661 
662 static inline bool is_block_data_invalid(struct block *b)
663 {
664 	return (b->data_size == 0);
665 }
666 
667 static void get_block_from_cache(struct block_cache *cache,
668 			int block_num, struct block **out_block)
669 {
670 	struct block *b, *found = NULL;
671 
672 	DMSG("Try to find block%d in cache", block_num);
673 	TAILQ_FOREACH(b, &cache->block_lru, list) {
674 		if (b->block_num == block_num) {
675 			DMSG("Found in cache");
676 			found = b;
677 			break;
678 		}
679 	}
680 
681 	if (found) {
682 		TAILQ_REMOVE(&cache->block_lru, found, list);
683 		TAILQ_INSERT_HEAD(&cache->block_lru, found, list);
684 		*out_block = found;
685 		return;
686 	}
687 
688 	DMSG("Not found, reuse oldest block on LRU list");
689 	b = TAILQ_LAST(&cache->block_lru, block_head);
690 	TAILQ_REMOVE(&cache->block_lru, b, list);
691 	TAILQ_INSERT_HEAD(&cache->block_lru, b, list);
692 	b->block_num = block_num;
693 	b->data_size = 0;
694 	*out_block = b;
695 }
696 
697 static int init_block_cache(struct block_cache *cache)
698 {
699 	struct block *b;
700 
701 	TAILQ_INIT(&cache->block_lru);
702 	cache->cached_block_num = 0;
703 
704 	while (cache->cached_block_num < MAX_NUM_CACHED_BLOCKS) {
705 
706 		b = alloc_block();
707 		if (!b) {
708 			EMSG("Failed to alloc block");
709 			goto fail;
710 		} else {
711 			TAILQ_INSERT_HEAD(&cache->block_lru, b, list);
712 			cache->cached_block_num++;
713 		}
714 	}
715 	return 0;
716 
717 fail:
718 	TAILQ_FOREACH(b, &cache->block_lru, list)
719 		free_block(b);
720 	return -1;
721 }
722 
723 static void destroy_block_cache(struct block_cache *cache)
724 {
725 	struct block *b, *next;
726 
727 	TAILQ_FOREACH_SAFE(b, &cache->block_lru, list, next) {
728 		TAILQ_REMOVE(&cache->block_lru, b, list);
729 		free_block(b);
730 	}
731 }
732 #else
733 static int init_block_cache(struct block_cache *cache __unused)
734 {
735 	return 0;
736 }
737 
738 static void destroy_block_cache(struct block_cache *cache __unused)
739 {
740 }
741 #endif
742 
743 static void write_data_to_block(struct block *b, int offset,
744 				void *buf, size_t len)
745 {
746 	DMSG("Write %zd bytes to block%d", len, b->block_num);
747 	memcpy(b->data + offset, buf, len);
748 	if (offset + len > b->data_size) {
749 		b->data_size = offset + len;
750 		DMSG("Extend block%d size to %zd bytes",
751 				b->block_num, b->data_size);
752 	}
753 }
754 
755 static void read_data_from_block(struct block *b, int offset,
756 				void *buf, size_t len)
757 {
758 	DMSG("Read %zd bytes from block%d", len, b->block_num);
759 	if (offset + len > b->data_size)
760 		panic("Exceeding block size");
761 	memcpy(buf, b->data + offset, len);
762 }
763 
764 #ifdef CFG_FS_BLOCK_CACHE
765 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num)
766 {
767 	struct block *b;
768 
769 	get_block_from_cache(&fdp->block_cache, block_num, &b);
770 	if (is_block_data_invalid(b))
771 		if (read_block_from_storage(fdp, b)) {
772 			EMSG("Unable to read block%d from storage",
773 					block_num);
774 			return NULL;
775 		}
776 
777 	return b;
778 }
779 #else
780 
781 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num)
782 {
783 	static struct block *b;
784 	int res;
785 
786 	if (!b)
787 		b = alloc_block();
788 	b->block_num = block_num;
789 
790 	res = read_block_from_storage(fdp, b);
791 	if (res)
792 		EMSG("Unable to read block%d from storage",
793 				block_num);
794 
795 	return res ? NULL : b;
796 }
797 #endif
798 
799 static struct block_operations block_ops = {
800 #ifdef CFG_FS_BLOCK_CACHE
801 	.read = read_block_with_cache,
802 #else
803 	.read = read_block_no_cache,
804 #endif
805 	.write = flush_block_to_storage,
806 };
807 
808 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
809 		size_t len, struct tee_fs_file_meta *new_meta)
810 {
811 	int start_block_num = pos_to_block_num(fdp->pos);
812 	int end_block_num = pos_to_block_num(fdp->pos + len - 1);
813 	size_t remain_bytes = len;
814 	uint8_t *data_ptr = (uint8_t *)buf;
815 	int orig_pos = fdp->pos;
816 
817 	while (start_block_num <= end_block_num) {
818 		int offset = fdp->pos % BLOCK_FILE_SIZE;
819 		struct block *b;
820 		size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ?
821 			BLOCK_FILE_SIZE : remain_bytes;
822 
823 		if (size_to_write + offset > BLOCK_FILE_SIZE)
824 			size_to_write = BLOCK_FILE_SIZE - offset;
825 
826 		b = block_ops.read(fdp, start_block_num);
827 		if (!b)
828 			goto failed;
829 
830 		DMSG("Write data, offset: %d, size_to_write: %zd",
831 			offset, size_to_write);
832 		write_data_to_block(b, offset, data_ptr, size_to_write);
833 
834 		if (block_ops.write(fdp, b, new_meta)) {
835 			EMSG("Unable to wrtie block%d to storage",
836 					b->block_num);
837 			goto failed;
838 		}
839 
840 		data_ptr += size_to_write;
841 		remain_bytes -= size_to_write;
842 		start_block_num++;
843 		fdp->pos += size_to_write;
844 	}
845 
846 	if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
847 		new_meta->info.length = fdp->pos;
848 
849 	return 0;
850 failed:
851 	fdp->pos = orig_pos;
852 	return -1;
853 }
854 
855 static inline int create_hard_link(const char *old_dir,
856 			const char *new_dir,
857 			const char *filename)
858 {
859 	char old_path[REE_FS_NAME_MAX];
860 	char new_path[REE_FS_NAME_MAX];
861 
862 	snprintf(old_path, REE_FS_NAME_MAX, "%s/%s",
863 			old_dir, filename);
864 	snprintf(new_path, REE_FS_NAME_MAX, "%s/%s",
865 			new_dir, filename);
866 
867 	DMSG("%s -> %s", old_path, new_path);
868 	return tee_fs_rpc_link(OPTEE_MSG_RPC_CMD_FS, old_path, new_path);
869 }
870 
871 static int unlink_tee_file(const char *file)
872 {
873 	int res = -1;
874 	size_t len = strlen(file) + 1;
875 	struct tee_fs_dirent *dirent;
876 	struct tee_fs_dir *dir;
877 
878 	DMSG("file=%s", file);
879 
880 	if (len > TEE_FS_NAME_MAX)
881 		goto exit;
882 
883 	dir = ree_fs_opendir_rpc(file);
884 	if (!dir)
885 		goto exit;
886 
887 	dirent = ree_fs_readdir_rpc(dir);
888 	while (dirent) {
889 		char path[REE_FS_NAME_MAX];
890 
891 		snprintf(path, REE_FS_NAME_MAX, "%s/%s",
892 			file, dirent->d_name);
893 
894 		DMSG("unlink %s", path);
895 		res = tee_fs_rpc_unlink(OPTEE_MSG_RPC_CMD_FS, path);
896 		if (res) {
897 			ree_fs_closedir_rpc(dir);
898 			goto exit;
899 		}
900 
901 		dirent = ree_fs_readdir_rpc(dir);
902 	}
903 
904 	res = ree_fs_closedir_rpc(dir);
905 	if (res)
906 		goto exit;
907 
908 	res = ree_fs_rmdir_rpc(file);
909 exit:
910 	return res;
911 }
912 
913 static bool tee_file_exists(const char *file)
914 {
915 	char meta_path[REE_FS_NAME_MAX];
916 
917 	get_meta_filepath(file, 0, meta_path);
918 	if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK)) {
919 		get_meta_filepath(file, 1, meta_path);
920 		if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK))
921 			return false;
922 	}
923 
924 	return true;
925 }
926 
927 static struct tee_fs_file_meta *create_tee_file(const char *file)
928 {
929 	struct tee_fs_file_meta *meta = NULL;
930 	int res;
931 
932 	DMSG("Creating TEE file=%s", file);
933 
934 	/* create TEE file directory if not exist */
935 	if (ree_fs_access_rpc(file, TEE_FS_F_OK)) {
936 		res = ree_fs_mkdir_rpc(file,
937 				TEE_FS_S_IRUSR | TEE_FS_S_IWUSR | TEE_FS_S_IXUSR);
938 		if (res) {
939 			EMSG("Failed to create TEE file directory, res=%d",
940 				res);
941 			goto exit;
942 		}
943 	}
944 
945 	/* create meta file in TEE file directory */
946 	meta = create_meta_file(file);
947 	if (!meta)
948 		EMSG("Failed to create new meta file");
949 
950 exit:
951 	return meta;
952 }
953 
954 static struct tee_fs_file_meta *open_tee_file(const char *file)
955 {
956 	struct tee_fs_file_meta *meta = NULL;
957 	int backup_version = 0;
958 
959 	DMSG("Opening TEE file=%s", file);
960 
961 	meta = open_meta_file(file, backup_version);
962 	if (!meta) {
963 		meta = open_meta_file(file, !backup_version);
964 		if (!meta) {
965 			/*
966 			 * cannot open meta file, assumed the TEE file
967 			 * is corrupted
968 			 */
969 			EMSG("Can not open meta file");
970 		}
971 	}
972 
973 	return meta;
974 }
975 
976 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
977 				   tee_fs_off_t new_file_len);
978 
979 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...)
980 {
981 	int res = -1;
982 	size_t len;
983 	struct tee_fs_file_meta *meta = NULL;
984 	struct tee_fs_fd *fdp = NULL;
985 	bool file_exist;
986 
987 	mutex_lock(&ree_fs_mutex);
988 
989 	assert(errno);
990 	*errno = TEE_SUCCESS;
991 
992 	if (!file) {
993 		*errno = TEE_ERROR_BAD_PARAMETERS;
994 		goto exit;
995 	}
996 
997 	len = strlen(file) + 1;
998 	if (len > TEE_FS_NAME_MAX) {
999 		*errno = TEE_ERROR_BAD_PARAMETERS;
1000 		goto exit;
1001 	}
1002 
1003 	file_exist = tee_file_exists(file);
1004 	if (flags & TEE_FS_O_CREATE) {
1005 		if ((flags & TEE_FS_O_EXCL) && file_exist) {
1006 			DMSG("tee file already exists");
1007 			*errno = TEE_ERROR_ACCESS_CONFLICT;
1008 			goto exit;
1009 		}
1010 
1011 		if (!file_exist)
1012 			meta = create_tee_file(file);
1013 		else
1014 			meta = open_tee_file(file);
1015 
1016 	} else {
1017 		if (!file_exist) {
1018 			DMSG("tee file not exists");
1019 			*errno = TEE_ERROR_ITEM_NOT_FOUND;
1020 			goto exit;
1021 		}
1022 
1023 		meta = open_tee_file(file);
1024 	}
1025 
1026 	if (!meta) {
1027 		EMSG("Failed to open TEE file");
1028 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1029 		goto exit;
1030 	}
1031 
1032 	DMSG("file=%s, length=%zd", file, meta->info.length);
1033 	fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd));
1034 	if (!fdp) {
1035 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1036 		goto exit_free_meta;
1037 	}
1038 
1039 	/* init internal status */
1040 	fdp->flags = flags;
1041 	fdp->meta = meta;
1042 	fdp->pos = 0;
1043 	if (init_block_cache(&fdp->block_cache)) {
1044 		res = -1;
1045 		goto exit_free_fd;
1046 	}
1047 
1048 	fdp->filename = malloc(len);
1049 	if (!fdp->filename) {
1050 		res = -1;
1051 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1052 		goto exit_destroy_block_cache;
1053 	}
1054 	memcpy(fdp->filename, file, len);
1055 
1056 	if ((flags & TEE_FS_O_TRUNC) &&
1057 		(flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) {
1058 		res = ree_fs_ftruncate_internal(errno, fdp, 0);
1059 		if (res < 0) {
1060 			EMSG("Unable to truncate file");
1061 			goto exit_free_filename;
1062 		}
1063 	}
1064 
1065 	/* return fd */
1066 	res = handle_get(&fs_handle_db, fdp);
1067 	if (res < 0)
1068 		goto exit_free_filename;
1069 	fdp->fd = res;
1070 	goto exit;
1071 
1072 exit_free_filename:
1073 	free(fdp->filename);
1074 exit_destroy_block_cache:
1075 	destroy_block_cache(&fdp->block_cache);
1076 exit_free_fd:
1077 	free(fdp);
1078 exit_free_meta:
1079 	free(meta);
1080 exit:
1081 	mutex_unlock(&ree_fs_mutex);
1082 	return res;
1083 }
1084 
1085 static int ree_fs_close(int fd)
1086 {
1087 	int res = -1;
1088 	struct tee_fs_fd *fdp;
1089 
1090 	mutex_lock(&ree_fs_mutex);
1091 
1092 	fdp = handle_lookup(&fs_handle_db, fd);
1093 	if (!fdp)
1094 		goto exit;
1095 
1096 	handle_put(&fs_handle_db, fdp->fd);
1097 
1098 	destroy_block_cache(&fdp->block_cache);
1099 	free(fdp->meta);
1100 	free(fdp->filename);
1101 	free(fdp);
1102 
1103 exit:
1104 	mutex_unlock(&ree_fs_mutex);
1105 	return res;
1106 }
1107 
1108 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd,
1109 				 tee_fs_off_t offset, int whence)
1110 {
1111 	tee_fs_off_t res = -1;
1112 	tee_fs_off_t new_pos;
1113 	size_t filelen;
1114 	struct tee_fs_fd *fdp;
1115 
1116 	mutex_lock(&ree_fs_mutex);
1117 
1118 	assert(errno);
1119 	*errno = TEE_SUCCESS;
1120 
1121 	fdp = handle_lookup(&fs_handle_db, fd);
1122 	if (!fdp) {
1123 		*errno = TEE_ERROR_BAD_PARAMETERS;
1124 		goto exit;
1125 	}
1126 
1127 	DMSG("offset=%d, whence=%d", (int)offset, whence);
1128 
1129 	filelen = fdp->meta->info.length;
1130 
1131 	switch (whence) {
1132 	case TEE_FS_SEEK_SET:
1133 		new_pos = offset;
1134 		break;
1135 
1136 	case TEE_FS_SEEK_CUR:
1137 		new_pos = fdp->pos + offset;
1138 		break;
1139 
1140 	case TEE_FS_SEEK_END:
1141 		new_pos = filelen + offset;
1142 		break;
1143 
1144 	default:
1145 		*errno = TEE_ERROR_BAD_PARAMETERS;
1146 		goto exit;
1147 	}
1148 
1149 	if (new_pos < 0)
1150 		new_pos = 0;
1151 
1152 	if (new_pos > TEE_DATA_MAX_POSITION) {
1153 		EMSG("Position is beyond TEE_DATA_MAX_POSITION");
1154 		*errno = TEE_ERROR_BAD_PARAMETERS;
1155 		goto exit;
1156 	}
1157 
1158 	res = fdp->pos = new_pos;
1159 exit:
1160 	mutex_unlock(&ree_fs_mutex);
1161 	return res;
1162 }
1163 
1164 /*
1165  * To ensure atomic truncate operation, we can:
1166  *
1167  *  - update file length to new length
1168  *  - commit new meta
1169  *  - free unused blocks
1170  *
1171  * To ensure atomic extend operation, we can:
1172  *
1173  *  - update file length to new length
1174  *  - allocate and fill zero data to new blocks
1175  *  - commit new meta
1176  *
1177  * Any failure before committing new meta is considered as
1178  * update failed, and the file content will not be updated
1179  */
1180 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
1181 				   tee_fs_off_t new_file_len)
1182 {
1183 	int res = -1;
1184 	size_t old_file_len = fdp->meta->info.length;
1185 	struct tee_fs_file_meta *new_meta = NULL;
1186 	uint8_t *buf = NULL;
1187 
1188 	assert(errno);
1189 	*errno = TEE_SUCCESS;
1190 
1191 	if (!fdp) {
1192 		*errno = TEE_ERROR_BAD_PARAMETERS;
1193 		res = -1;
1194 		goto exit;
1195 	}
1196 
1197 	if (fdp->flags & TEE_FS_O_RDONLY) {
1198 		*errno = TEE_ERROR_BAD_PARAMETERS;
1199 		EMSG("Read only");
1200 		res = -1;
1201 		goto exit;
1202 	}
1203 
1204 	if ((size_t)new_file_len == old_file_len) {
1205 		DMSG("Ignore due to file length does not changed");
1206 		res = 0;
1207 		goto exit;
1208 	}
1209 
1210 	if (new_file_len > MAX_FILE_SIZE) {
1211 		*errno = TEE_ERROR_BAD_PARAMETERS;
1212 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1213 		res = -1;
1214 		goto exit;
1215 	}
1216 
1217 	new_meta = duplicate_meta(fdp);
1218 	if (!new_meta) {
1219 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1220 		res = -1;
1221 		goto free;
1222 	}
1223 
1224 	new_meta->info.length = new_file_len;
1225 
1226 	if ((size_t)new_file_len < old_file_len) {
1227 		int old_block_num = get_last_block_num(old_file_len);
1228 		int new_block_num = get_last_block_num(new_file_len);
1229 
1230 		DMSG("Truncate file length to %zu", (size_t)new_file_len);
1231 
1232 		res = commit_meta_file(fdp, new_meta);
1233 		if (res < 0) {
1234 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1235 			EMSG("Failed to commit meta file");
1236 			goto free;
1237 		}
1238 
1239 		/* now we are safe to free unused blocks */
1240 		while (old_block_num > new_block_num) {
1241 			if (remove_block_file(fdp, old_block_num)) {
1242 				IMSG("Warning: Failed to free block: %d",
1243 						old_block_num);
1244 			}
1245 
1246 			old_block_num--;
1247 		}
1248 
1249 	} else {
1250 		size_t ext_len = new_file_len - old_file_len;
1251 		int orig_pos = fdp->pos;
1252 
1253 		buf = malloc(BLOCK_FILE_SIZE);
1254 		if (!buf) {
1255 			*errno = TEE_ERROR_OUT_OF_MEMORY;
1256 			EMSG("Failed to allocate buffer, size=%d",
1257 					BLOCK_FILE_SIZE);
1258 			res = -1;
1259 			goto free;
1260 		}
1261 
1262 		memset(buf, 0x0, BLOCK_FILE_SIZE);
1263 
1264 		DMSG("Extend file length to %zu", (size_t)new_file_len);
1265 
1266 		fdp->pos = old_file_len;
1267 
1268 		res = 0;
1269 		while (ext_len > 0) {
1270 			size_t data_len = (ext_len > BLOCK_FILE_SIZE) ?
1271 					BLOCK_FILE_SIZE : ext_len;
1272 
1273 			DMSG("fill len=%zu", data_len);
1274 			res = out_of_place_write(fdp, (void *)buf,
1275 					data_len, new_meta);
1276 			if (res < 0) {
1277 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1278 				EMSG("Failed to fill data");
1279 				break;
1280 			}
1281 
1282 			ext_len -= data_len;
1283 		}
1284 
1285 		fdp->pos = orig_pos;
1286 
1287 		if (res == 0) {
1288 			res = commit_meta_file(fdp, new_meta);
1289 			if (res < 0) {
1290 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1291 				EMSG("Failed to commit meta file");
1292 			}
1293 		}
1294 	}
1295 
1296 free:
1297 	free(new_meta);
1298 	free(buf);
1299 
1300 exit:
1301 	return res;
1302 }
1303 
1304 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len)
1305 {
1306 	int res = -1;
1307 	int start_block_num;
1308 	int end_block_num;
1309 	size_t remain_bytes = len;
1310 	uint8_t *data_ptr = buf;
1311 	struct tee_fs_fd *fdp;
1312 
1313 	mutex_lock(&ree_fs_mutex);
1314 
1315 	assert(errno);
1316 	*errno = TEE_SUCCESS;
1317 
1318 	fdp = handle_lookup(&fs_handle_db, fd);
1319 	if (!fdp) {
1320 		*errno = TEE_ERROR_BAD_PARAMETERS;
1321 		goto exit;
1322 	}
1323 
1324 	if ((fdp->pos + len) < len ||
1325 	    fdp->pos > (tee_fs_off_t)fdp->meta->info.length)
1326 		len = 0;
1327 	else if (fdp->pos + len > fdp->meta->info.length)
1328 		len = fdp->meta->info.length - fdp->pos;
1329 
1330 	if (!len) {
1331 		res = 0;
1332 		goto exit;
1333 	}
1334 
1335 	if (!buf) {
1336 		*errno = TEE_ERROR_BAD_PARAMETERS;
1337 		goto exit;
1338 	}
1339 
1340 	if (fdp->flags & TEE_FS_O_WRONLY) {
1341 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1342 		goto exit;
1343 	}
1344 
1345 	DMSG("%s, data len=%zu", fdp->filename, len);
1346 
1347 	start_block_num = pos_to_block_num(fdp->pos);
1348 	end_block_num = pos_to_block_num(fdp->pos + len - 1);
1349 	DMSG("start_block_num:%d, end_block_num:%d",
1350 		start_block_num, end_block_num);
1351 
1352 	while (start_block_num <= end_block_num) {
1353 		struct block *b;
1354 		int offset = fdp->pos % BLOCK_FILE_SIZE;
1355 		size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ?
1356 			BLOCK_FILE_SIZE : remain_bytes;
1357 
1358 		if (size_to_read + offset > BLOCK_FILE_SIZE)
1359 			size_to_read = BLOCK_FILE_SIZE - offset;
1360 
1361 		DMSG("block_num:%d, offset:%d, size_to_read: %zd",
1362 			start_block_num, offset, size_to_read);
1363 
1364 		b = block_ops.read(fdp, start_block_num);
1365 		if (!b) {
1366 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1367 			goto exit;
1368 		}
1369 
1370 		read_data_from_block(b, offset, data_ptr, size_to_read);
1371 		data_ptr += size_to_read;
1372 		remain_bytes -= size_to_read;
1373 		fdp->pos += size_to_read;
1374 
1375 		start_block_num++;
1376 	}
1377 	res = 0;
1378 exit:
1379 	mutex_unlock(&ree_fs_mutex);
1380 	return (res < 0) ? res : (int)len;
1381 }
1382 
1383 /*
1384  * To ensure atomicity of write operation, we need to
1385  * do the following steps:
1386  * (The sequence of operations is very important)
1387  *
1388  *  - Create a new backup version of meta file as a copy
1389  *    of current meta file.
1390  *  - For each blocks to write:
1391  *    - Create new backup version for current block.
1392  *    - Write data to new backup version.
1393  *    - Update the new meta file accordingly.
1394  *  - Write the new meta file.
1395  *
1396  * (Any failure in above steps is considered as update failed,
1397  *  and the file content will not be updated)
1398  *
1399  * After previous step the update is considered complete, but
1400  * we should do the following clean-up step(s):
1401  *
1402  *  - Delete old meta file.
1403  *  - Remove old block files.
1404  *
1405  * (Any failure in above steps is considered as a successfully
1406  *  update)
1407  */
1408 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len)
1409 {
1410 	int res = -1;
1411 	struct tee_fs_file_meta *new_meta = NULL;
1412 	struct tee_fs_fd *fdp;
1413 	size_t file_size;
1414 	int orig_pos;
1415 
1416 	mutex_lock(&ree_fs_mutex);
1417 
1418 	assert(errno);
1419 	*errno = TEE_SUCCESS;
1420 
1421 	fdp = handle_lookup(&fs_handle_db, fd);
1422 	if (!fdp) {
1423 		*errno = TEE_ERROR_BAD_PARAMETERS;
1424 		goto exit;
1425 	}
1426 	if (!len) {
1427 		res = 0;
1428 		goto exit;
1429 	}
1430 	if (!buf) {
1431 		*errno = TEE_ERROR_BAD_PARAMETERS;
1432 		goto exit;
1433 	}
1434 
1435 	file_size = fdp->meta->info.length;
1436 	orig_pos = fdp->pos;
1437 
1438 	if (fdp->flags & TEE_FS_O_RDONLY) {
1439 		EMSG("Write to a read-only file, denied");
1440 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1441 		goto exit;
1442 	}
1443 
1444 	if ((fdp->pos + len) > MAX_FILE_SIZE) {
1445 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1446 		*errno = TEE_ERROR_BAD_PARAMETERS;
1447 		goto exit;
1448 	}
1449 
1450 	DMSG("%s, data len=%zu", fdp->filename, len);
1451 	if (file_size < (size_t)fdp->pos) {
1452 		DMSG("File hole detected, try to extend file size");
1453 		res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos);
1454 		if (res < 0)
1455 			goto exit;
1456 	}
1457 
1458 	new_meta = duplicate_meta(fdp);
1459 	if (!new_meta) {
1460 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1461 		goto exit;
1462 	}
1463 
1464 	res = out_of_place_write(fdp, buf, len, new_meta);
1465 	if (res < 0) {
1466 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1467 	} else {
1468 		int r;
1469 		int start_block_num;
1470 		int end_block_num;
1471 
1472 		r = commit_meta_file(fdp, new_meta);
1473 		if (r < 0) {
1474 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1475 			res = -1;
1476 		}
1477 
1478 		/* we are safe to free old blocks */
1479 		start_block_num = pos_to_block_num(orig_pos);
1480 		end_block_num = pos_to_block_num(fdp->pos - 1);
1481 		while (start_block_num <= end_block_num) {
1482 			if (remove_outdated_block(fdp, start_block_num))
1483 				IMSG("Warning: Failed to free old block: %d",
1484 					start_block_num);
1485 
1486 			start_block_num++;
1487 		}
1488 	}
1489 exit:
1490 	mutex_unlock(&ree_fs_mutex);
1491 	free(new_meta);
1492 	return (res < 0) ? res : (int)len;
1493 }
1494 
1495 /*
1496  * To ensure atomicity of rename operation, we need to
1497  * do the following steps:
1498  *
1499  *  - Create a new folder that represents the renamed TEE file
1500  *  - For each REE block files, create a hard link under the just
1501  *    created folder (new TEE file)
1502  *  - Now we are ready to commit meta, create hard link for the
1503  *    meta file
1504  *
1505  * (Any failure in above steps is considered as update failed,
1506  *  and the file content will not be updated)
1507  *
1508  * After previous step the update is considered complete, but
1509  * we should do the following clean-up step(s):
1510  *
1511  *  - Unlink all REE files represents the old TEE file (including
1512  *    meta and block files)
1513  *
1514  * (Any failure in above steps is considered as a successfully
1515  *  update)
1516  */
1517 static int ree_fs_rename_internal(const char *old, const char *new)
1518 {
1519 	int res = -1;
1520 	size_t old_len;
1521 	size_t new_len;
1522 	size_t meta_count = 0;
1523 	struct tee_fs_dir *old_dir;
1524 	struct tee_fs_dirent *dirent;
1525 	char *meta_filename = NULL;
1526 
1527 	if (!old || !new)
1528 		return -1;
1529 
1530 	DMSG("old=%s, new=%s", old, new);
1531 
1532 	old_len = strlen(old) + 1;
1533 	new_len = strlen(new) + 1;
1534 
1535 	if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX)
1536 		goto exit;
1537 
1538 	res = ree_fs_mkdir_rpc(new,
1539 			TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
1540 	if (res)
1541 		goto exit;
1542 
1543 	old_dir = ree_fs_opendir_rpc(old);
1544 	if (!old_dir)
1545 		goto exit;
1546 
1547 	dirent = ree_fs_readdir_rpc(old_dir);
1548 	while (dirent) {
1549 		if (!strncmp(dirent->d_name, "meta.", 5)) {
1550 			meta_filename = strdup(dirent->d_name);
1551 			meta_count++;
1552 		} else {
1553 			res = create_hard_link(old, new, dirent->d_name);
1554 			if (res)
1555 				goto exit_close_old_dir;
1556 		}
1557 
1558 		dirent = ree_fs_readdir_rpc(old_dir);
1559 	}
1560 
1561 	/* finally, link the meta file, rename operation completed */
1562 	if (!meta_filename)
1563 		panic("no meta file");
1564 
1565 	/*
1566 	 * TODO: This will cause memory leakage at previous strdup()
1567 	 * if we accidently have two meta files in a TEE file.
1568 	 *
1569 	 * It's not easy to handle the case above (e.g. Which meta file
1570 	 * should be linked first? What to do if a power cut happened
1571 	 * during creating links for the two meta files?)
1572 	 *
1573 	 * We will solve this issue using another approach: merging
1574 	 * both meta and block files into a single REE file. This approach
1575 	 * can completely remove ree_fs_rename(). We can simply
1576 	 * rename TEE file using REE rename() system call, which is also
1577 	 * atomic.
1578 	 */
1579 	if (meta_count > 1)
1580 		EMSG("Warning: more than one meta file in your TEE file\n"
1581 		     "This will cause memory leakage.");
1582 
1583 	res = create_hard_link(old, new, meta_filename);
1584 	if (res)
1585 		goto exit_close_old_dir;
1586 
1587 	/* we are safe now, remove old TEE file */
1588 	unlink_tee_file(old);
1589 
1590 exit_close_old_dir:
1591 	ree_fs_closedir_rpc(old_dir);
1592 exit:
1593 	free(meta_filename);
1594 	return res;
1595 }
1596 
1597 static int ree_fs_rename(const char *old, const char *new)
1598 {
1599 	int res;
1600 
1601 	mutex_lock(&ree_fs_mutex);
1602 	res = ree_fs_rename_internal(old, new);
1603 	mutex_unlock(&ree_fs_mutex);
1604 
1605 	return res;
1606 }
1607 
1608 /*
1609  * To ensure atomic unlink operation, we can simply
1610  * split the unlink operation into:
1611  *
1612  *  - rename("file", "file.trash");
1613  *
1614  * (Any failure in above steps is considered as update failed,
1615  *  and the file content will not be updated)
1616  *
1617  * After previous step the update is considered complete, but
1618  * we should do the following clean-up step(s):
1619  *
1620  *  - unlink("file.trash");
1621  *
1622  * (Any failure in above steps is considered as a successfully
1623  *  update)
1624  */
1625 static int ree_fs_unlink(const char *file)
1626 {
1627 	int res = -1;
1628 	char trash_file[TEE_FS_NAME_MAX + 6];
1629 
1630 	if (!file)
1631 		return -1;
1632 
1633 	snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash",
1634 		file);
1635 
1636 	mutex_lock(&ree_fs_mutex);
1637 
1638 	res = ree_fs_rename_internal(file, trash_file);
1639 	if (res < 0)
1640 		goto exit;
1641 
1642 	unlink_tee_file(trash_file);
1643 
1644 exit:
1645 	mutex_unlock(&ree_fs_mutex);
1646 	return res;
1647 }
1648 
1649 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length)
1650 {
1651 	struct tee_fs_fd *fdp;
1652 	int res;
1653 
1654 	mutex_lock(&ree_fs_mutex);
1655 	fdp = handle_lookup(&fs_handle_db, fd);
1656 	res = ree_fs_ftruncate_internal(errno, fdp, length);
1657 	mutex_unlock(&ree_fs_mutex);
1658 
1659 	return res;
1660 }
1661 
1662 const struct tee_file_operations ree_fs_ops = {
1663 	.open = ree_fs_open,
1664 	.close = ree_fs_close,
1665 	.read = ree_fs_read,
1666 	.write = ree_fs_write,
1667 	.lseek = ree_fs_lseek,
1668 	.ftruncate = ree_fs_ftruncate,
1669 	.rename = ree_fs_rename,
1670 	.unlink = ree_fs_unlink,
1671 	.mkdir = ree_fs_mkdir_rpc,
1672 	.opendir = ree_fs_opendir_rpc,
1673 	.closedir = ree_fs_closedir_rpc,
1674 	.readdir = ree_fs_readdir_rpc,
1675 	.rmdir = ree_fs_rmdir_rpc,
1676 	.access = ree_fs_access_rpc
1677 };
1678