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