xref: /optee_os/core/tee/tee_svc_storage.c (revision a50cb361d9e5735f197ccc87beb0d24af8315369)
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 
28 #include <kernel/tee_ta_manager.h>
29 #include <kernel/tee_misc.h>
30 #include <mm/tee_mmu.h>
31 #include <tee/tee_fs.h>
32 #include <tee/tee_fs_defs.h>
33 #include <tee/tee_obj.h>
34 #include <tee/tee_svc.h>
35 #include <tee/tee_pobj.h>
36 #include <tee/tee_svc_storage.h>
37 #include <tee/tee_svc_cryp.h>
38 #include <tee_api_defines.h>
39 #include <tee_api_defines_extensions.h>
40 #include <trace.h>
41 
42 /*
43  * Returns the appropriate tee_file_operations for the specified storage ID.
44  * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise
45  * RPMB.
46  */
47 static const struct tee_file_operations *file_ops(uint32_t storage_id)
48 {
49 
50 	switch (storage_id) {
51 	case TEE_STORAGE_PRIVATE:
52 #if defined(CFG_REE_FS)
53 		return &ree_fs_ops;
54 #elif defined(CFG_RPMB_FS)
55 		return &rpmb_fs_ops;
56 #elif defined(CFG_SQL_FS)
57 		return &sql_fs_ops;
58 #else
59 #error At least one filesystem must be enabled.
60 #endif
61 #ifdef CFG_REE_FS
62 	case TEE_STORAGE_PRIVATE_REE:
63 		return &ree_fs_ops;
64 #endif
65 #ifdef CFG_RPMB_FS
66 	case TEE_STORAGE_PRIVATE_RPMB:
67 		return &rpmb_fs_ops;
68 #endif
69 #ifdef CFG_SQL_FS
70 	case TEE_STORAGE_PRIVATE_SQL:
71 		return &sql_fs_ops;
72 #endif
73 	default:
74 		return NULL;
75 	}
76 }
77 
78 /* SSF (Secure Storage File version 00 */
79 #define TEE_SVC_STORAGE_MAGIC 0x53534600;
80 
81 /* Header of GP formated secure storage files */
82 struct tee_svc_storage_head {
83 	uint32_t magic;
84 	uint32_t head_size;
85 	uint32_t meta_size;
86 	uint32_t ds_size;
87 	uint32_t keySize;
88 	uint32_t maxKeySize;
89 	uint32_t objectUsage;
90 	uint32_t objectType;
91 	uint32_t have_attrs;
92 };
93 
94 struct tee_storage_enum {
95 	TAILQ_ENTRY(tee_storage_enum) link;
96 	struct tee_fs_dir *dir;
97 	const struct tee_file_operations *fops;
98 };
99 
100 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc,
101 					   uint32_t enum_id,
102 					   struct tee_storage_enum **e_out)
103 {
104 	struct tee_storage_enum *e;
105 
106 	TAILQ_FOREACH(e, &utc->storage_enums, link) {
107 		if (enum_id == (vaddr_t)e) {
108 			*e_out = e;
109 			return TEE_SUCCESS;
110 		}
111 	}
112 	return TEE_ERROR_BAD_PARAMETERS;
113 }
114 
115 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc,
116 				     struct tee_storage_enum *e)
117 {
118 	int ret;
119 
120 	if (e == NULL || utc == NULL)
121 		return TEE_ERROR_BAD_PARAMETERS;
122 
123 	TAILQ_REMOVE(&utc->storage_enums, e, link);
124 
125 	if (!e->fops)
126 		return TEE_ERROR_ITEM_NOT_FOUND;
127 
128 	ret = e->fops->closedir(e->dir);
129 	e->dir = NULL;
130 	e->fops = NULL;
131 
132 	free(e);
133 
134 	if (ret != 0)
135 		return TEE_ERROR_ITEM_NOT_FOUND;
136 
137 	return TEE_SUCCESS;
138 }
139 
140 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */
141 char *tee_svc_storage_create_filename(struct tee_ta_session *sess,
142 				      void *object_id,
143 				      uint32_t object_id_len,
144 				      bool transient)
145 {
146 	uint8_t *file;
147 	uint32_t pos = 0;
148 	uint32_t hslen = 1 /* Leading slash */
149 			+ TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len)
150 			+ 1; /* Intermediate slash */
151 
152 	/* +1 for the '.' (temporary persistent object) */
153 	if (transient)
154 		hslen++;
155 
156 	file = malloc(hslen);
157 	if (!file)
158 		return NULL;
159 
160 	file[pos++] = '/';
161 	pos += tee_b2hs((uint8_t *)&sess->ctx->uuid, &file[pos],
162 			sizeof(TEE_UUID), hslen);
163 	file[pos++] = '/';
164 
165 	if (transient)
166 		file[pos++] = '.';
167 
168 	tee_b2hs(object_id, file + pos, object_id_len, hslen - pos);
169 
170 	return (char *)file;
171 }
172 
173 /* "/TA_uuid" */
174 char *tee_svc_storage_create_dirname(struct tee_ta_session *sess)
175 {
176 	uint8_t *dir;
177 	uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1;
178 
179 	dir = malloc(hslen);
180 	if (!dir)
181 		return NULL;
182 
183 	dir[0] = '/';
184 	tee_b2hs((uint8_t *)&sess->ctx->uuid, dir + 1, sizeof(TEE_UUID),
185 		 hslen);
186 
187 	return (char *)dir;
188 }
189 
190 static TEE_Result tee_svc_storage_remove_corrupt_obj(
191 					struct tee_ta_session *sess,
192 					struct tee_obj *o)
193 {
194 	TEE_Result res;
195 	char *file = NULL;
196 	char *dir = NULL;
197 	const struct tee_file_operations *fops = o->pobj->fops;
198 
199 	file = tee_svc_storage_create_filename(sess,
200 					       o->pobj->obj_id,
201 					       o->pobj->obj_id_len,
202 					       false);
203 	if (file == NULL) {
204 		res = TEE_ERROR_OUT_OF_MEMORY;
205 		goto exit;
206 	}
207 
208 	tee_obj_close(to_user_ta_ctx(sess->ctx), o);
209 	fops->unlink(file);
210 	free(file);
211 	dir = tee_svc_storage_create_dirname(sess);
212 	if (dir != NULL) {
213 		fops->rmdir(dir);
214 		free(dir);
215 	}
216 
217 	res = TEE_SUCCESS;
218 
219 exit:
220 	return res;
221 }
222 
223 static uint32_t tee_svc_storage_conv_oflags(uint32_t flags)
224 {
225 	uint32_t out = 0;
226 
227 	if (flags & (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_SHARE_READ)) {
228 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
229 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
230 			     TEE_DATA_FLAG_SHARE_WRITE))
231 			out |= TEE_FS_O_RDWR;
232 		else
233 			out |= TEE_FS_O_RDONLY;
234 	} else {
235 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
236 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
237 			     TEE_DATA_FLAG_SHARE_WRITE))
238 			out |= TEE_FS_O_WRONLY;
239 	}
240 
241 	return out;
242 }
243 
244 static int tee_svc_storage_conv_whence(TEE_Whence whence)
245 {
246 	switch (whence) {
247 	case TEE_DATA_SEEK_SET:
248 		return TEE_FS_SEEK_SET;
249 	case TEE_DATA_SEEK_CUR:
250 		return TEE_FS_SEEK_CUR;
251 	case TEE_DATA_SEEK_END:
252 		return TEE_FS_SEEK_END;
253 	default:
254 		return -1;
255 	}
256 }
257 
258 static TEE_Result tee_svc_storage_create_file(struct tee_ta_session *sess,
259 			char *file,
260 			const struct tee_file_operations *fops,
261 			int *fd)
262 {
263 	TEE_Result res = TEE_SUCCESS;
264 	TEE_Result errno;
265 	char *dir = NULL;
266 	int tmp;
267 	int err;
268 	uint32_t cflags = TEE_FS_O_WRONLY |
269 			TEE_FS_O_CREATE | TEE_FS_O_TRUNC;
270 
271 	dir = tee_svc_storage_create_dirname(sess);
272 	if (dir == NULL) {
273 		res = TEE_ERROR_OUT_OF_MEMORY;
274 		goto exit;
275 	}
276 
277 	/* try and make directory */
278 	err = fops->access(dir, TEE_FS_F_OK);
279 	if (err) {
280 		/* directory does not exists */
281 		tmp = fops->mkdir(dir, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR |
282 				  TEE_FS_S_IXUSR);
283 
284 		if (tmp < 0) {
285 			/* error codes needs better granularity */
286 			res = TEE_ERROR_GENERIC;
287 			goto exit;
288 		}
289 	}
290 
291 	/* try and open again */
292 	*fd = fops->open(&errno, file, cflags);
293 	if (*fd < 0)
294 		res = errno;
295 
296 exit:
297 	free(dir);
298 
299 	return res;
300 }
301 
302 static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
303 				     struct tee_obj *o)
304 {
305 	TEE_Result res = TEE_SUCCESS;
306 	TEE_Result errno;
307 	int fd = -1;
308 	int err;
309 	struct tee_svc_storage_head head;
310 	char *file = NULL;
311 	const struct tee_file_operations *fops;
312 	void *attr = NULL;
313 
314 	if (o == NULL || o->pobj == NULL)
315 		return TEE_ERROR_BAD_PARAMETERS;
316 
317 	fops = o->pobj->fops;
318 
319 	file = tee_svc_storage_create_filename(sess,
320 					       o->pobj->obj_id,
321 					       o->pobj->obj_id_len,
322 					       false);
323 	if (file == NULL) {
324 		res = TEE_ERROR_OUT_OF_MEMORY;
325 		goto exit;
326 	}
327 
328 	fd = fops->open(&errno, file, TEE_FS_O_RDONLY);
329 	free(file);
330 	if (fd < 0) {
331 		res = errno;
332 		goto exit;
333 	}
334 
335 	/* read head */
336 	err = fops->read(&errno, fd, &head,
337 				sizeof(struct tee_svc_storage_head));
338 	if (err < 0) {
339 		res = errno;
340 		if (res == TEE_ERROR_CORRUPT_OBJECT)
341 			EMSG("Head corrupt\n");
342 		goto exit;
343 	}
344 
345 	if (err != sizeof(struct tee_svc_storage_head)) {
346 		res = TEE_ERROR_BAD_FORMAT;
347 		goto exit;
348 	}
349 
350 	res = tee_obj_set_type(o, head.objectType, head.maxKeySize);
351 	if (res != TEE_SUCCESS)
352 		goto exit;
353 
354 	if (head.meta_size) {
355 		attr = malloc(head.meta_size);
356 		if (!attr) {
357 			res = TEE_ERROR_OUT_OF_MEMORY;
358 			goto exit;
359 		}
360 
361 		/* read meta */
362 		err = fops->read(&errno, fd, attr, head.meta_size);
363 		if (err != (int)head.meta_size) {
364 			res = TEE_ERROR_CORRUPT_OBJECT;
365 			goto exit;
366 		}
367 	}
368 
369 	res = tee_obj_attr_from_binary(o, attr, head.meta_size);
370 	if (res != TEE_SUCCESS)
371 		goto exit;
372 
373 	o->info.dataSize = head.ds_size;
374 	o->info.keySize = head.keySize;
375 	o->info.objectUsage = head.objectUsage;
376 	o->info.objectType = head.objectType;
377 	o->have_attrs = head.have_attrs;
378 
379 exit:
380 	free(attr);
381 	if (fd >= 0)
382 		fops->close(fd);
383 
384 	return res;
385 }
386 
387 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
388 					    struct tee_obj *o,
389 					    struct tee_obj *attr_o, void *data,
390 					    uint32_t len)
391 {
392 	TEE_Result res = TEE_SUCCESS;
393 	TEE_Result errno;
394 	int fd = -1;
395 	int err = -1;
396 	struct tee_svc_storage_head head;
397 	char *tmpfile = NULL;
398 	const struct tee_file_operations *fops;
399 	void *attr = NULL;
400 	size_t attr_size = 0;
401 
402 	if (o == NULL || o->pobj == NULL)
403 		return TEE_ERROR_BAD_PARAMETERS;
404 
405 	fops = o->pobj->fops;
406 
407 	/* create temporary persistent object filename */
408 	tmpfile = tee_svc_storage_create_filename(sess,
409 						   o->pobj->obj_id,
410 						   o->pobj->obj_id_len,
411 						   true);
412 
413 	if (tmpfile == NULL) {
414 		res = TEE_ERROR_OUT_OF_MEMORY;
415 		goto exit;
416 	}
417 
418 	res = tee_svc_storage_create_file(sess, tmpfile, fops, &fd);
419 	if (res != TEE_SUCCESS)
420 		goto exit;
421 
422 	if (attr_o) {
423 		res = tee_obj_set_type(o, attr_o->info.objectType,
424 				       attr_o->info.maxKeySize);
425 		if (res != TEE_SUCCESS)
426 			goto exit;
427 		res = tee_obj_attr_copy_from(o, attr_o);
428 		if (res != TEE_SUCCESS)
429 			goto exit;
430 		o->have_attrs = attr_o->have_attrs;
431 		o->info.objectUsage = attr_o->info.objectUsage;
432 		o->info.keySize = attr_o->info.keySize;
433 		res = tee_obj_attr_to_binary(o, NULL, &attr_size);
434 		if (res != TEE_SUCCESS)
435 			goto exit;
436 		if (attr_size) {
437 			attr = malloc(attr_size);
438 			if (!attr) {
439 				res = TEE_ERROR_OUT_OF_MEMORY;
440 				goto exit;
441 			}
442 			res = tee_obj_attr_to_binary(o, attr, &attr_size);
443 			if (res != TEE_SUCCESS)
444 				goto exit;
445 		}
446 	} else {
447 		res = tee_obj_set_type(o, TEE_TYPE_DATA, 0);
448 		if (res != TEE_SUCCESS)
449 			goto exit;
450 	}
451 
452 	/* write head */
453 	head.magic = TEE_SVC_STORAGE_MAGIC;
454 	head.head_size = sizeof(struct tee_svc_storage_head);
455 	head.meta_size = attr_size;
456 	head.ds_size = len;
457 	head.keySize = o->info.keySize;
458 	head.maxKeySize = o->info.maxKeySize;
459 	head.objectUsage = o->info.objectUsage;
460 	head.objectType = o->info.objectType;
461 	head.have_attrs = o->have_attrs;
462 
463 	/* write head */
464 	err = fops->write(&errno, fd, &head,
465 			sizeof(struct tee_svc_storage_head));
466 	if (err < 0)
467 		res = errno;
468 	if (err != sizeof(struct tee_svc_storage_head))
469 		goto exit;
470 
471 	/* write meta */
472 	err = fops->write(&errno, fd, attr, attr_size);
473 	if (err < 0)
474 		res = errno;
475 	if (err != (int)attr_size)
476 		goto exit;
477 
478 	/* write init data */
479 	o->info.dataSize = len;
480 
481 	/* write data to fs if needed */
482 	if (data && len) {
483 		err = fops->write(&errno, fd, data, len);
484 		if (err < 0)
485 			res = errno;
486 		if (err != (int)len)
487 			goto exit;
488 	}
489 
490 exit:
491 	free(attr);
492 	free(tmpfile);
493 	tmpfile = NULL;
494 	if (fd != -1)
495 		fops->close(fd);
496 
497 	return res;
498 }
499 
500 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
501 			size_t object_id_len, unsigned long flags,
502 			uint32_t *obj)
503 {
504 	TEE_Result res;
505 	TEE_Result errno;
506 	struct tee_ta_session *sess;
507 	struct tee_obj *o;
508 	char *file = NULL;
509 	int fs_flags;
510 	int fd = -1;
511 	tee_fs_off_t off;
512 	tee_fs_off_t e_off;
513 	struct tee_pobj *po = NULL;
514 	int err = -1;
515 	struct user_ta_ctx *utc;
516 	const struct tee_file_operations *fops = file_ops(storage_id);
517 	size_t attr_size;
518 
519 	if (!fops) {
520 		res = TEE_ERROR_ITEM_NOT_FOUND;
521 		goto exit;
522 	}
523 
524 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN) {
525 		res = TEE_ERROR_BAD_PARAMETERS;
526 		goto exit;
527 	}
528 
529 	res = tee_ta_get_current_session(&sess);
530 	if (res != TEE_SUCCESS)
531 		goto err;
532 	utc = to_user_ta_ctx(sess->ctx);
533 
534 	res = tee_mmu_check_access_rights(utc,
535 					  TEE_MEMORY_ACCESS_READ |
536 					  TEE_MEMORY_ACCESS_ANY_OWNER,
537 					  (tee_uaddr_t) object_id,
538 					  object_id_len);
539 	if (res != TEE_SUCCESS)
540 		goto err;
541 
542 	res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
543 			   object_id_len, flags, fops, &po);
544 	if (res != TEE_SUCCESS)
545 		goto err;
546 
547 	fs_flags = tee_svc_storage_conv_oflags(flags);
548 
549 	o = tee_obj_alloc();
550 	if (o == NULL) {
551 		res = TEE_ERROR_OUT_OF_MEMORY;
552 		goto err;
553 	}
554 
555 	o->info.handleFlags =
556 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
557 	o->flags = flags;
558 	o->pobj = po;
559 
560 	res = tee_svc_storage_read_head(sess, o);
561 	if (res != TEE_SUCCESS) {
562 		tee_obj_add(utc, o);
563 		if (res == TEE_ERROR_CORRUPT_OBJECT) {
564 			EMSG("Object corrupt\n");
565 			res = tee_svc_storage_remove_corrupt_obj(sess, o);
566 			if (res != TEE_SUCCESS)
567 				goto exit;
568 			res = TEE_ERROR_CORRUPT_OBJECT;
569 			goto exit;
570 		}
571 		goto oclose;
572 	}
573 
574 	file = tee_svc_storage_create_filename(sess, object_id,
575 					       object_id_len, false);
576 	if (file == NULL) {
577 		res = TEE_ERROR_OUT_OF_MEMORY;
578 		goto err;
579 	}
580 
581 	err = fops->access(file, TEE_FS_F_OK);
582 	if (err) {
583 		/* file not found */
584 		res = TEE_ERROR_STORAGE_NOT_AVAILABLE;
585 		goto err;
586 	}
587 
588 	fd = fops->open(&errno, file, fs_flags);
589 	if (fd < 0) {
590 		res = errno;
591 		goto err;
592 	}
593 	o->fd = fd;
594 
595 	tee_obj_add(utc, o);
596 
597 	res = tee_svc_copy_kaddr_to_uref(obj, o);
598 	if (res != TEE_SUCCESS)
599 		goto oclose;
600 
601 	res = tee_obj_attr_to_binary(o, NULL, &attr_size);
602 	if (res != TEE_SUCCESS && res)
603 		goto oclose;
604 
605 	e_off = sizeof(struct tee_svc_storage_head) + attr_size;
606 	off = fops->lseek(&errno, fd, e_off, TEE_FS_SEEK_SET);
607 	if (off != e_off) {
608 		res = TEE_ERROR_NO_DATA;
609 		goto oclose;
610 	} else {
611 		res = TEE_SUCCESS;
612 	}
613 
614 	goto exit;
615 
616 oclose:
617 	tee_obj_close(utc, o);
618 
619 err:
620 	if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT)
621 		res = TEE_ERROR_CORRUPT_OBJECT;
622 	if (res == TEE_ERROR_CORRUPT_OBJECT)
623 		fops->unlink(file);
624 	if (fd >= 0)
625 		fops->close(fd);
626 	if (po)
627 		tee_pobj_release(po);
628 
629 exit:
630 	free(file);
631 	file = NULL;
632 	return res;
633 }
634 
635 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
636 			size_t object_id_len, unsigned long flags,
637 			unsigned long attr, void *data, size_t len,
638 			uint32_t *obj)
639 {
640 	TEE_Result res;
641 	TEE_Result errno;
642 	struct tee_ta_session *sess;
643 	struct tee_obj *o = NULL;
644 	struct tee_obj *attr_o = NULL;
645 	char *file = NULL;
646 	int fd = -1;
647 	int fs_flags;
648 	tee_fs_off_t off;
649 	tee_fs_off_t e_off;
650 	struct tee_pobj *po = NULL;
651 	char *tmpfile = NULL;
652 	int err = -1;
653 	int filedoesnotexist;
654 	struct user_ta_ctx *utc;
655 	const struct tee_file_operations *fops = file_ops(storage_id);
656 	size_t attr_size;
657 
658 	if (!fops)
659 		return TEE_ERROR_ITEM_NOT_FOUND;
660 
661 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
662 		return TEE_ERROR_BAD_PARAMETERS;
663 
664 	res = tee_ta_get_current_session(&sess);
665 	if (res != TEE_SUCCESS)
666 		return res;
667 	utc = to_user_ta_ctx(sess->ctx);
668 
669 	res = tee_mmu_check_access_rights(utc,
670 					  TEE_MEMORY_ACCESS_READ |
671 					  TEE_MEMORY_ACCESS_ANY_OWNER,
672 					  (tee_uaddr_t) object_id,
673 					  object_id_len);
674 	if (res != TEE_SUCCESS)
675 		goto err;
676 
677 	res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
678 			   object_id_len, flags, fops, &po);
679 	if (res != TEE_SUCCESS)
680 		goto err;
681 
682 	/* check rights of the provided buffer */
683 	if (data && len) {
684 		res = tee_mmu_check_access_rights(utc,
685 						  TEE_MEMORY_ACCESS_READ |
686 						  TEE_MEMORY_ACCESS_ANY_OWNER,
687 						  (tee_uaddr_t) data, len);
688 
689 		if (res != TEE_SUCCESS)
690 			goto err;
691 	}
692 
693 	o = tee_obj_alloc();
694 	if (o == NULL) {
695 		res = TEE_ERROR_OUT_OF_MEMORY;
696 		goto err;
697 	}
698 
699 	o->info.handleFlags =
700 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
701 	o->flags = flags;
702 	o->pobj = po;
703 
704 	if (attr != TEE_HANDLE_NULL) {
705 		res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr),
706 				  &attr_o);
707 		if (res != TEE_SUCCESS)
708 			goto err;
709 	}
710 
711 	res = tee_svc_storage_init_file(sess, o, attr_o, data, len);
712 	if (res != TEE_SUCCESS)
713 		goto err;
714 
715 	/* create persistent object filename */
716 	file = tee_svc_storage_create_filename(sess, object_id,
717 					       object_id_len, false);
718 	if (file == NULL) {
719 		res = TEE_ERROR_OUT_OF_MEMORY;
720 		goto err;
721 	}
722 
723 	filedoesnotexist = fops->access(file, TEE_FS_F_OK);
724 	if (!filedoesnotexist) {
725 		/* file exists */
726 		if (!(flags & TEE_DATA_FLAG_OVERWRITE)) {
727 			res = TEE_ERROR_ACCESS_CONFLICT;
728 			goto err;
729 		}
730 	}
731 
732 	/* create temporary persistent object filename */
733 	tmpfile = tee_svc_storage_create_filename(sess, object_id,
734 						  object_id_len,
735 						  true);
736 	if (tmpfile == NULL) {
737 		res = TEE_ERROR_OUT_OF_MEMORY;
738 		goto err;
739 	}
740 
741 	/*
742 	 * remove the file if it exists, because rename does not perform
743 	 * this operation. Note that it delete and rename should be atomic,
744 	 * which is not the case currently.
745 	 * Fixme: unlink must be removed once rename() support prior deletion
746 	 * of the new file name when it already exists.
747 	 */
748 	if (!filedoesnotexist)
749 		fops->unlink(file);
750 	/* rename temporary persistent object filename */
751 	err = fops->rename(tmpfile, file);
752 	if (err) {
753 		/* error codes needs better granularity */
754 		res = TEE_ERROR_GENERIC;
755 		goto rmfile;
756 	}
757 
758 	fs_flags = tee_svc_storage_conv_oflags(flags);
759 
760 	fd = fops->open(&errno, file, fs_flags);
761 	if (fd < 0) {
762 		res = errno;
763 		goto err;
764 	}
765 	o->fd = fd;
766 
767 	tee_obj_add(utc, o);
768 
769 	res = tee_svc_copy_kaddr_to_uref(obj, o);
770 	if (res != TEE_SUCCESS)
771 		goto oclose;
772 
773 	res = tee_obj_attr_to_binary(o, NULL, &attr_size);
774 	if (res != TEE_SUCCESS)
775 		goto oclose;
776 
777 	e_off = sizeof(struct tee_svc_storage_head) + attr_size;
778 	off = fops->lseek(&errno, fd, e_off, TEE_FS_SEEK_SET);
779 	if (off != e_off) {
780 		res = TEE_ERROR_NO_DATA;
781 		goto oclose;
782 	} else {
783 		res = TEE_SUCCESS;
784 	}
785 
786 	goto exit;
787 
788 oclose:
789 	tee_obj_close(utc, o);
790 	goto exit;
791 
792 rmfile:
793 	fops->unlink(tmpfile);
794 
795 err:
796 	if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT)
797 		res = TEE_ERROR_CORRUPT_OBJECT;
798 	if (res == TEE_ERROR_CORRUPT_OBJECT && file)
799 		fops->unlink(file);
800 	if (fd >= 0)
801 		fops->close(fd);
802 	if (po)
803 		tee_pobj_release(po);
804 	if (o)
805 		free(o);
806 
807 exit:
808 	free(file);
809 	file = NULL;
810 	free(tmpfile);
811 	tmpfile = NULL;
812 
813 	return res;
814 }
815 
816 TEE_Result syscall_storage_obj_del(unsigned long obj)
817 {
818 	TEE_Result res;
819 	struct tee_ta_session *sess;
820 	struct tee_obj *o;
821 	int err;
822 	char *file;
823 	char *dir;
824 	struct user_ta_ctx *utc;
825 	const struct tee_file_operations *fops;
826 
827 	res = tee_ta_get_current_session(&sess);
828 	if (res != TEE_SUCCESS)
829 		return res;
830 	utc = to_user_ta_ctx(sess->ctx);
831 
832 	res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
833 	if (res != TEE_SUCCESS)
834 		return res;
835 
836 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META))
837 		return TEE_ERROR_ACCESS_CONFLICT;
838 
839 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
840 		return TEE_ERROR_BAD_STATE;
841 
842 	file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
843 						o->pobj->obj_id_len, false);
844 	if (file == NULL)
845 		return TEE_ERROR_OUT_OF_MEMORY;
846 
847 	fops = o->pobj->fops;
848 	tee_obj_close(utc, o);
849 
850 	err = fops->access(file, TEE_FS_F_OK);
851 	if (err)
852 		/* file not found */
853 		return TEE_ERROR_STORAGE_NOT_AVAILABLE;
854 
855 	err = fops->unlink(file);
856 	free(file);
857 	if (err)
858 		/* error codes needs better granularity */
859 		return TEE_ERROR_GENERIC;
860 
861 	/* try and remove dir */
862 	dir = tee_svc_storage_create_dirname(sess);
863 	if (dir == NULL)
864 		return TEE_ERROR_OUT_OF_MEMORY;
865 	/* ignore result */
866 	fops->rmdir(dir);
867 	free(dir);
868 
869 	return TEE_SUCCESS;
870 }
871 
872 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id,
873 			size_t object_id_len)
874 {
875 	TEE_Result res;
876 	struct tee_ta_session *sess;
877 	struct tee_obj *o;
878 	struct tee_pobj *po = NULL;
879 	char *new_file = NULL;
880 	char *old_file = NULL;
881 	int err = -1;
882 	struct user_ta_ctx *utc;
883 	const struct tee_file_operations *fops;
884 
885 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
886 		return TEE_ERROR_BAD_PARAMETERS;
887 
888 	res = tee_ta_get_current_session(&sess);
889 	if (res != TEE_SUCCESS)
890 		return res;
891 	utc = to_user_ta_ctx(sess->ctx);
892 
893 	res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
894 	if (res != TEE_SUCCESS)
895 		return res;
896 
897 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
898 		res = TEE_ERROR_BAD_STATE;
899 		goto exit;
900 	}
901 
902 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
903 		res = TEE_ERROR_BAD_STATE;
904 		goto exit;
905 	}
906 
907 	if (o->pobj == NULL || o->pobj->obj_id == NULL) {
908 		res = TEE_ERROR_BAD_STATE;
909 		goto exit;
910 	}
911 
912 	res = tee_mmu_check_access_rights(utc,
913 					TEE_MEMORY_ACCESS_READ |
914 					TEE_MEMORY_ACCESS_ANY_OWNER,
915 					(tee_uaddr_t) object_id, object_id_len);
916 	if (res != TEE_SUCCESS)
917 		goto exit;
918 
919 	res = tee_obj_verify(sess, o);
920 	if (res != TEE_SUCCESS)
921 		goto exit;
922 
923 	/* get new ds name */
924 	new_file = tee_svc_storage_create_filename(sess, object_id,
925 						   object_id_len, false);
926 	if (new_file == NULL) {
927 		res = TEE_ERROR_OUT_OF_MEMORY;
928 		goto exit;
929 	}
930 
931 	old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
932 						   o->pobj->obj_id_len, false);
933 	if (old_file == NULL) {
934 		res = TEE_ERROR_OUT_OF_MEMORY;
935 		goto exit;
936 	}
937 
938 	/* reserve dest name */
939 	fops = o->pobj->fops;
940 	res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
941 			   object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META,
942 			   fops, &po);
943 	if (res != TEE_SUCCESS)
944 		goto exit;
945 
946 	err = fops->access(new_file, TEE_FS_F_OK);
947 	if (err == 0) {
948 		/* file exists */
949 		res = TEE_ERROR_ACCESS_CONFLICT;
950 		goto exit;
951 	}
952 
953 	/* move */
954 	err = fops->rename(old_file, new_file);
955 	if (err) {
956 		/* error codes needs better granularity */
957 		res = TEE_ERROR_GENERIC;
958 		goto exit;
959 	}
960 
961 	res = tee_pobj_rename(o->pobj, object_id, object_id_len);
962 
963 exit:
964 	tee_pobj_release(po);
965 
966 	free(new_file);
967 	free(old_file);
968 
969 	return res;
970 }
971 
972 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum)
973 {
974 	struct tee_storage_enum *e;
975 	struct tee_ta_session *sess;
976 	TEE_Result res;
977 	struct user_ta_ctx *utc;
978 
979 	if (obj_enum == NULL)
980 		return TEE_ERROR_BAD_PARAMETERS;
981 
982 	res = tee_ta_get_current_session(&sess);
983 	if (res != TEE_SUCCESS)
984 		return res;
985 	utc = to_user_ta_ctx(sess->ctx);
986 
987 	e = malloc(sizeof(struct tee_storage_enum));
988 	if (e == NULL)
989 		return TEE_ERROR_OUT_OF_MEMORY;
990 
991 	e->dir = NULL;
992 	e->fops = NULL;
993 	TAILQ_INSERT_TAIL(&utc->storage_enums, e, link);
994 
995 	return tee_svc_copy_kaddr_to_uref(obj_enum, e);
996 }
997 
998 TEE_Result syscall_storage_free_enum(unsigned long obj_enum)
999 {
1000 	struct tee_storage_enum *e;
1001 	TEE_Result res;
1002 	struct tee_ta_session *sess;
1003 	struct user_ta_ctx *utc;
1004 
1005 	res = tee_ta_get_current_session(&sess);
1006 	if (res != TEE_SUCCESS)
1007 		return res;
1008 	utc = to_user_ta_ctx(sess->ctx);
1009 
1010 	res = tee_svc_storage_get_enum(utc,
1011 			tee_svc_uref_to_vaddr(obj_enum), &e);
1012 	if (res != TEE_SUCCESS)
1013 		return res;
1014 
1015 	return tee_svc_close_enum(utc, e);
1016 }
1017 
1018 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum)
1019 {
1020 	struct tee_storage_enum *e;
1021 	TEE_Result res;
1022 	struct tee_ta_session *sess;
1023 
1024 	res = tee_ta_get_current_session(&sess);
1025 	if (res != TEE_SUCCESS)
1026 		return res;
1027 
1028 	res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx),
1029 			tee_svc_uref_to_vaddr(obj_enum), &e);
1030 	if (res != TEE_SUCCESS)
1031 		return res;
1032 
1033 	res = e->fops->closedir(e->dir);
1034 	e->dir = NULL;
1035 	if (res != 0)
1036 		return TEE_ERROR_GENERIC;
1037 
1038 	return TEE_SUCCESS;
1039 }
1040 
1041 static TEE_Result tee_svc_storage_set_enum(char *d_name,
1042 			const struct tee_file_operations *fops,
1043 			struct tee_obj *o)
1044 {
1045 	TEE_Result res;
1046 	uint32_t blen;
1047 	uint32_t hslen;
1048 
1049 	o->info.handleFlags =
1050 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
1051 	o->info.objectUsage = TEE_USAGE_DEFAULT;
1052 
1053 	hslen = strlen(d_name);
1054 	blen = TEE_HS2B_BBUF_SIZE(hslen);
1055 	o->pobj->obj_id = malloc(blen);
1056 	if (!o->pobj->obj_id) {
1057 		res = TEE_ERROR_OUT_OF_MEMORY;
1058 		goto exit;
1059 	}
1060 	tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen);
1061 	o->pobj->obj_id_len = blen;
1062 	o->pobj->fops = fops;
1063 
1064 	res = TEE_SUCCESS;
1065 
1066 exit:
1067 	return res;
1068 
1069 }
1070 
1071 TEE_Result syscall_storage_start_enum(unsigned long obj_enum,
1072 				      unsigned long storage_id)
1073 {
1074 	struct tee_storage_enum *e;
1075 	char *dir;
1076 	TEE_Result res;
1077 	struct tee_ta_session *sess;
1078 	struct tee_fs_dirent *d = NULL;
1079 	struct tee_obj *o = NULL;
1080 	const struct tee_file_operations *fops = file_ops(storage_id);
1081 
1082 	res = tee_ta_get_current_session(&sess);
1083 	if (res != TEE_SUCCESS)
1084 		return res;
1085 
1086 	res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx),
1087 			tee_svc_uref_to_vaddr(obj_enum), &e);
1088 	if (res != TEE_SUCCESS)
1089 		return res;
1090 
1091 	if (!fops)
1092 		return TEE_ERROR_ITEM_NOT_FOUND;
1093 
1094 	dir = tee_svc_storage_create_dirname(sess);
1095 	if (dir == NULL)
1096 		return TEE_ERROR_OUT_OF_MEMORY;
1097 
1098 	e->fops = fops;
1099 	e->dir = fops->opendir(dir);
1100 	free(dir);
1101 	if (e->dir == NULL)
1102 		/* error codes needs better granularity */
1103 		return TEE_ERROR_ITEM_NOT_FOUND;
1104 
1105 	/* verify object */
1106 	o = tee_obj_alloc();
1107 	if (o == NULL) {
1108 		res = TEE_ERROR_OUT_OF_MEMORY;
1109 		goto exit;
1110 	}
1111 
1112 	o->pobj = calloc(1, sizeof(struct tee_pobj));
1113 	if (!o->pobj) {
1114 		res = TEE_ERROR_OUT_OF_MEMORY;
1115 		goto exit;
1116 	}
1117 
1118 	/* object enumeration loop */
1119 	do {
1120 		d = fops->readdir(e->dir);
1121 		if (d) {
1122 			/* allocate obj_id and set object */
1123 			res = tee_svc_storage_set_enum(d->d_name, fops, o);
1124 			if (res != TEE_SUCCESS)
1125 				goto exit;
1126 			res = tee_obj_verify(sess, o);
1127 			if (res != TEE_SUCCESS)
1128 				goto exit;
1129 			/* free obj_id for each iteration */
1130 			free(o->pobj->obj_id);
1131 			/* force obj_id to skip freeing at exit statement */
1132 			o->pobj->obj_id = NULL;
1133 		}
1134 	} while (d);
1135 
1136 	/* re-start */
1137 	res = fops->closedir(e->dir);
1138 	e->dir = NULL;
1139 	if (res != 0) {
1140 		res = TEE_ERROR_GENERIC;
1141 		goto exit;
1142 	}
1143 
1144 	dir = tee_svc_storage_create_dirname(sess);
1145 	if (dir == NULL) {
1146 		res = TEE_ERROR_OUT_OF_MEMORY;
1147 		goto exit;
1148 	}
1149 
1150 	e->dir = fops->opendir(dir);
1151 	free(dir);
1152 
1153 exit:
1154 	if (o) {
1155 		if (o->pobj)
1156 			free(o->pobj->obj_id);
1157 		free(o->pobj);
1158 		tee_obj_free(o);
1159 	}
1160 
1161 	return res;
1162 }
1163 
1164 TEE_Result syscall_storage_next_enum(unsigned long obj_enum,
1165 			TEE_ObjectInfo *info, void *obj_id, uint64_t *len)
1166 {
1167 	struct tee_storage_enum *e;
1168 	struct tee_fs_dirent *d;
1169 	TEE_Result res = TEE_SUCCESS;
1170 	struct tee_ta_session *sess;
1171 	struct tee_obj *o = NULL;
1172 	uint64_t l;
1173 	struct user_ta_ctx *utc;
1174 
1175 	res = tee_ta_get_current_session(&sess);
1176 	if (res != TEE_SUCCESS)
1177 		goto exit;
1178 	utc = to_user_ta_ctx(sess->ctx);
1179 
1180 	res = tee_svc_storage_get_enum(utc,
1181 			tee_svc_uref_to_vaddr(obj_enum), &e);
1182 	if (res != TEE_SUCCESS)
1183 		goto exit;
1184 
1185 	/* check rights of the provided buffers */
1186 	res = tee_mmu_check_access_rights(utc,
1187 					TEE_MEMORY_ACCESS_WRITE |
1188 					TEE_MEMORY_ACCESS_ANY_OWNER,
1189 					(tee_uaddr_t) info,
1190 					sizeof(TEE_ObjectInfo));
1191 	if (res != TEE_SUCCESS)
1192 		goto exit;
1193 
1194 	res = tee_mmu_check_access_rights(utc,
1195 					TEE_MEMORY_ACCESS_WRITE |
1196 					TEE_MEMORY_ACCESS_ANY_OWNER,
1197 					(tee_uaddr_t) obj_id,
1198 					TEE_OBJECT_ID_MAX_LEN);
1199 	if (res != TEE_SUCCESS)
1200 		goto exit;
1201 
1202 	if (!e->fops) {
1203 		res = TEE_ERROR_ITEM_NOT_FOUND;
1204 		goto exit;
1205 	}
1206 
1207 	d = e->fops->readdir(e->dir);
1208 	if (d == NULL) {
1209 		res = TEE_ERROR_ITEM_NOT_FOUND;
1210 		goto exit;
1211 	}
1212 
1213 	o = tee_obj_alloc();
1214 	if (o == NULL) {
1215 		res = TEE_ERROR_OUT_OF_MEMORY;
1216 		goto exit;
1217 	}
1218 
1219 	o->pobj = calloc(1, sizeof(struct tee_pobj));
1220 	if (!o->pobj) {
1221 		res = TEE_ERROR_OUT_OF_MEMORY;
1222 		goto exit;
1223 	}
1224 
1225 	res = tee_svc_storage_set_enum(d->d_name, e->fops, o);
1226 	if (res != TEE_SUCCESS)
1227 		goto exit;
1228 
1229 	res = tee_obj_verify(sess, o);
1230 	if (res != TEE_SUCCESS)
1231 		goto exit;
1232 
1233 	res = tee_svc_storage_read_head(sess, o);
1234 	if (res != TEE_SUCCESS)
1235 		goto exit;
1236 
1237 	memcpy(info, &o->info, sizeof(TEE_ObjectInfo));
1238 	memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len);
1239 
1240 	l = o->pobj->obj_id_len;
1241 	res = tee_svc_copy_to_user(len, &l, sizeof(*len));
1242 
1243 exit:
1244 	if (o) {
1245 		if (o->pobj)
1246 			free(o->pobj->obj_id);
1247 		free(o->pobj);
1248 		tee_obj_free(o);
1249 	}
1250 
1251 	return res;
1252 }
1253 
1254 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len,
1255 			uint64_t *count)
1256 {
1257 	TEE_Result res;
1258 	TEE_Result errno;
1259 	struct tee_ta_session *sess;
1260 	struct tee_obj *o;
1261 	int n_count;
1262 	uint64_t u_count;
1263 	struct user_ta_ctx *utc;
1264 
1265 	res = tee_ta_get_current_session(&sess);
1266 	if (res != TEE_SUCCESS)
1267 		goto exit;
1268 	utc = to_user_ta_ctx(sess->ctx);
1269 
1270 	res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
1271 	if (res != TEE_SUCCESS)
1272 		goto exit;
1273 
1274 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
1275 		res = TEE_ERROR_BAD_STATE;
1276 		goto exit;
1277 	}
1278 
1279 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) {
1280 		res = TEE_ERROR_ACCESS_CONFLICT;
1281 		goto exit;
1282 	}
1283 
1284 	/* check rights of the provided buffer */
1285 	res = tee_mmu_check_access_rights(utc,
1286 					TEE_MEMORY_ACCESS_WRITE |
1287 					TEE_MEMORY_ACCESS_ANY_OWNER,
1288 					(tee_uaddr_t) data, len);
1289 	if (res != TEE_SUCCESS)
1290 		goto exit;
1291 
1292 	n_count = o->pobj->fops->read(&errno, o->fd, data, len);
1293 	if (n_count < 0) {
1294 		res = errno;
1295 		EMSG("Error code=%x\n", (uint32_t)res);
1296 		if (res == TEE_ERROR_CORRUPT_OBJECT) {
1297 			EMSG("Object corrupt\n");
1298 			tee_svc_storage_remove_corrupt_obj(sess, o);
1299 		}
1300 		goto exit;
1301 	}
1302 	u_count = (uint64_t)((n_count < 0) ? 0 : n_count);
1303 
1304 	res = tee_svc_copy_to_user(count, &u_count, sizeof(*count));
1305 
1306 	o->info.dataPosition += u_count;
1307 
1308 exit:
1309 	return res;
1310 }
1311 
1312 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len)
1313 {
1314 	TEE_Result res;
1315 	TEE_Result errno;
1316 	struct tee_ta_session *sess;
1317 	struct tee_obj *o;
1318 	int err;
1319 	struct user_ta_ctx *utc;
1320 
1321 	res = tee_ta_get_current_session(&sess);
1322 	if (res != TEE_SUCCESS)
1323 		goto exit;
1324 	utc = to_user_ta_ctx(sess->ctx);
1325 
1326 	res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
1327 	if (res != TEE_SUCCESS)
1328 		goto exit;
1329 
1330 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
1331 		res = TEE_ERROR_BAD_STATE;
1332 		goto exit;
1333 	}
1334 
1335 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) {
1336 		res = TEE_ERROR_ACCESS_CONFLICT;
1337 		goto exit;
1338 	}
1339 
1340 	/* check rights of the provided buffer */
1341 	res = tee_mmu_check_access_rights(utc,
1342 					TEE_MEMORY_ACCESS_READ |
1343 					TEE_MEMORY_ACCESS_ANY_OWNER,
1344 					(tee_uaddr_t) data, len);
1345 	if (res != TEE_SUCCESS)
1346 		goto exit;
1347 
1348 	err = o->pobj->fops->write(&errno, o->fd, data, len);
1349 	if (err < 0)
1350 		res = errno;
1351 	if (err != (int)len)
1352 		goto exit;
1353 
1354 	o->info.dataPosition += len;
1355 	if (o->info.dataPosition > o->info.dataSize)
1356 		o->info.dataSize = o->info.dataPosition;
1357 
1358 exit:
1359 	return res;
1360 }
1361 
1362 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len)
1363 {
1364 	TEE_Result res;
1365 	TEE_Result errno;
1366 	struct tee_ta_session *sess;
1367 	struct tee_obj *o;
1368 	int err;
1369 	tee_fs_off_t off;
1370 	size_t attr_size;
1371 
1372 	res = tee_ta_get_current_session(&sess);
1373 	if (res != TEE_SUCCESS)
1374 		goto exit;
1375 
1376 	res = tee_obj_get(to_user_ta_ctx(sess->ctx),
1377 			  tee_svc_uref_to_vaddr(obj), &o);
1378 	if (res != TEE_SUCCESS)
1379 		goto exit;
1380 
1381 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
1382 		res = TEE_ERROR_BAD_STATE;
1383 		goto exit;
1384 	}
1385 
1386 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) {
1387 		res = TEE_ERROR_ACCESS_CONFLICT;
1388 		goto exit;
1389 	}
1390 
1391 	res = tee_obj_verify(sess, o);
1392 	if (res != TEE_SUCCESS)
1393 		goto exit;
1394 
1395 	res = tee_obj_attr_to_binary(o, NULL, &attr_size);
1396 	if (res != TEE_SUCCESS)
1397 		goto exit;
1398 
1399 	off = sizeof(struct tee_svc_storage_head) + attr_size;
1400 	err = o->pobj->fops->ftruncate(&errno, o->fd, len + off);
1401 	if (err < 0) {
1402 		res = errno;
1403 		if (res == TEE_ERROR_CORRUPT_OBJECT) {
1404 			EMSG("Object corrupt\n");
1405 			res = tee_svc_storage_remove_corrupt_obj(sess, o);
1406 			if (res != TEE_SUCCESS)
1407 				goto exit;
1408 			res = TEE_ERROR_CORRUPT_OBJECT;
1409 			goto exit;
1410 		} else
1411 			res = TEE_ERROR_GENERIC;
1412 	}
1413 
1414 exit:
1415 	return res;
1416 }
1417 
1418 TEE_Result syscall_storage_obj_seek(unsigned long obj, long offset,
1419 				    unsigned long whence)
1420 {
1421 	TEE_Result res;
1422 	TEE_Result errno;
1423 	struct tee_ta_session *sess;
1424 	struct tee_obj *o;
1425 	int fw;
1426 	tee_fs_off_t off;
1427 	tee_fs_off_t e_off = 0;
1428 	size_t attr_size;
1429 
1430 	res = tee_ta_get_current_session(&sess);
1431 	if (res != TEE_SUCCESS)
1432 		goto exit;
1433 
1434 	res = tee_obj_get(to_user_ta_ctx(sess->ctx),
1435 			  tee_svc_uref_to_vaddr(obj), &o);
1436 	if (res != TEE_SUCCESS)
1437 		goto exit;
1438 
1439 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
1440 		res = TEE_ERROR_BAD_STATE;
1441 		goto exit;
1442 	}
1443 
1444 	res = tee_obj_verify(sess, o);
1445 	if (res != TEE_SUCCESS)
1446 		goto exit;
1447 
1448 	res = tee_obj_attr_to_binary(o, NULL, &attr_size);
1449 	if (res != TEE_SUCCESS)
1450 		goto exit;
1451 
1452 	fw = tee_svc_storage_conv_whence(whence);
1453 
1454 	if (whence == TEE_DATA_SEEK_SET)
1455 		e_off = sizeof(struct tee_svc_storage_head) + attr_size;
1456 
1457 	off = o->pobj->fops->lseek(&errno, o->fd, e_off + offset, fw);
1458 	if (off > -1 && off >= e_off) {
1459 		res = TEE_SUCCESS;
1460 		o->info.dataPosition = off -
1461 			(sizeof(struct tee_svc_storage_head) + attr_size);
1462 	} else {
1463 		res = TEE_ERROR_GENERIC;
1464 		goto exit;
1465 	}
1466 
1467 exit:
1468 	return res;
1469 }
1470 
1471 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc)
1472 {
1473 	struct tee_storage_enum_head *eh = &utc->storage_enums;
1474 
1475 	/* disregard return value */
1476 	while (!TAILQ_EMPTY(eh))
1477 		tee_svc_close_enum(utc, TAILQ_FIRST(eh));
1478 }
1479