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