xref: /optee_os/core/tee/tee_ree_fs.c (revision 5347d6f90e78fcd67f5f81cf1760411910efff45)
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 /*
49  * This file implements the tee_file_operations structure for a secure
50  * filesystem based on single file in normal world.
51  *
52  * All fields in the REE file are duplicated with two versions 0 and 1. The
53  * active meta-data block is selected by the lowest bit in the
54  * meta-counter.  The active file block is selected by corresponding bit
55  * number in struct tee_fs_file_info.backup_version_table.
56  *
57  * The atomicity of each operation is ensured by updating meta-counter when
58  * everything in the secondary blocks (both meta-data and file-data blocks)
59  * are successfully written.  The main purpose of the code below is to
60  * perform block encryption and authentication of the file data, and
61  * properly handle seeking through the file. One file (in the sense of
62  * struct tee_file_operations) maps to one file in the REE filesystem, and
63  * has the following structure:
64  *
65  * [ 4 bytes meta-counter]
66  * [ meta-data version 0][ meta-data version 1 ]
67  * [ Block 0 version 0 ][ Block 0 version 1 ]
68  * [ Block 1 version 0 ][ Block 1 version 1 ]
69  * ...
70  * [ Block n version 0 ][ Block n version 1 ]
71  *
72  * One meta-data block is built up as:
73  * [ struct meta_header | struct tee_fs_get_header_size ]
74  *
75  * One data block is built up as:
76  * [ struct block_header | BLOCK_FILE_SIZE bytes ]
77  *
78  * struct meta_header and struct block_header are defined in
79  * tee_fs_key_manager.h.
80  *
81  */
82 
83 
84 #define MAX_FILE_SIZE	(BLOCK_FILE_SIZE * NUM_BLOCKS_PER_FILE)
85 
86 struct block {
87 	int block_num;
88 	uint8_t *data;
89 };
90 
91 struct tee_fs_fd {
92 	uint32_t meta_counter;
93 	struct tee_fs_file_meta meta;
94 	tee_fs_off_t pos;
95 	uint32_t flags;
96 	bool is_new_file;
97 	int fd;
98 };
99 
100 static inline int pos_to_block_num(int position)
101 {
102 	return position >> BLOCK_FILE_SHIFT;
103 }
104 
105 static inline int get_last_block_num(size_t size)
106 {
107 	return pos_to_block_num(size - 1);
108 }
109 
110 static bool get_backup_version_of_block(struct tee_fs_file_meta *meta,
111 					size_t block_num)
112 {
113 	uint32_t index = (block_num / 32);
114 	uint32_t block_mask = 1 << (block_num % 32);
115 
116 	return !!(meta->info.backup_version_table[index] & block_mask);
117 }
118 
119 static inline void toggle_backup_version_of_block(
120 		struct tee_fs_file_meta *meta,
121 		size_t block_num)
122 {
123 	uint32_t index = (block_num / 32);
124 	uint32_t block_mask = 1 << (block_num % 32);
125 
126 	meta->info.backup_version_table[index] ^= block_mask;
127 }
128 
129 struct block_operations {
130 
131 	/*
132 	 * Read a block from REE File System which is corresponding
133 	 * to the given block_num.
134 	 */
135 	struct block *(*read)(struct tee_fs_fd *fdp, int block_num);
136 
137 	/*
138 	 * Write the given block to REE File System
139 	 */
140 	int (*write)(struct tee_fs_fd *fdp, struct block *b,
141 			struct tee_fs_file_meta *new_meta);
142 };
143 
144 static struct mutex ree_fs_mutex = MUTEX_INITIALIZER;
145 
146 static TEE_Result ree_fs_opendir_rpc(const char *name, struct tee_fs_dir **d)
147 
148 {
149 	return tee_fs_rpc_new_opendir(OPTEE_MSG_RPC_CMD_FS, name, d);
150 }
151 
152 static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
153 {
154 	if (d)
155 		tee_fs_rpc_new_closedir(OPTEE_MSG_RPC_CMD_FS, d);
156 }
157 
158 static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d,
159 				     struct tee_fs_dirent **ent)
160 {
161 	return tee_fs_rpc_new_readdir(OPTEE_MSG_RPC_CMD_FS, d, ent);
162 }
163 
164 static size_t meta_size(void)
165 {
166 	return tee_fs_get_header_size(META_FILE) +
167 	       sizeof(struct tee_fs_file_meta);
168 }
169 
170 static size_t meta_pos_raw(struct tee_fs_fd *fdp, bool active)
171 {
172 	size_t offs = sizeof(uint32_t);
173 
174 	if ((fdp->meta_counter & 1) == active)
175 		offs += meta_size();
176 	return offs;
177 }
178 
179 static size_t block_size_raw(void)
180 {
181 	return tee_fs_get_header_size(BLOCK_FILE) + BLOCK_FILE_SIZE;
182 }
183 
184 static size_t block_pos_raw(struct tee_fs_file_meta *meta, size_t block_num,
185 			    bool active)
186 {
187 	size_t n = block_num * 2;
188 
189 	if (active == get_backup_version_of_block(meta, block_num))
190 		n++;
191 
192 	return sizeof(uint32_t) + meta_size() * 2 + n * block_size_raw();
193 }
194 
195 /*
196  * encrypted_fek: as input for META_FILE and BLOCK_FILE
197  */
198 static TEE_Result encrypt_and_write_file(struct tee_fs_fd *fdp,
199 		enum tee_fs_file_type file_type, size_t offs,
200 		void *data_in, size_t data_in_size,
201 		uint8_t *encrypted_fek)
202 {
203 	TEE_Result res;
204 	struct tee_fs_rpc_operation op;
205 	void *ciphertext;
206 	size_t header_size = tee_fs_get_header_size(file_type);
207 	size_t ciphertext_size = header_size + data_in_size;
208 
209 
210 	res = tee_fs_rpc_new_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
211 					offs, ciphertext_size, &ciphertext);
212 	if (res != TEE_SUCCESS)
213 		return res;
214 
215 	res = tee_fs_encrypt_file(file_type, data_in, data_in_size,
216 				  ciphertext, &ciphertext_size, encrypted_fek);
217 	if (res != TEE_SUCCESS)
218 		return res;
219 
220 	return tee_fs_rpc_new_write_final(&op);
221 }
222 
223 /*
224  * encrypted_fek: as output for META_FILE
225  *                as input for BLOCK_FILE
226  */
227 static TEE_Result read_and_decrypt_file(struct tee_fs_fd *fdp,
228 		enum tee_fs_file_type file_type, size_t offs,
229 		void *data_out, size_t *data_out_size,
230 		uint8_t *encrypted_fek)
231 {
232 	TEE_Result res;
233 	struct tee_fs_rpc_operation op;
234 	size_t bytes;
235 	void *ciphertext;
236 
237 	bytes = *data_out_size + tee_fs_get_header_size(file_type);
238 	res = tee_fs_rpc_new_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, offs,
239 				       bytes, &ciphertext);
240 	if (res != TEE_SUCCESS)
241 		return res;
242 
243 	res = tee_fs_rpc_new_read_final(&op, &bytes);
244 	if (res != TEE_SUCCESS)
245 		return res;
246 
247 	if (!bytes) {
248 		*data_out_size = 0;
249 		return TEE_SUCCESS;
250 	}
251 
252 	res = tee_fs_decrypt_file(file_type, ciphertext, bytes, data_out,
253 				  data_out_size, encrypted_fek);
254 	if (res != TEE_SUCCESS)
255 		return TEE_ERROR_CORRUPT_OBJECT;
256 	return TEE_SUCCESS;
257 }
258 
259 static TEE_Result write_meta_file(struct tee_fs_fd *fdp,
260 		struct tee_fs_file_meta *meta)
261 {
262 	size_t offs = meta_pos_raw(fdp, false);
263 
264 	return encrypt_and_write_file(fdp, META_FILE, offs,
265 			(void *)&meta->info, sizeof(meta->info),
266 			meta->encrypted_fek);
267 }
268 
269 static TEE_Result write_meta_counter(struct tee_fs_fd *fdp)
270 {
271 	TEE_Result res;
272 	struct tee_fs_rpc_operation op;
273 	size_t bytes = sizeof(uint32_t);
274 	void *data;
275 
276 	res = tee_fs_rpc_new_write_init(&op, OPTEE_MSG_RPC_CMD_FS,
277 					fdp->fd, 0, bytes, &data);
278 	if (res != TEE_SUCCESS)
279 		return res;
280 
281 	memcpy(data, &fdp->meta_counter, bytes);
282 
283 	return tee_fs_rpc_new_write_final(&op);
284 }
285 
286 static TEE_Result create_meta(struct tee_fs_fd *fdp, const char *fname)
287 {
288 	TEE_Result res;
289 
290 	memset(fdp->meta.info.backup_version_table, 0xff,
291 		sizeof(fdp->meta.info.backup_version_table));
292 	fdp->meta.info.length = 0;
293 
294 	res = tee_fs_generate_fek(fdp->meta.encrypted_fek, TEE_FS_KM_FEK_SIZE);
295 	if (res != TEE_SUCCESS)
296 		return res;
297 
298 	res = tee_fs_rpc_new_create(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
299 	if (res != TEE_SUCCESS)
300 		return res;
301 
302 	fdp->meta.counter = fdp->meta_counter;
303 
304 	res = write_meta_file(fdp, &fdp->meta);
305 	if (res != TEE_SUCCESS)
306 		return res;
307 	return write_meta_counter(fdp);
308 }
309 
310 static TEE_Result commit_meta_file(struct tee_fs_fd *fdp,
311 				   struct tee_fs_file_meta *new_meta)
312 {
313 	TEE_Result res;
314 
315 	new_meta->counter = fdp->meta_counter + 1;
316 
317 	res = write_meta_file(fdp, new_meta);
318 	if (res != TEE_SUCCESS)
319 		return res;
320 
321 	/*
322 	 * From now on the new meta is successfully committed,
323 	 * change tee_fs_fd accordingly
324 	 */
325 	fdp->meta = *new_meta;
326 	fdp->meta_counter = fdp->meta.counter;
327 
328 	return write_meta_counter(fdp);
329 }
330 
331 static TEE_Result read_meta_file(struct tee_fs_fd *fdp,
332 		struct tee_fs_file_meta *meta)
333 {
334 	size_t meta_info_size = sizeof(struct tee_fs_file_info);
335 	size_t offs = meta_pos_raw(fdp, true);
336 
337 	return read_and_decrypt_file(fdp, META_FILE, offs,
338 				     &meta->info, &meta_info_size,
339 				     meta->encrypted_fek);
340 }
341 
342 static TEE_Result read_meta_counter(struct tee_fs_fd *fdp)
343 {
344 	TEE_Result res;
345 	struct tee_fs_rpc_operation op;
346 	void *data;
347 	size_t bytes = sizeof(uint32_t);
348 
349 	res = tee_fs_rpc_new_read_init(&op, OPTEE_MSG_RPC_CMD_FS,
350 				       fdp->fd, 0, bytes, &data);
351 	if (res != TEE_SUCCESS)
352 		return res;
353 
354 	res = tee_fs_rpc_new_read_final(&op, &bytes);
355 	if (res != TEE_SUCCESS)
356 		return res;
357 
358 	if (bytes != sizeof(uint32_t))
359 		return TEE_ERROR_CORRUPT_OBJECT;
360 
361 	memcpy(&fdp->meta_counter, data, bytes);
362 
363 	return TEE_SUCCESS;
364 }
365 
366 static TEE_Result read_meta(struct tee_fs_fd *fdp, const char *fname)
367 {
368 	TEE_Result res;
369 
370 	res = tee_fs_rpc_new_open(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
371 	if (res != TEE_SUCCESS)
372 		return res;
373 
374 	res = read_meta_counter(fdp);
375 	if (res != TEE_SUCCESS)
376 		return res;
377 
378 	return read_meta_file(fdp, &fdp->meta);
379 }
380 
381 static bool is_block_file_exist(struct tee_fs_file_meta *meta,
382 					size_t block_num)
383 {
384 	size_t file_size = meta->info.length;
385 
386 	if (file_size == 0)
387 		return false;
388 
389 	return (block_num <= (size_t)get_last_block_num(file_size));
390 }
391 
392 static TEE_Result read_block_from_storage(struct tee_fs_fd *fdp,
393 					  struct block *b)
394 {
395 	TEE_Result res = TEE_SUCCESS;
396 	uint8_t *plaintext = b->data;
397 	size_t block_file_size = BLOCK_FILE_SIZE;
398 	size_t offs = block_pos_raw(&fdp->meta, b->block_num, true);
399 
400 	if (!is_block_file_exist(&fdp->meta, b->block_num))
401 		goto exit;
402 
403 	res = read_and_decrypt_file(fdp, BLOCK_FILE, offs, plaintext,
404 				    &block_file_size, fdp->meta.encrypted_fek);
405 	if (res != TEE_SUCCESS) {
406 		EMSG("Failed to read and decrypt file");
407 		goto exit;
408 	}
409 	if (block_file_size != BLOCK_FILE_SIZE)
410 		return TEE_ERROR_GENERIC;
411 	DMSG("Successfully read and decrypt block%d from storage",
412 	     b->block_num);
413 exit:
414 	return res;
415 }
416 
417 static int flush_block_to_storage(struct tee_fs_fd *fdp, struct block *b,
418 					 struct tee_fs_file_meta *new_meta)
419 {
420 	TEE_Result res;
421 	size_t block_num = b->block_num;
422 	size_t offs = block_pos_raw(&fdp->meta, b->block_num, false);
423 
424 	res = encrypt_and_write_file(fdp, BLOCK_FILE, offs, b->data,
425 				     BLOCK_FILE_SIZE, new_meta->encrypted_fek);
426 	if (res != TEE_SUCCESS) {
427 		EMSG("Failed to encrypt and write block file");
428 		goto fail;
429 	}
430 
431 	DMSG("Successfully encrypt and write block%d to storage",
432 	     b->block_num);
433 	toggle_backup_version_of_block(new_meta, block_num);
434 
435 	return 0;
436 fail:
437 	return -1;
438 }
439 
440 static struct block *alloc_block(void)
441 {
442 	struct block *c;
443 
444 	c = malloc(sizeof(struct block));
445 	if (!c)
446 		return NULL;
447 
448 	c->data = malloc(BLOCK_FILE_SIZE);
449 	if (!c->data) {
450 		EMSG("unable to alloc memory for block data");
451 		goto exit;
452 	}
453 
454 	c->block_num = -1;
455 
456 	return c;
457 
458 exit:
459 	free(c);
460 	return NULL;
461 }
462 
463 static void write_data_to_block(struct block *b, int offset,
464 				void *buf, size_t len)
465 {
466 	DMSG("Write %zd bytes to block%d", len, b->block_num);
467 	memcpy(b->data + offset, buf, len);
468 }
469 
470 static void read_data_from_block(struct block *b, int offset,
471 				void *buf, size_t len)
472 {
473 	DMSG("Read %zd bytes from block%d", len, b->block_num);
474 	memcpy(buf, b->data + offset, len);
475 }
476 
477 static struct block *read_block_no_cache(struct tee_fs_fd *fdp, int block_num)
478 {
479 	static struct block *b;
480 	TEE_Result res;
481 
482 	if (!b)
483 		b = alloc_block();
484 	b->block_num = block_num;
485 
486 	res = read_block_from_storage(fdp, b);
487 	if (res != TEE_SUCCESS)
488 		EMSG("Unable to read block%d from storage",
489 				block_num);
490 
491 	return res != TEE_SUCCESS ? NULL : b;
492 }
493 
494 static struct block_operations block_ops = {
495 	.read = read_block_no_cache,
496 	.write = flush_block_to_storage,
497 };
498 
499 static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
500 		size_t len, struct tee_fs_file_meta *new_meta)
501 {
502 	int start_block_num = pos_to_block_num(fdp->pos);
503 	int end_block_num = pos_to_block_num(fdp->pos + len - 1);
504 	size_t remain_bytes = len;
505 	uint8_t *data_ptr = (uint8_t *)buf;
506 	int orig_pos = fdp->pos;
507 
508 	while (start_block_num <= end_block_num) {
509 		int offset = fdp->pos % BLOCK_FILE_SIZE;
510 		struct block *b;
511 		size_t size_to_write = (remain_bytes > BLOCK_FILE_SIZE) ?
512 			BLOCK_FILE_SIZE : remain_bytes;
513 
514 		if (size_to_write + offset > BLOCK_FILE_SIZE)
515 			size_to_write = BLOCK_FILE_SIZE - offset;
516 
517 		b = block_ops.read(fdp, start_block_num);
518 		if (!b)
519 			goto failed;
520 
521 		DMSG("Write data, offset: %d, size_to_write: %zd",
522 			offset, size_to_write);
523 		write_data_to_block(b, offset, data_ptr, size_to_write);
524 
525 		if (block_ops.write(fdp, b, new_meta)) {
526 			EMSG("Unable to wrtie block%d to storage",
527 					b->block_num);
528 			goto failed;
529 		}
530 
531 		data_ptr += size_to_write;
532 		remain_bytes -= size_to_write;
533 		start_block_num++;
534 		fdp->pos += size_to_write;
535 	}
536 
537 	if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
538 		new_meta->info.length = fdp->pos;
539 
540 	return TEE_SUCCESS;
541 failed:
542 	fdp->pos = orig_pos;
543 	return TEE_ERROR_GENERIC;
544 }
545 
546 static TEE_Result open_internal(const char *file, bool create, bool overwrite,
547 				struct tee_file_handle **fh)
548 {
549 	TEE_Result res;
550 	size_t len;
551 	struct tee_fs_fd *fdp = NULL;
552 
553 	if (!file)
554 		return TEE_ERROR_BAD_PARAMETERS;
555 
556 	len = strlen(file) + 1;
557 	if (len > TEE_FS_NAME_MAX)
558 		return TEE_ERROR_BAD_PARAMETERS;
559 
560 	fdp = calloc(1, sizeof(struct tee_fs_fd));
561 	if (!fdp)
562 		return TEE_ERROR_OUT_OF_MEMORY;
563 	fdp->fd = -1;
564 
565 	mutex_lock(&ree_fs_mutex);
566 
567 	res = read_meta(fdp, file);
568 	if (res == TEE_SUCCESS) {
569 		if (overwrite) {
570 			res = TEE_ERROR_ACCESS_CONFLICT;
571 			goto exit_close_file;
572 		}
573 	} else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
574 		if (!create)
575 			goto exit_free_fd;
576 		res = create_meta(fdp, file);
577 		if (res != TEE_SUCCESS)
578 			goto exit_close_file;
579 	} else {
580 		goto exit_free_fd;
581 	}
582 
583 	*fh = (struct tee_file_handle *)fdp;
584 	goto exit;
585 
586 exit_close_file:
587 	if (fdp->fd != -1)
588 		tee_fs_rpc_new_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
589 	if (create)
590 		tee_fs_rpc_new_remove(OPTEE_MSG_RPC_CMD_FS, file);
591 exit_free_fd:
592 	free(fdp);
593 exit:
594 	mutex_unlock(&ree_fs_mutex);
595 	return res;
596 }
597 
598 static TEE_Result ree_fs_open(const char *file, struct tee_file_handle **fh)
599 {
600 	return open_internal(file, false, false, fh);
601 }
602 
603 static TEE_Result ree_fs_create(const char *file, bool overwrite,
604 				struct tee_file_handle **fh)
605 {
606 	return open_internal(file, true, overwrite, fh);
607 }
608 
609 static void ree_fs_close(struct tee_file_handle **fh)
610 {
611 	struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh;
612 
613 	if (fdp) {
614 		tee_fs_rpc_new_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
615 		free(fdp);
616 		*fh = NULL;
617 	}
618 }
619 
620 static TEE_Result ree_fs_seek(struct tee_file_handle *fh, int32_t offset,
621 			      TEE_Whence whence, int32_t *new_offs)
622 {
623 	TEE_Result res;
624 	tee_fs_off_t new_pos;
625 	size_t filelen;
626 	struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
627 
628 	mutex_lock(&ree_fs_mutex);
629 
630 	DMSG("offset=%d, whence=%d", (int)offset, whence);
631 
632 	filelen = fdp->meta.info.length;
633 
634 	switch (whence) {
635 	case TEE_DATA_SEEK_SET:
636 		new_pos = offset;
637 		break;
638 
639 	case TEE_DATA_SEEK_CUR:
640 		new_pos = fdp->pos + offset;
641 		break;
642 
643 	case TEE_DATA_SEEK_END:
644 		new_pos = filelen + offset;
645 		break;
646 
647 	default:
648 		res = TEE_ERROR_BAD_PARAMETERS;
649 		goto exit;
650 	}
651 
652 	if (new_pos < 0)
653 		new_pos = 0;
654 
655 	if (new_pos > TEE_DATA_MAX_POSITION) {
656 		EMSG("Position is beyond TEE_DATA_MAX_POSITION");
657 		res = TEE_ERROR_BAD_PARAMETERS;
658 		goto exit;
659 	}
660 
661 	fdp->pos = new_pos;
662 	if (new_offs)
663 		*new_offs = new_pos;
664 	res = TEE_SUCCESS;
665 exit:
666 	mutex_unlock(&ree_fs_mutex);
667 	return res;
668 }
669 
670 /*
671  * To ensure atomic truncate operation, we can:
672  *
673  *  - update file length to new length
674  *  - commit new meta
675  *
676  * To ensure atomic extend operation, we can:
677  *
678  *  - update file length to new length
679  *  - allocate and fill zero data to new blocks
680  *  - commit new meta
681  *
682  * Any failure before committing new meta is considered as
683  * update failed, and the file content will not be updated
684  */
685 static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp,
686 					    tee_fs_off_t new_file_len)
687 {
688 	TEE_Result res;
689 	size_t old_file_len = fdp->meta.info.length;
690 	struct tee_fs_file_meta new_meta;
691 
692 	if ((size_t)new_file_len == old_file_len) {
693 		DMSG("Ignore due to file length does not changed");
694 		return TEE_SUCCESS;
695 	}
696 
697 	if (new_file_len > MAX_FILE_SIZE) {
698 		EMSG("Over maximum file size(%d)", MAX_FILE_SIZE);
699 		return TEE_ERROR_BAD_PARAMETERS;
700 	}
701 
702 	new_meta = fdp->meta;
703 	new_meta.info.length = new_file_len;
704 
705 	if ((size_t)new_file_len < old_file_len) {
706 		DMSG("Truncate file length to %zu", (size_t)new_file_len);
707 
708 		res = commit_meta_file(fdp, &new_meta);
709 		if (res != TEE_SUCCESS)
710 			return res;
711 	} else {
712 		size_t ext_len = new_file_len - old_file_len;
713 		int orig_pos = fdp->pos;
714 		uint8_t *buf;
715 
716 		buf = calloc(1, BLOCK_FILE_SIZE);
717 		if (!buf) {
718 			EMSG("Failed to allocate buffer, size=%d",
719 					BLOCK_FILE_SIZE);
720 			return TEE_ERROR_OUT_OF_MEMORY;
721 		}
722 
723 		DMSG("Extend file length to %zu", (size_t)new_file_len);
724 
725 		fdp->pos = old_file_len;
726 
727 		res = TEE_SUCCESS;
728 		while (ext_len > 0) {
729 			size_t data_len = (ext_len > BLOCK_FILE_SIZE) ?
730 					BLOCK_FILE_SIZE : ext_len;
731 
732 			DMSG("fill len=%zu", data_len);
733 			res = out_of_place_write(fdp, buf, data_len, &new_meta);
734 			if (res != TEE_SUCCESS) {
735 				EMSG("Failed to fill data");
736 				break;
737 			}
738 
739 			ext_len -= data_len;
740 		}
741 
742 		free(buf);
743 		fdp->pos = orig_pos;
744 
745 		if (res == TEE_SUCCESS) {
746 			res = commit_meta_file(fdp, &new_meta);
747 			if (res != TEE_SUCCESS)
748 				EMSG("Failed to commit meta file");
749 		}
750 	}
751 
752 	return res;
753 }
754 
755 static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
756 			      size_t *len)
757 {
758 	TEE_Result res;
759 	int start_block_num;
760 	int end_block_num;
761 	size_t remain_bytes;
762 	uint8_t *data_ptr = buf;
763 	struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
764 
765 	mutex_lock(&ree_fs_mutex);
766 
767 	remain_bytes = *len;
768 	if ((fdp->pos + remain_bytes) < remain_bytes ||
769 	    fdp->pos > (tee_fs_off_t)fdp->meta.info.length)
770 		remain_bytes = 0;
771 	else if (fdp->pos + remain_bytes > fdp->meta.info.length)
772 		remain_bytes = fdp->meta.info.length - fdp->pos;
773 
774 	*len = remain_bytes;
775 
776 	if (!remain_bytes) {
777 		res = TEE_SUCCESS;
778 		goto exit;
779 	}
780 
781 	start_block_num = pos_to_block_num(fdp->pos);
782 	end_block_num = pos_to_block_num(fdp->pos + remain_bytes - 1);
783 
784 	while (start_block_num <= end_block_num) {
785 		struct block *b;
786 		int offset = fdp->pos % BLOCK_FILE_SIZE;
787 		size_t size_to_read = remain_bytes > BLOCK_FILE_SIZE ?
788 			BLOCK_FILE_SIZE : remain_bytes;
789 
790 		if (size_to_read + offset > BLOCK_FILE_SIZE)
791 			size_to_read = BLOCK_FILE_SIZE - offset;
792 
793 		b = block_ops.read(fdp, start_block_num);
794 		if (!b) {
795 			res = TEE_ERROR_CORRUPT_OBJECT;
796 			goto exit;
797 		}
798 
799 		read_data_from_block(b, offset, data_ptr, size_to_read);
800 		data_ptr += size_to_read;
801 		remain_bytes -= size_to_read;
802 		fdp->pos += size_to_read;
803 
804 		start_block_num++;
805 	}
806 	res = TEE_SUCCESS;
807 exit:
808 	mutex_unlock(&ree_fs_mutex);
809 	return res;
810 }
811 
812 /*
813  * To ensure atomicity of write operation, we need to
814  * do the following steps:
815  * (The sequence of operations is very important)
816  *
817  *  - Create a new backup version of meta file as a copy
818  *    of current meta file.
819  *  - For each blocks to write:
820  *    - Create new backup version for current block.
821  *    - Write data to new backup version.
822  *    - Update the new meta file accordingly.
823  *  - Write the new meta file.
824  *
825  * (Any failure in above steps is considered as update failed,
826  *  and the file content will not be updated)
827  */
828 static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf,
829 			       size_t len)
830 {
831 	TEE_Result res;
832 	struct tee_fs_file_meta new_meta;
833 	struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
834 	size_t file_size;
835 
836 
837 	if (!len)
838 		return TEE_SUCCESS;
839 
840 	mutex_lock(&ree_fs_mutex);
841 
842 	file_size = fdp->meta.info.length;
843 
844 	if ((fdp->pos + len) > MAX_FILE_SIZE || (fdp->pos + len) < len) {
845 		res = TEE_ERROR_BAD_PARAMETERS;
846 		goto exit;
847 	}
848 
849 	if (file_size < (size_t)fdp->pos) {
850 		res = ree_fs_ftruncate_internal(fdp, fdp->pos);
851 		if (res != TEE_SUCCESS)
852 			goto exit;
853 	}
854 
855 	new_meta = fdp->meta;
856 	res = out_of_place_write(fdp, buf, len, &new_meta);
857 	if (res != TEE_SUCCESS)
858 		goto exit;
859 
860 	res = commit_meta_file(fdp, &new_meta);
861 exit:
862 	mutex_unlock(&ree_fs_mutex);
863 	return res;
864 }
865 
866 static TEE_Result ree_fs_rename_internal(const char *old, const char *new,
867 					 bool overwrite)
868 {
869 	size_t old_len;
870 	size_t new_len;
871 
872 	DMSG("old=%s, new=%s", old, new);
873 
874 	old_len = strlen(old) + 1;
875 	new_len = strlen(new) + 1;
876 
877 	if (old_len > TEE_FS_NAME_MAX || new_len > TEE_FS_NAME_MAX)
878 		return TEE_ERROR_BAD_PARAMETERS;
879 
880 	return tee_fs_rpc_new_rename(OPTEE_MSG_RPC_CMD_FS, old, new, overwrite);
881 }
882 
883 static TEE_Result ree_fs_rename(const char *old, const char *new,
884 				bool overwrite)
885 {
886 	TEE_Result res;
887 
888 	mutex_lock(&ree_fs_mutex);
889 	res = ree_fs_rename_internal(old, new, overwrite);
890 	mutex_unlock(&ree_fs_mutex);
891 
892 	return res;
893 }
894 
895 static TEE_Result ree_fs_remove(const char *file)
896 {
897 	TEE_Result res;
898 
899 	mutex_lock(&ree_fs_mutex);
900 	res = tee_fs_rpc_new_remove(OPTEE_MSG_RPC_CMD_FS, file);
901 	mutex_unlock(&ree_fs_mutex);
902 
903 	return res;
904 }
905 
906 static TEE_Result ree_fs_truncate(struct tee_file_handle *fh, size_t len)
907 {
908 	TEE_Result res;
909 	struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
910 
911 	mutex_lock(&ree_fs_mutex);
912 	res = ree_fs_ftruncate_internal(fdp, len);
913 	mutex_unlock(&ree_fs_mutex);
914 
915 	return res;
916 }
917 
918 const struct tee_file_operations ree_fs_ops = {
919 	.open = ree_fs_open,
920 	.create = ree_fs_create,
921 	.close = ree_fs_close,
922 	.read = ree_fs_read,
923 	.write = ree_fs_write,
924 	.seek = ree_fs_seek,
925 	.truncate = ree_fs_truncate,
926 	.rename = ree_fs_rename,
927 	.remove = ree_fs_remove,
928 	.opendir = ree_fs_opendir_rpc,
929 	.closedir = ree_fs_closedir_rpc,
930 	.readdir = ree_fs_readdir_rpc,
931 };
932