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