xref: /optee_os/core/tee/tee_ree_fs.c (revision 15ace8d3324c33105e869f28fe4bde35ee1089d9)
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 	int 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 	size_t bytes_to_read = len;
831 
832 	DMSG("Read %zd bytes from block%d", len, b->block_num);
833 	if (offset + len > b->data_size) {
834 		bytes_to_read = b->data_size - offset;
835 		DMSG("Exceed block size, update len to %zd bytes",
836 			bytes_to_read);
837 	}
838 	memcpy(buf, b->data + offset, bytes_to_read);
839 }
840 
841 #ifdef CFG_FS_BLOCK_CACHE
842 static struct block *read_block_with_cache(struct tee_fs_fd *fdp, int block_num)
843 {
844 	struct block *b;
845 
846 	get_block_from_cache(&fdp->block_cache, block_num, &b);
847 	if (is_block_data_invalid(b))
848 		if (read_block_from_storage(fdp, b)) {
849 			EMSG("Unable to read block%d from storage",
850 					block_num);
851 			return NULL;
852 		}
853 
854 	return b;
855 }
856 #else
857 
858 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num)
859 {
860 	static struct block *b;
861 	int res;
862 
863 	if (!b)
864 		b = alloc_block();
865 	b->block_num = block_num;
866 
867 	res = read_block_from_storage(fdp, b);
868 	if (res)
869 		EMSG("Unable to read block%d from storage",
870 				block_num);
871 
872 	return res ? NULL : b;
873 }
874 #endif
875 
876 static struct block_operations block_ops = {
877 #ifdef CFG_FS_BLOCK_CACHE
878 	.read = read_block_with_cache,
879 #else
880 	.read = read_block_no_cache,
881 #endif
882 	.write = flush_block_to_storage,
883 };
884 
885 static int out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
886 		size_t len, struct tee_fs_file_meta *new_meta)
887 {
888 	int start_block_num = pos_to_block_num(fdp->pos);
889 	int end_block_num = pos_to_block_num(fdp->pos + len - 1);
890 	size_t remain_bytes = len;
891 	uint8_t *data_ptr = (uint8_t *)buf;
892 	int orig_pos = fdp->pos;
893 
894 	while (start_block_num <= end_block_num) {
895 		int offset = fdp->pos % BLOCK_FILE_SIZE;
896 		struct block *b;
897 		size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ?
898 			BLOCK_FILE_SIZE : remain_bytes;
899 
900 		if (size_to_write + offset > BLOCK_FILE_SIZE)
901 			size_to_write = BLOCK_FILE_SIZE - offset;
902 
903 		b = block_ops.read(fdp, start_block_num);
904 		if (!b)
905 			goto failed;
906 
907 		DMSG("Write data, offset: %d, size_to_write: %zd",
908 			offset, size_to_write);
909 		write_data_to_block(b, offset, data_ptr, size_to_write);
910 
911 		if (block_ops.write(fdp, b, new_meta)) {
912 			EMSG("Unable to wrtie block%d to storage",
913 					b->block_num);
914 			goto failed;
915 		}
916 
917 		data_ptr += size_to_write;
918 		remain_bytes -= size_to_write;
919 		start_block_num++;
920 		fdp->pos += size_to_write;
921 	}
922 
923 	if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
924 		new_meta->info.length = fdp->pos;
925 
926 	return 0;
927 failed:
928 	fdp->pos = orig_pos;
929 	return -1;
930 }
931 
932 static inline int create_hard_link(const char *old_dir,
933 			const char *new_dir,
934 			const char *filename)
935 {
936 	char old_path[REE_FS_NAME_MAX];
937 	char new_path[REE_FS_NAME_MAX];
938 
939 	snprintf(old_path, REE_FS_NAME_MAX, "%s/%s",
940 			old_dir, filename);
941 	snprintf(new_path, REE_FS_NAME_MAX, "%s/%s",
942 			new_dir, filename);
943 
944 	DMSG("%s -> %s", old_path, new_path);
945 	return tee_fs_rpc_link(OPTEE_MSG_RPC_CMD_FS, old_path, new_path);
946 }
947 
948 static int unlink_tee_file(const char *file)
949 {
950 	int res = -1;
951 	size_t len = strlen(file) + 1;
952 	struct tee_fs_dirent *dirent;
953 	struct tee_fs_dir *dir;
954 
955 	DMSG("file=%s", file);
956 
957 	if (len > TEE_FS_NAME_MAX)
958 		goto exit;
959 
960 	dir = ree_fs_opendir_rpc(file);
961 	if (!dir)
962 		goto exit;
963 
964 	dirent = ree_fs_readdir_rpc(dir);
965 	while (dirent) {
966 		char path[REE_FS_NAME_MAX];
967 
968 		snprintf(path, REE_FS_NAME_MAX, "%s/%s",
969 			file, dirent->d_name);
970 
971 		DMSG("unlink %s", path);
972 		res = tee_fs_rpc_unlink(OPTEE_MSG_RPC_CMD_FS, path);
973 		if (res) {
974 			ree_fs_closedir_rpc(dir);
975 			goto exit;
976 		}
977 
978 		dirent = ree_fs_readdir_rpc(dir);
979 	}
980 
981 	res = ree_fs_closedir_rpc(dir);
982 	if (res)
983 		goto exit;
984 
985 	res = ree_fs_rmdir_rpc(file);
986 exit:
987 	return res;
988 }
989 
990 static bool tee_file_exists(const char *file)
991 {
992 	char meta_path[REE_FS_NAME_MAX];
993 
994 	get_meta_filepath(file, 0, meta_path);
995 	if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK)) {
996 		get_meta_filepath(file, 1, meta_path);
997 		if (ree_fs_access_rpc(meta_path, TEE_FS_F_OK))
998 			return false;
999 	}
1000 
1001 	return true;
1002 }
1003 
1004 static struct tee_fs_file_meta *create_tee_file(const char *file)
1005 {
1006 	struct tee_fs_file_meta *meta = NULL;
1007 	int res;
1008 
1009 	DMSG("Creating TEE file=%s", file);
1010 
1011 	/* create TEE file directory if not exist */
1012 	if (ree_fs_access_rpc(file, TEE_FS_F_OK)) {
1013 		res = ree_fs_mkdir_rpc(file,
1014 				TEE_FS_S_IRUSR | TEE_FS_S_IWUSR | TEE_FS_S_IXUSR);
1015 		if (res) {
1016 			EMSG("Failed to create TEE file directory, res=%d",
1017 				res);
1018 			goto exit;
1019 		}
1020 	}
1021 
1022 	/* create meta file in TEE file directory */
1023 	meta = create_meta_file(file);
1024 	if (!meta)
1025 		EMSG("Failed to create new meta file");
1026 
1027 exit:
1028 	return meta;
1029 }
1030 
1031 static struct tee_fs_file_meta *open_tee_file(const char *file)
1032 {
1033 	struct tee_fs_file_meta *meta = NULL;
1034 	int backup_version = 0;
1035 
1036 	DMSG("Opening TEE file=%s", file);
1037 
1038 	meta = open_meta_file(file, backup_version);
1039 	if (!meta) {
1040 		meta = open_meta_file(file, !backup_version);
1041 		if (!meta) {
1042 			/*
1043 			 * cannot open meta file, assumed the TEE file
1044 			 * is corrupted
1045 			 */
1046 			EMSG("Can not open meta file");
1047 		}
1048 	}
1049 
1050 	return meta;
1051 }
1052 
1053 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
1054 				   tee_fs_off_t new_file_len);
1055 
1056 static int ree_fs_open(TEE_Result *errno, const char *file, int flags, ...)
1057 {
1058 	int res = -1;
1059 	size_t len;
1060 	struct tee_fs_file_meta *meta = NULL;
1061 	struct tee_fs_fd *fdp = NULL;
1062 	bool file_exist;
1063 
1064 	mutex_lock(&ree_fs_mutex);
1065 
1066 	assert(errno);
1067 	*errno = TEE_SUCCESS;
1068 
1069 	if (!file) {
1070 		*errno = TEE_ERROR_BAD_PARAMETERS;
1071 		goto exit;
1072 	}
1073 
1074 	len = strlen(file) + 1;
1075 	if (len > TEE_FS_NAME_MAX) {
1076 		*errno = TEE_ERROR_BAD_PARAMETERS;
1077 		goto exit;
1078 	}
1079 
1080 	file_exist = tee_file_exists(file);
1081 	if (flags & TEE_FS_O_CREATE) {
1082 		if ((flags & TEE_FS_O_EXCL) && file_exist) {
1083 			DMSG("tee file already exists");
1084 			*errno = TEE_ERROR_ACCESS_CONFLICT;
1085 			goto exit;
1086 		}
1087 
1088 		if (!file_exist)
1089 			meta = create_tee_file(file);
1090 		else
1091 			meta = open_tee_file(file);
1092 
1093 	} else {
1094 		if (!file_exist) {
1095 			DMSG("tee file not exists");
1096 			*errno = TEE_ERROR_ITEM_NOT_FOUND;
1097 			goto exit;
1098 		}
1099 
1100 		meta = open_tee_file(file);
1101 	}
1102 
1103 	if (!meta) {
1104 		EMSG("Failed to open TEE file");
1105 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1106 		goto exit;
1107 	}
1108 
1109 	DMSG("file=%s, length=%zd", file, meta->info.length);
1110 	fdp = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd));
1111 	if (!fdp) {
1112 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1113 		goto exit_free_meta;
1114 	}
1115 
1116 	/* init internal status */
1117 	fdp->flags = flags;
1118 	fdp->meta = meta;
1119 	fdp->pos = 0;
1120 	if (init_block_cache(&fdp->block_cache)) {
1121 		res = -1;
1122 		goto exit_free_fd;
1123 	}
1124 
1125 	fdp->filename = malloc(len);
1126 	if (!fdp->filename) {
1127 		res = -1;
1128 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1129 		goto exit_destroy_block_cache;
1130 	}
1131 	memcpy(fdp->filename, file, len);
1132 
1133 	if ((flags & TEE_FS_O_TRUNC) &&
1134 		(flags & TEE_FS_O_WRONLY || flags & TEE_FS_O_RDWR)) {
1135 		res = ree_fs_ftruncate_internal(errno, fdp, 0);
1136 		if (res < 0) {
1137 			EMSG("Unable to truncate file");
1138 			goto exit_free_filename;
1139 		}
1140 	}
1141 
1142 	/* return fd */
1143 	res = handle_get(&fs_handle_db, fdp);
1144 	if (res < 0)
1145 		goto exit_free_filename;
1146 	fdp->fd = res;
1147 	goto exit;
1148 
1149 exit_free_filename:
1150 	free(fdp->filename);
1151 exit_destroy_block_cache:
1152 	destroy_block_cache(&fdp->block_cache);
1153 exit_free_fd:
1154 	free(fdp);
1155 exit_free_meta:
1156 	free(meta);
1157 exit:
1158 	mutex_unlock(&ree_fs_mutex);
1159 	return res;
1160 }
1161 
1162 static int ree_fs_close(int fd)
1163 {
1164 	int res = -1;
1165 	struct tee_fs_fd *fdp;
1166 
1167 	mutex_lock(&ree_fs_mutex);
1168 
1169 	fdp = handle_lookup(&fs_handle_db, fd);
1170 	if (!fdp)
1171 		goto exit;
1172 
1173 	handle_put(&fs_handle_db, fdp->fd);
1174 
1175 	destroy_block_cache(&fdp->block_cache);
1176 	free(fdp->meta);
1177 	free(fdp->filename);
1178 	free(fdp);
1179 
1180 exit:
1181 	mutex_unlock(&ree_fs_mutex);
1182 	return res;
1183 }
1184 
1185 static tee_fs_off_t ree_fs_lseek(TEE_Result *errno, int fd,
1186 				 tee_fs_off_t offset, int whence)
1187 {
1188 	tee_fs_off_t res = -1;
1189 	tee_fs_off_t new_pos;
1190 	size_t filelen;
1191 	struct tee_fs_fd *fdp;
1192 
1193 	mutex_lock(&ree_fs_mutex);
1194 
1195 	assert(errno);
1196 	*errno = TEE_SUCCESS;
1197 
1198 	fdp = handle_lookup(&fs_handle_db, fd);
1199 	if (!fdp) {
1200 		*errno = TEE_ERROR_BAD_PARAMETERS;
1201 		goto exit;
1202 	}
1203 
1204 	DMSG("offset=%d, whence=%d", (int)offset, whence);
1205 
1206 	filelen = fdp->meta->info.length;
1207 
1208 	switch (whence) {
1209 	case TEE_FS_SEEK_SET:
1210 		new_pos = offset;
1211 		break;
1212 
1213 	case TEE_FS_SEEK_CUR:
1214 		new_pos = fdp->pos + offset;
1215 		break;
1216 
1217 	case TEE_FS_SEEK_END:
1218 		new_pos = filelen + offset;
1219 		break;
1220 
1221 	default:
1222 		*errno = TEE_ERROR_BAD_PARAMETERS;
1223 		goto exit;
1224 	}
1225 
1226 	if (new_pos < 0)
1227 		new_pos = 0;
1228 
1229 	if (new_pos > TEE_DATA_MAX_POSITION) {
1230 		EMSG("Position is beyond TEE_DATA_MAX_POSITION");
1231 		*errno = TEE_ERROR_BAD_PARAMETERS;
1232 		goto exit;
1233 	}
1234 
1235 	res = fdp->pos = new_pos;
1236 exit:
1237 	mutex_unlock(&ree_fs_mutex);
1238 	return res;
1239 }
1240 
1241 /*
1242  * To ensure atomic truncate operation, we can:
1243  *
1244  *  - update file length to new length
1245  *  - commit new meta
1246  *  - free unused blocks
1247  *
1248  * To ensure atomic extend operation, we can:
1249  *
1250  *  - update file length to new length
1251  *  - allocate and fill zero data to new blocks
1252  *  - commit new meta
1253  *
1254  * Any failure before committing new meta is considered as
1255  * update failed, and the file content will not be updated
1256  */
1257 static int ree_fs_ftruncate_internal(TEE_Result *errno, struct tee_fs_fd *fdp,
1258 				   tee_fs_off_t new_file_len)
1259 {
1260 	int res = -1;
1261 	size_t old_file_len = fdp->meta->info.length;
1262 	struct tee_fs_file_meta *new_meta = NULL;
1263 	uint8_t *buf = NULL;
1264 
1265 	assert(errno);
1266 	*errno = TEE_SUCCESS;
1267 
1268 	if (!fdp) {
1269 		*errno = TEE_ERROR_BAD_PARAMETERS;
1270 		res = -1;
1271 		goto exit;
1272 	}
1273 
1274 	if (fdp->flags & TEE_FS_O_RDONLY) {
1275 		*errno = TEE_ERROR_BAD_PARAMETERS;
1276 		EMSG("Read only");
1277 		res = -1;
1278 		goto exit;
1279 	}
1280 
1281 	if ((size_t)new_file_len == old_file_len) {
1282 		DMSG("Ignore due to file length does not changed");
1283 		res = 0;
1284 		goto exit;
1285 	}
1286 
1287 	if (new_file_len > MAX_FILE_SIZE) {
1288 		*errno = TEE_ERROR_BAD_PARAMETERS;
1289 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1290 		res = -1;
1291 		goto exit;
1292 	}
1293 
1294 	new_meta = duplicate_meta(fdp);
1295 	if (!new_meta) {
1296 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1297 		res = -1;
1298 		goto free;
1299 	}
1300 
1301 	new_meta->info.length = new_file_len;
1302 
1303 	if ((size_t)new_file_len < old_file_len) {
1304 		int old_block_num = get_last_block_num(old_file_len);
1305 		int new_block_num = get_last_block_num(new_file_len);
1306 
1307 		DMSG("Truncate file length to %zu", (size_t)new_file_len);
1308 
1309 		res = commit_meta_file(fdp, new_meta);
1310 		if (res < 0) {
1311 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1312 			EMSG("Failed to commit meta file");
1313 			goto free;
1314 		}
1315 
1316 		/* now we are safe to free unused blocks */
1317 		while (old_block_num > new_block_num) {
1318 			if (remove_block_file(fdp, old_block_num)) {
1319 				IMSG("Warning: Failed to free block: %d",
1320 						old_block_num);
1321 			}
1322 
1323 			old_block_num--;
1324 		}
1325 
1326 	} else {
1327 		size_t ext_len = new_file_len - old_file_len;
1328 		int orig_pos = fdp->pos;
1329 
1330 		buf = malloc(BLOCK_FILE_SIZE);
1331 		if (!buf) {
1332 			*errno = TEE_ERROR_OUT_OF_MEMORY;
1333 			EMSG("Failed to allocate buffer, size=%d",
1334 					BLOCK_FILE_SIZE);
1335 			res = -1;
1336 			goto free;
1337 		}
1338 
1339 		memset(buf, 0x0, BLOCK_FILE_SIZE);
1340 
1341 		DMSG("Extend file length to %zu", (size_t)new_file_len);
1342 
1343 		fdp->pos = old_file_len;
1344 
1345 		res = 0;
1346 		while (ext_len > 0) {
1347 			size_t data_len = (ext_len > BLOCK_FILE_SIZE) ?
1348 					BLOCK_FILE_SIZE : ext_len;
1349 
1350 			DMSG("fill len=%zu", data_len);
1351 			res = out_of_place_write(fdp, (void *)buf,
1352 					data_len, new_meta);
1353 			if (res < 0) {
1354 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1355 				EMSG("Failed to fill data");
1356 				break;
1357 			}
1358 
1359 			ext_len -= data_len;
1360 		}
1361 
1362 		fdp->pos = orig_pos;
1363 
1364 		if (res == 0) {
1365 			res = commit_meta_file(fdp, new_meta);
1366 			if (res < 0) {
1367 				*errno = TEE_ERROR_CORRUPT_OBJECT;
1368 				EMSG("Failed to commit meta file");
1369 			}
1370 		}
1371 	}
1372 
1373 free:
1374 	free(new_meta);
1375 	free(buf);
1376 
1377 exit:
1378 	return res;
1379 }
1380 
1381 static int ree_fs_read(TEE_Result *errno, int fd, void *buf, size_t len)
1382 {
1383 	int res = -1;
1384 	int start_block_num;
1385 	int end_block_num;
1386 	size_t remain_bytes = len;
1387 	uint8_t *data_ptr = buf;
1388 	struct tee_fs_fd *fdp;
1389 
1390 	mutex_lock(&ree_fs_mutex);
1391 
1392 	assert(errno);
1393 	*errno = TEE_SUCCESS;
1394 
1395 	fdp = handle_lookup(&fs_handle_db, fd);
1396 	if (!fdp) {
1397 		*errno = TEE_ERROR_BAD_PARAMETERS;
1398 		goto exit;
1399 	}
1400 
1401 	if (fdp->pos + len > fdp->meta->info.length) {
1402 		len = fdp->meta->info.length - fdp->pos;
1403 		DMSG("reached EOF, update read length to %zu", len);
1404 	}
1405 
1406 	if (!len) {
1407 		res = 0;
1408 		goto exit;
1409 	}
1410 
1411 	if (!buf) {
1412 		*errno = TEE_ERROR_BAD_PARAMETERS;
1413 		goto exit;
1414 	}
1415 
1416 	if (fdp->flags & TEE_FS_O_WRONLY) {
1417 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1418 		goto exit;
1419 	}
1420 
1421 	DMSG("%s, data len=%zu", fdp->filename, len);
1422 
1423 	start_block_num = pos_to_block_num(fdp->pos);
1424 	end_block_num = pos_to_block_num(fdp->pos + len - 1);
1425 	DMSG("start_block_num:%d, end_block_num:%d",
1426 		start_block_num, end_block_num);
1427 
1428 	while (start_block_num <= end_block_num) {
1429 		struct block *b;
1430 		int offset = fdp->pos % BLOCK_FILE_SIZE;
1431 		size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ?
1432 			BLOCK_FILE_SIZE : remain_bytes;
1433 
1434 		if (size_to_read + offset > BLOCK_FILE_SIZE)
1435 			size_to_read = BLOCK_FILE_SIZE - offset;
1436 
1437 		DMSG("block_num:%d, offset:%d, size_to_read: %zd",
1438 			start_block_num, offset, size_to_read);
1439 
1440 		b = block_ops.read(fdp, start_block_num);
1441 		if (!b) {
1442 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1443 			goto exit;
1444 		}
1445 
1446 		read_data_from_block(b, offset, data_ptr, size_to_read);
1447 		data_ptr += size_to_read;
1448 		remain_bytes -= size_to_read;
1449 		fdp->pos += size_to_read;
1450 
1451 		start_block_num++;
1452 	}
1453 	res = 0;
1454 exit:
1455 	mutex_unlock(&ree_fs_mutex);
1456 	return (res < 0) ? res : (int)len;
1457 }
1458 
1459 /*
1460  * To ensure atomicity of write operation, we need to
1461  * do the following steps:
1462  * (The sequence of operations is very important)
1463  *
1464  *  - Create a new backup version of meta file as a copy
1465  *    of current meta file.
1466  *  - For each blocks to write:
1467  *    - Create new backup version for current block.
1468  *    - Write data to new backup version.
1469  *    - Update the new meta file accordingly.
1470  *  - Write the new meta file.
1471  *
1472  * (Any failure in above steps is considered as update failed,
1473  *  and the file content will not be updated)
1474  *
1475  * After previous step the update is considered complete, but
1476  * we should do the following clean-up step(s):
1477  *
1478  *  - Delete old meta file.
1479  *  - Remove old block files.
1480  *
1481  * (Any failure in above steps is considered as a successfully
1482  *  update)
1483  */
1484 static int ree_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len)
1485 {
1486 	int res = -1;
1487 	struct tee_fs_file_meta *new_meta = NULL;
1488 	struct tee_fs_fd *fdp;
1489 	size_t file_size;
1490 	int orig_pos;
1491 
1492 	mutex_lock(&ree_fs_mutex);
1493 
1494 	assert(errno);
1495 	*errno = TEE_SUCCESS;
1496 
1497 	fdp = handle_lookup(&fs_handle_db, fd);
1498 	if (!fdp) {
1499 		*errno = TEE_ERROR_BAD_PARAMETERS;
1500 		goto exit;
1501 	}
1502 	if (!len) {
1503 		res = 0;
1504 		goto exit;
1505 	}
1506 	if (!buf) {
1507 		*errno = TEE_ERROR_BAD_PARAMETERS;
1508 		goto exit;
1509 	}
1510 
1511 	file_size = fdp->meta->info.length;
1512 	orig_pos = fdp->pos;
1513 
1514 	if (fdp->flags & TEE_FS_O_RDONLY) {
1515 		EMSG("Write to a read-only file, denied");
1516 		*errno = TEE_ERROR_ACCESS_CONFLICT;
1517 		goto exit;
1518 	}
1519 
1520 	if ((fdp->pos + len) > MAX_FILE_SIZE) {
1521 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
1522 		*errno = TEE_ERROR_BAD_PARAMETERS;
1523 		goto exit;
1524 	}
1525 
1526 	DMSG("%s, data len=%zu", fdp->filename, len);
1527 	if (file_size < (size_t)fdp->pos) {
1528 		DMSG("File hole detected, try to extend file size");
1529 		res = ree_fs_ftruncate_internal(errno, fdp, fdp->pos);
1530 		if (res < 0)
1531 			goto exit;
1532 	}
1533 
1534 	new_meta = duplicate_meta(fdp);
1535 	if (!new_meta) {
1536 		*errno = TEE_ERROR_OUT_OF_MEMORY;
1537 		goto exit;
1538 	}
1539 
1540 	res = out_of_place_write(fdp, buf, len, new_meta);
1541 	if (res < 0) {
1542 		*errno = TEE_ERROR_CORRUPT_OBJECT;
1543 	} else {
1544 		int r;
1545 		int start_block_num;
1546 		int end_block_num;
1547 
1548 		r = commit_meta_file(fdp, new_meta);
1549 		if (r < 0) {
1550 			*errno = TEE_ERROR_CORRUPT_OBJECT;
1551 			res = -1;
1552 		}
1553 
1554 		/* we are safe to free old blocks */
1555 		start_block_num = pos_to_block_num(orig_pos);
1556 		end_block_num = pos_to_block_num(fdp->pos - 1);
1557 		while (start_block_num <= end_block_num) {
1558 			if (remove_outdated_block(fdp, start_block_num))
1559 				IMSG("Warning: Failed to free old block: %d",
1560 					start_block_num);
1561 
1562 			start_block_num++;
1563 		}
1564 	}
1565 exit:
1566 	mutex_unlock(&ree_fs_mutex);
1567 	free(new_meta);
1568 	return (res < 0) ? res : (int)len;
1569 }
1570 
1571 /*
1572  * To ensure atomicity of rename operation, we need to
1573  * do the following steps:
1574  *
1575  *  - Create a new folder that represents the renamed TEE file
1576  *  - For each REE block files, create a hard link under the just
1577  *    created folder (new TEE file)
1578  *  - Now we are ready to commit meta, create hard link for the
1579  *    meta file
1580  *
1581  * (Any failure in above steps is considered as update failed,
1582  *  and the file content will not be updated)
1583  *
1584  * After previous step the update is considered complete, but
1585  * we should do the following clean-up step(s):
1586  *
1587  *  - Unlink all REE files represents the old TEE file (including
1588  *    meta and block files)
1589  *
1590  * (Any failure in above steps is considered as a successfully
1591  *  update)
1592  */
1593 static int ree_fs_rename_internal(const char *old, const char *new)
1594 {
1595 	int res = -1;
1596 	size_t old_len;
1597 	size_t new_len;
1598 	size_t meta_count = 0;
1599 	struct tee_fs_dir *old_dir;
1600 	struct tee_fs_dirent *dirent;
1601 	char *meta_filename = NULL;
1602 
1603 	if (!old || !new)
1604 		return -1;
1605 
1606 	DMSG("old=%s, new=%s", old, new);
1607 
1608 	old_len = strlen(old) + 1;
1609 	new_len = strlen(new) + 1;
1610 
1611 	if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX)
1612 		goto exit;
1613 
1614 	res = ree_fs_mkdir_rpc(new,
1615 			TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
1616 	if (res)
1617 		goto exit;
1618 
1619 	old_dir = ree_fs_opendir_rpc(old);
1620 	if (!old_dir)
1621 		goto exit;
1622 
1623 	dirent = ree_fs_readdir_rpc(old_dir);
1624 	while (dirent) {
1625 		if (!strncmp(dirent->d_name, "meta.", 5)) {
1626 			meta_filename = strdup(dirent->d_name);
1627 			meta_count++;
1628 		} else {
1629 			res = create_hard_link(old, new, dirent->d_name);
1630 			if (res)
1631 				goto exit_close_old_dir;
1632 		}
1633 
1634 		dirent = ree_fs_readdir_rpc(old_dir);
1635 	}
1636 
1637 	/* finally, link the meta file, rename operation completed */
1638 	if (!meta_filename)
1639 		panic("no meta file");
1640 
1641 	/*
1642 	 * TODO: This will cause memory leakage at previous strdup()
1643 	 * if we accidently have two meta files in a TEE file.
1644 	 *
1645 	 * It's not easy to handle the case above (e.g. Which meta file
1646 	 * should be linked first? What to do if a power cut happened
1647 	 * during creating links for the two meta files?)
1648 	 *
1649 	 * We will solve this issue using another approach: merging
1650 	 * both meta and block files into a single REE file. This approach
1651 	 * can completely remove ree_fs_rename(). We can simply
1652 	 * rename TEE file using REE rename() system call, which is also
1653 	 * atomic.
1654 	 */
1655 	if (meta_count > 1)
1656 		EMSG("Warning: more than one meta file in your TEE file\n"
1657 		     "This will cause memory leakage.");
1658 
1659 	res = create_hard_link(old, new, meta_filename);
1660 	if (res)
1661 		goto exit_close_old_dir;
1662 
1663 	/* we are safe now, remove old TEE file */
1664 	unlink_tee_file(old);
1665 
1666 exit_close_old_dir:
1667 	ree_fs_closedir_rpc(old_dir);
1668 exit:
1669 	free(meta_filename);
1670 	return res;
1671 }
1672 
1673 static int ree_fs_rename(const char *old, const char *new)
1674 {
1675 	int res;
1676 
1677 	mutex_lock(&ree_fs_mutex);
1678 	res = ree_fs_rename_internal(old, new);
1679 	mutex_unlock(&ree_fs_mutex);
1680 
1681 	return res;
1682 }
1683 
1684 /*
1685  * To ensure atomic unlink operation, we can simply
1686  * split the unlink operation into:
1687  *
1688  *  - rename("file", "file.trash");
1689  *
1690  * (Any failure in above steps is considered as update failed,
1691  *  and the file content will not be updated)
1692  *
1693  * After previous step the update is considered complete, but
1694  * we should do the following clean-up step(s):
1695  *
1696  *  - unlink("file.trash");
1697  *
1698  * (Any failure in above steps is considered as a successfully
1699  *  update)
1700  */
1701 static int ree_fs_unlink(const char *file)
1702 {
1703 	int res = -1;
1704 	char trash_file[TEE_FS_NAME_MAX + 6];
1705 
1706 	if (!file)
1707 		return -1;
1708 
1709 	snprintf(trash_file, TEE_FS_NAME_MAX + 6, "%s.trash",
1710 		file);
1711 
1712 	mutex_lock(&ree_fs_mutex);
1713 
1714 	res = ree_fs_rename_internal(file, trash_file);
1715 	if (res < 0)
1716 		goto exit;
1717 
1718 	unlink_tee_file(trash_file);
1719 
1720 exit:
1721 	mutex_unlock(&ree_fs_mutex);
1722 	return res;
1723 }
1724 
1725 static int ree_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t length)
1726 {
1727 	struct tee_fs_fd *fdp;
1728 	int res;
1729 
1730 	mutex_lock(&ree_fs_mutex);
1731 	fdp = handle_lookup(&fs_handle_db, fd);
1732 	res = ree_fs_ftruncate_internal(errno, fdp, length);
1733 	mutex_unlock(&ree_fs_mutex);
1734 
1735 	return res;
1736 }
1737 
1738 const struct tee_file_operations ree_fs_ops = {
1739 	.open = ree_fs_open,
1740 	.close = ree_fs_close,
1741 	.read = ree_fs_read,
1742 	.write = ree_fs_write,
1743 	.lseek = ree_fs_lseek,
1744 	.ftruncate = ree_fs_ftruncate,
1745 	.rename = ree_fs_rename,
1746 	.unlink = ree_fs_unlink,
1747 	.mkdir = ree_fs_mkdir_rpc,
1748 	.opendir = ree_fs_opendir_rpc,
1749 	.closedir = ree_fs_closedir_rpc,
1750 	.readdir = ree_fs_readdir_rpc,
1751 	.rmdir = ree_fs_rmdir_rpc,
1752 	.access = ree_fs_access_rpc
1753 };
1754