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