1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
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 #include <assert.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <handle.h>
32 #include <libgen.h>
33 #include <optee_msg_supplicant.h>
34 #include <stdbool.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <teec_trace.h>
41 #include <tee_supp_fs.h>
42 #include <tee_supplicant.h>
43 #include <unistd.h>
44 
45 #ifndef __aligned
46 #define __aligned(x) __attribute__((__aligned__(x)))
47 #endif
48 #include <linux/tee.h>
49 
50 #ifndef PATH_MAX
51 #define PATH_MAX 255
52 #endif
53 
54 /* Path to all secure storage files. */
55 static char tee_fs_root[PATH_MAX];
56 
57 #define TEE_FS_FILENAME_MAX_LENGTH 150
58 
59 static pthread_mutex_t dir_handle_db_mutex = PTHREAD_MUTEX_INITIALIZER;
60 static struct handle_db dir_handle_db =
61 		HANDLE_DB_INITIALIZER_WITH_MUTEX(&dir_handle_db_mutex);
62 
errno_to_teec(int err)63 static TEEC_Result errno_to_teec(int err)
64 {
65 	switch (err) {
66 	case ENOSPC:
67 		return TEEC_ERROR_STORAGE_NO_SPACE;
68 	case ENOENT:
69 		return TEEC_ERROR_ITEM_NOT_FOUND;
70 	default:
71 		break;
72 	}
73 	return TEEC_ERROR_GENERIC;
74 }
75 
tee_fs_get_absolute_filename(char * file,char * out,size_t out_size)76 static size_t tee_fs_get_absolute_filename(char *file, char *out,
77 					   size_t out_size)
78 {
79 	int s = 0;
80 
81 	if (!file || !out || (out_size <= strlen(tee_fs_root) + 1))
82 		return 0;
83 
84 	s = snprintf(out, out_size, "%s%s", tee_fs_root, file);
85 	if (s < 0 || (size_t)s >= out_size)
86 		return 0;
87 
88 	/* Safe to cast since we have checked that sizes are OK */
89 	return (size_t)s;
90 }
91 
fs_fsync(void)92 static void fs_fsync(void)
93 {
94 	int fd = 0;
95 
96 	fd = open(tee_fs_root, O_RDONLY | O_DIRECTORY);
97 	if (fd > 0) {
98 		fsync(fd);
99 		close(fd);
100 	}
101 }
102 
do_mkdir(const char * path,mode_t mode)103 static int do_mkdir(const char *path, mode_t mode)
104 {
105 	struct stat st;
106 
107 	memset(&st, 0, sizeof(st));
108 
109 	if (mkdir(path, mode) != 0 && errno != EEXIST)
110 		return -1;
111 
112 	if (stat(path, &st) != 0 && !S_ISDIR(st.st_mode))
113 		return -1;
114 
115 	fs_fsync();
116 	return 0;
117 }
118 
mkpath(const char * path,mode_t mode)119 static int mkpath(const char *path, mode_t mode)
120 {
121 	int status = 0;
122 	char *subpath = strdup(path);
123 	char *prev = subpath;
124 	char *curr = NULL;
125 
126 	while (status == 0 && (curr = strchr(prev, '/')) != 0) {
127 		/*
128 		 * Check for root or double slash
129 		 */
130 		if (curr != prev) {
131 			*curr = '\0';
132 			status = do_mkdir(subpath, mode);
133 			*curr = '/';
134 		}
135 		prev = curr + 1;
136 	}
137 	if (status == 0)
138 		status = do_mkdir(path, mode);
139 
140 	free(subpath);
141 	return status;
142 }
143 
tee_supp_fs_init(void)144 static int tee_supp_fs_init(void)
145 {
146 	size_t n = 0;
147 	mode_t mode = 0700;
148 
149 	n = snprintf(tee_fs_root, sizeof(tee_fs_root), "%s/", supplicant_params.fs_parent_path);
150 
151 	if (n >= sizeof(tee_fs_root))
152 		return -1;
153 
154 	if (mkpath(tee_fs_root, mode) != 0)
155 		return -1;
156 
157 	return 0;
158 }
159 
open_wrapper(const char * fname,int flags)160 static int open_wrapper(const char *fname, int flags)
161 {
162 	int fd = 0;
163 
164 	while (true) {
165 		fd = open(fname, flags | O_SYNC, 0600);
166 		if (fd >= 0 || errno != EINTR)
167 			return fd;
168 	}
169 }
170 
ree_fs_new_open(size_t num_params,struct tee_ioctl_param * params)171 static TEEC_Result ree_fs_new_open(size_t num_params,
172 				   struct tee_ioctl_param *params)
173 {
174 	char abs_filename[PATH_MAX] = { 0 };
175 	char *fname = NULL;
176 	int fd = 0;
177 
178 	if (num_params != 3 ||
179 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
180 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
181 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
182 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
183 	    (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
184 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
185 		return TEEC_ERROR_BAD_PARAMETERS;
186 
187 	fname = tee_supp_param_to_va(params + 1);
188 	if (!fname)
189 		return TEEC_ERROR_BAD_PARAMETERS;
190 
191 	if (!tee_fs_get_absolute_filename(fname, abs_filename,
192 					  sizeof(abs_filename)))
193 		return TEEC_ERROR_BAD_PARAMETERS;
194 
195 	fd = open_wrapper(abs_filename, O_RDWR);
196 	if (fd < 0) {
197 		/*
198 		 * In case the problem is the filesystem is RO, retry with the
199 		 * open flags restricted to RO.
200 		 */
201 		fd = open_wrapper(abs_filename, O_RDONLY);
202 		if (fd < 0)
203 			return TEEC_ERROR_ITEM_NOT_FOUND;
204 	}
205 
206 	params[2].a = fd;
207 	return TEEC_SUCCESS;
208 }
209 
ree_fs_new_create(size_t num_params,struct tee_ioctl_param * params)210 static TEEC_Result ree_fs_new_create(size_t num_params,
211 				     struct tee_ioctl_param *params)
212 {
213 	char abs_filename[PATH_MAX] = { 0 };
214 	char abs_dir[PATH_MAX] = { 0 };
215 	char *fname = NULL;
216 	char *d = NULL;
217 	int fd = 0;
218 	const int flags = O_RDWR | O_CREAT | O_TRUNC;
219 
220 	if (num_params != 3 ||
221 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
222 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
223 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
224 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
225 	    (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
226 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
227 		return TEEC_ERROR_BAD_PARAMETERS;
228 
229 	fname = tee_supp_param_to_va(params + 1);
230 	if (!fname)
231 		return TEEC_ERROR_BAD_PARAMETERS;
232 
233 	if (!tee_fs_get_absolute_filename(fname, abs_filename,
234 					  sizeof(abs_filename)))
235 		return TEEC_ERROR_BAD_PARAMETERS;
236 
237 	fd = open_wrapper(abs_filename, flags);
238 	if (fd >= 0)
239 		goto out;
240 	if (errno != ENOENT)
241 		return errno_to_teec(errno);
242 
243 	/* Directory for file missing, try make to it */
244 	strncpy(abs_dir, abs_filename, sizeof(abs_dir));
245 	abs_dir[sizeof(abs_dir) - 1] = '\0';
246 	d = dirname(abs_dir);
247 	if (!mkdir(d, 0700)) {
248 		int err = 0;
249 
250 		fd = open_wrapper(abs_filename, flags);
251 		if (fd >= 0)
252 			goto out;
253 		/*
254 		 * The directory was made but the file could still not be
255 		 * created.
256 		 */
257 		err = errno;
258 		rmdir(d);
259 		return errno_to_teec(err);
260 	}
261 	if (errno != ENOENT)
262 		return errno_to_teec(errno);
263 
264 	/* Parent directory for file missing, try to make it */
265 	d = dirname(d);
266 	if (mkdir(d, 0700))
267 		return errno_to_teec(errno);
268 
269 	/* Try to make directory for file again */
270 	strncpy(abs_dir, abs_filename, sizeof(abs_dir));
271 	abs_dir[sizeof(abs_dir) - 1] = '\0';
272 	d = dirname(abs_dir);
273 	if (mkdir(d, 0700)) {
274 		int err = errno;
275 
276 		d = dirname(d);
277 		rmdir(d);
278 		return errno_to_teec(err);
279 	}
280 
281 	fd = open_wrapper(abs_filename, flags);
282 	if (fd < 0) {
283 		int err = errno;
284 
285 		rmdir(d);
286 		d = dirname(d);
287 		rmdir(d);
288 		return errno_to_teec(err);
289 	}
290 
291 out:
292 	fs_fsync();
293 	params[2].a = fd;
294 	return TEEC_SUCCESS;
295 }
296 
ree_fs_new_close(size_t num_params,struct tee_ioctl_param * params)297 static TEEC_Result ree_fs_new_close(size_t num_params,
298 				    struct tee_ioctl_param *params)
299 {
300 	int fd = 0;
301 
302 	if (num_params != 1 ||
303 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
304 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
305 		return TEEC_ERROR_BAD_PARAMETERS;
306 
307 	fd = params[0].b;
308 	while (close(fd)) {
309 		if (errno != EINTR)
310 			return errno_to_teec(errno);
311 	}
312 	return TEEC_SUCCESS;
313 }
314 
ree_fs_new_read(size_t num_params,struct tee_ioctl_param * params)315 static TEEC_Result ree_fs_new_read(size_t num_params,
316 				   struct tee_ioctl_param *params)
317 {
318 	uint8_t *buf = NULL;
319 	size_t len = 0;
320 	off_t offs = 0;
321 	int fd = 0;
322 	ssize_t r = 0;
323 	size_t s = 0;
324 
325 	if (num_params != 2 ||
326 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
327 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
328 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
329 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
330 		return TEEC_ERROR_BAD_PARAMETERS;
331 
332 	fd = params[0].b;
333 	offs = params[0].c;
334 
335 	buf = tee_supp_param_to_va(params + 1);
336 	if (!buf)
337 		return TEEC_ERROR_BAD_PARAMETERS;
338 	len = MEMREF_SIZE(params + 1);
339 
340 	s = 0;
341 	r = -1;
342 	while (r && len) {
343 		r = pread(fd, buf, len, offs);
344 		if (r < 0) {
345 			if (errno == EINTR)
346 				continue;
347 			return errno_to_teec(errno);
348 		}
349 		assert((size_t)r <= len);
350 		buf += r;
351 		len -= r;
352 		offs += r;
353 		s += r;
354 	}
355 
356 	MEMREF_SIZE(params + 1) = s;
357 	return TEEC_SUCCESS;
358 }
359 
ree_fs_new_write(size_t num_params,struct tee_ioctl_param * params)360 static TEEC_Result ree_fs_new_write(size_t num_params,
361 				    struct tee_ioctl_param *params)
362 {
363 	uint8_t *buf = NULL;
364 	size_t len = 0;
365 	off_t offs = 0;
366 	int fd = 0;
367 	ssize_t r = 0;
368 
369 	if (num_params != 2 ||
370 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
371 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
372 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
373 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
374 		return TEEC_ERROR_BAD_PARAMETERS;
375 
376 	fd = params[0].b;
377 	offs = params[0].c;
378 
379 	buf = tee_supp_param_to_va(params + 1);
380 	if (!buf)
381 		return TEEC_ERROR_BAD_PARAMETERS;
382 	len = MEMREF_SIZE(params + 1);
383 
384 	while (len) {
385 		r = pwrite(fd, buf, len, offs);
386 		if (r < 0) {
387 			if (errno == EINTR)
388 				continue;
389 			return errno_to_teec(errno);
390 		}
391 		assert((size_t)r <= len);
392 		buf += r;
393 		len -= r;
394 		offs += r;
395 	}
396 
397 	return TEEC_SUCCESS;
398 }
399 
ree_fs_new_truncate(size_t num_params,struct tee_ioctl_param * params)400 static TEEC_Result ree_fs_new_truncate(size_t num_params,
401 				       struct tee_ioctl_param *params)
402 {
403 	size_t len = 0;
404 	int fd = 0;
405 
406 	if (num_params != 1 ||
407 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
408 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
409 		return TEEC_ERROR_BAD_PARAMETERS;
410 
411 	fd = params[0].b;
412 	len = params[0].c;
413 
414 	while (ftruncate(fd, len)) {
415 		if (errno != EINTR)
416 			return errno_to_teec(errno);
417 	}
418 
419 	return TEEC_SUCCESS;
420 }
421 
ree_fs_new_remove(size_t num_params,struct tee_ioctl_param * params)422 static TEEC_Result ree_fs_new_remove(size_t num_params,
423 				     struct tee_ioctl_param *params)
424 {
425 	char abs_filename[PATH_MAX] = { 0 };
426 	char *fname = NULL;
427 	char *d = NULL;
428 
429 	if (num_params != 2 ||
430 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
431 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
432 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
433 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
434 		return TEEC_ERROR_BAD_PARAMETERS;
435 
436 	fname = tee_supp_param_to_va(params + 1);
437 	if (!fname)
438 		return TEEC_ERROR_BAD_PARAMETERS;
439 
440 	if (!tee_fs_get_absolute_filename(fname, abs_filename,
441 					  sizeof(abs_filename)))
442 		return TEEC_ERROR_BAD_PARAMETERS;
443 
444 	if (unlink(abs_filename))
445 		return errno_to_teec(errno);
446 
447 	/* If a file is removed, maybe the directory can be removed to? */
448 	d = dirname(abs_filename);
449 	if (!rmdir(d)) {
450 		/*
451 		 * If the directory was removed, maybe the parent directory
452 		 * can be removed too?
453 		 */
454 		d = dirname(d);
455 		rmdir(d);
456 	}
457 
458 	return TEEC_SUCCESS;
459 }
460 
ree_fs_new_rename(size_t num_params,struct tee_ioctl_param * params)461 static TEEC_Result ree_fs_new_rename(size_t num_params,
462 				     struct tee_ioctl_param *params)
463 {
464 	char old_abs_filename[PATH_MAX] = { 0 };
465 	char new_abs_filename[PATH_MAX] = { 0 };
466 	char *old_fname = NULL;
467 	char *new_fname = NULL;
468 	bool overwrite = false;
469 
470 	if (num_params != 3 ||
471 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
472 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
473 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
474 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
475 	    (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
476 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
477 		return TEEC_ERROR_BAD_PARAMETERS;
478 
479 	overwrite = !!params[0].b;
480 
481 	old_fname = tee_supp_param_to_va(params + 1);
482 	if (!old_fname)
483 		return TEEC_ERROR_BAD_PARAMETERS;
484 
485 	new_fname = tee_supp_param_to_va(params + 2);
486 	if (!new_fname)
487 		return TEEC_ERROR_BAD_PARAMETERS;
488 
489 	if (!tee_fs_get_absolute_filename(old_fname, old_abs_filename,
490 					  sizeof(old_abs_filename)))
491 		return TEEC_ERROR_BAD_PARAMETERS;
492 
493 	if (!tee_fs_get_absolute_filename(new_fname, new_abs_filename,
494 					  sizeof(new_abs_filename)))
495 		return TEEC_ERROR_BAD_PARAMETERS;
496 
497 	if (!overwrite) {
498 		struct stat st;
499 
500 		if (!stat(new_abs_filename, &st))
501 			return TEEC_ERROR_ACCESS_CONFLICT;
502 	}
503 	if (rename(old_abs_filename, new_abs_filename)) {
504 		if (errno == ENOENT)
505 			return TEEC_ERROR_ITEM_NOT_FOUND;
506 	}
507 
508 	fs_fsync();
509 	return TEEC_SUCCESS;
510 }
511 
ree_fs_new_opendir(size_t num_params,struct tee_ioctl_param * params)512 static TEEC_Result ree_fs_new_opendir(size_t num_params,
513 				      struct tee_ioctl_param *params)
514 {
515 	char abs_filename[PATH_MAX] = { 0 };
516 	char *fname = NULL;
517 	DIR *dir = NULL;
518 	int handle = 0;
519 	struct dirent *dent = NULL;
520 	bool empty = true;
521 
522 	if (num_params != 3 ||
523 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
524 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
525 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
526 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
527 	    (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
528 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
529 		return TEEC_ERROR_BAD_PARAMETERS;
530 
531 	fname = tee_supp_param_to_va(params + 1);
532 	if (!fname)
533 		return TEEC_ERROR_BAD_PARAMETERS;
534 
535 	if (!tee_fs_get_absolute_filename(fname, abs_filename,
536 					  sizeof(abs_filename)))
537 		return TEEC_ERROR_BAD_PARAMETERS;
538 
539 	dir = opendir(abs_filename);
540 	if (!dir)
541 		return TEEC_ERROR_ITEM_NOT_FOUND;
542 
543 	/*
544 	 * Ignore empty directories. Works around an issue when the
545 	 * data path is mounted over NFS. Due to the way OP-TEE implements
546 	 * TEE_CloseAndDeletePersistentObject1() currently, tee-supplicant
547 	 * still has a file descriptor open to the file when it's removed in
548 	 * ree_fs_new_remove(). In this case the NFS server may create a
549 	 * temporary reference called .nfs????, and the rmdir() call fails
550 	 * so that the TA directory is left over. Checking this special case
551 	 * here avoids that TEE_StartPersistentObjectEnumerator() returns
552 	 * TEE_SUCCESS when it should return TEEC_ERROR_ITEM_NOT_FOUND.
553 	 * Test case: "xtest 6009 6010".
554 	 */
555 	while ((dent = readdir(dir))) {
556 		if (dent->d_name[0] == '.')
557 			continue;
558 		empty = false;
559 		break;
560 	}
561 	if (empty) {
562 		closedir(dir);
563 		return TEEC_ERROR_ITEM_NOT_FOUND;
564 	}
565 	rewinddir(dir);
566 
567 	handle = handle_get(&dir_handle_db, dir);
568 	if (handle < 0) {
569 		closedir(dir);
570 		return TEEC_ERROR_OUT_OF_MEMORY;
571 	}
572 
573 	params[2].a = handle;
574 	return TEEC_SUCCESS;
575 }
576 
ree_fs_new_closedir(size_t num_params,struct tee_ioctl_param * params)577 static TEEC_Result ree_fs_new_closedir(size_t num_params,
578 				       struct tee_ioctl_param *params)
579 {
580 	DIR *dir = NULL;
581 
582 	if (num_params != 1 ||
583 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
584 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
585 		return TEEC_ERROR_BAD_PARAMETERS;
586 
587 	dir = handle_put(&dir_handle_db, params[0].b);
588 	if (!dir)
589 		return TEEC_ERROR_BAD_PARAMETERS;
590 
591 	closedir(dir);
592 
593 	return TEEC_SUCCESS;
594 }
595 
ree_fs_new_readdir(size_t num_params,struct tee_ioctl_param * params)596 static TEEC_Result ree_fs_new_readdir(size_t num_params,
597 				      struct tee_ioctl_param *params)
598 {
599 	DIR *dir = NULL;
600 	struct dirent *dirent = NULL;
601 	char *buf = NULL;
602 	size_t len = 0;
603 	size_t fname_len = 0;
604 
605 	if (num_params != 2 ||
606 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
607 			TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
608 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
609 			TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
610 		return TEEC_ERROR_BAD_PARAMETERS;
611 
612 
613 	buf = tee_supp_param_to_va(params + 1);
614 	if (!buf)
615 		return TEEC_ERROR_BAD_PARAMETERS;
616 	len = MEMREF_SIZE(params + 1);
617 
618 	dir = handle_lookup(&dir_handle_db, params[0].b);
619 	if (!dir)
620 		return TEEC_ERROR_BAD_PARAMETERS;
621 
622 	while (true) {
623 		dirent = readdir(dir);
624 		if (!dirent)
625 			return TEEC_ERROR_ITEM_NOT_FOUND;
626 		if (dirent->d_name[0] != '.')
627 			break;
628 	}
629 
630 	fname_len = strlen(dirent->d_name) + 1;
631 	MEMREF_SIZE(params + 1) = fname_len;
632 	if (fname_len > len)
633 		return TEEC_ERROR_SHORT_BUFFER;
634 
635 	memcpy(buf, dirent->d_name, fname_len);
636 
637 	return TEEC_SUCCESS;
638 }
639 
tee_supp_fs_process(size_t num_params,struct tee_ioctl_param * params)640 TEEC_Result tee_supp_fs_process(size_t num_params,
641 				struct tee_ioctl_param *params)
642 {
643 	if (!num_params || !tee_supp_param_is_value(params))
644 		return TEEC_ERROR_BAD_PARAMETERS;
645 
646 	if (!tee_fs_root[0]) {
647 		if (tee_supp_fs_init() != 0) {
648 			EMSG("error tee_supp_fs_init: failed to create %s/",
649 				tee_fs_root);
650 			memset(tee_fs_root, 0, sizeof(tee_fs_root));
651 			return TEEC_ERROR_STORAGE_NOT_AVAILABLE;
652 		}
653 	}
654 
655 	switch (params->a) {
656 	case OPTEE_MRF_OPEN:
657 		return ree_fs_new_open(num_params, params);
658 	case OPTEE_MRF_CREATE:
659 		return ree_fs_new_create(num_params, params);
660 	case OPTEE_MRF_CLOSE:
661 		return ree_fs_new_close(num_params, params);
662 	case OPTEE_MRF_READ:
663 		return ree_fs_new_read(num_params, params);
664 	case OPTEE_MRF_WRITE:
665 		return ree_fs_new_write(num_params, params);
666 	case OPTEE_MRF_TRUNCATE:
667 		return ree_fs_new_truncate(num_params, params);
668 	case OPTEE_MRF_REMOVE:
669 		return ree_fs_new_remove(num_params, params);
670 	case OPTEE_MRF_RENAME:
671 		return ree_fs_new_rename(num_params, params);
672 	case OPTEE_MRF_OPENDIR:
673 		return ree_fs_new_opendir(num_params, params);
674 	case OPTEE_MRF_CLOSEDIR:
675 		return ree_fs_new_closedir(num_params, params);
676 	case OPTEE_MRF_READDIR:
677 		return ree_fs_new_readdir(num_params, params);
678 	default:
679 		return TEEC_ERROR_BAD_PARAMETERS;
680 	}
681 }
682