2 * Copyright (c) 2014, STMicroelectronics International N.V.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
28 #include <kernel/mutex.h>
29 #include <kernel/tee_misc.h>
30 #include <kernel/tee_ta_manager.h>
31 #include <mm/tee_mmu.h>
33 #include <tee_api_defines_extensions.h>
34 #include <tee_api_defines.h>
35 #include <tee/tee_fs.h>
36 #include <tee/tee_obj.h>
37 #include <tee/tee_pobj.h>
38 #include <tee/tee_svc_cryp.h>
39 #include <tee/tee_svc.h>
40 #include <tee/tee_svc_storage.h>
44 * Returns the appropriate tee_file_operations for the specified storage ID.
45 * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise
48 static const struct tee_file_operations *file_ops(uint32_t storage_id)
52 case TEE_STORAGE_PRIVATE:
53 #if defined(CFG_REE_FS)
55 #elif defined(CFG_RPMB_FS)
57 #elif defined(CFG_SQL_FS)
60 #error At least one filesystem must be enabled.
63 case TEE_STORAGE_PRIVATE_REE:
67 case TEE_STORAGE_PRIVATE_RPMB:
71 case TEE_STORAGE_PRIVATE_SQL:
79 /* SSF (Secure Storage File version 00 */
80 #define TEE_SVC_STORAGE_MAGIC 0x53534600
82 /* Header of GP formated secure storage files */
83 struct tee_svc_storage_head {
95 struct tee_storage_enum {
96 TAILQ_ENTRY(tee_storage_enum) link;
97 struct tee_fs_dir *dir;
98 const struct tee_file_operations *fops;
101 static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc,
103 struct tee_storage_enum **e_out)
105 struct tee_storage_enum *e;
107 TAILQ_FOREACH(e, &utc->storage_enums, link) {
108 if (enum_id == (vaddr_t)e) {
113 return TEE_ERROR_BAD_PARAMETERS;
116 static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc,
117 struct tee_storage_enum *e)
119 if (e == NULL || utc == NULL)
120 return TEE_ERROR_BAD_PARAMETERS;
122 TAILQ_REMOVE(&utc->storage_enums, e, link);
125 e->fops->closedir(e->dir);
135 /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */
136 TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen,
137 struct tee_pobj *po, bool transient)
141 uint32_t hslen = 1 /* Leading slash */
142 + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len)
143 + 1; /* Intermediate slash */
145 /* +1 for the '.' (temporary persistent object) */
150 return TEE_ERROR_SHORT_BUFFER;
153 pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos],
154 sizeof(TEE_UUID), hslen);
160 tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos);
166 TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen,
167 const TEE_UUID *uuid)
170 uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1;
173 return TEE_ERROR_SHORT_BUFFER;
176 tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen);
181 static TEE_Result tee_svc_storage_remove_corrupt_obj(
182 struct tee_ta_session *sess,
185 o->pobj->fops->remove(o->pobj);
186 tee_obj_close(to_user_ta_ctx(sess->ctx), o);
191 static TEE_Result tee_svc_storage_read_head(struct tee_obj *o)
193 TEE_Result res = TEE_SUCCESS;
195 struct tee_svc_storage_head head;
196 const struct tee_file_operations *fops = o->pobj->fops;
200 res = fops->open(o->pobj, &o->fh);
201 if (res != TEE_SUCCESS)
205 bytes = sizeof(struct tee_svc_storage_head);
206 res = fops->read(o->fh, 0, &head, &bytes);
207 if (res != TEE_SUCCESS) {
208 if (res == TEE_ERROR_CORRUPT_OBJECT)
209 EMSG("Head corrupt\n");
213 if (bytes != sizeof(struct tee_svc_storage_head)) {
214 res = TEE_ERROR_BAD_FORMAT;
218 res = tee_obj_set_type(o, head.objectType, head.maxKeySize);
219 if (res != TEE_SUCCESS)
222 o->ds_pos = sizeof(struct tee_svc_storage_head) + head.meta_size;
223 if (head.meta_size) {
224 attr = malloc(head.meta_size);
226 res = TEE_ERROR_OUT_OF_MEMORY;
231 bytes = head.meta_size;
232 res = fops->read(o->fh, sizeof(struct tee_svc_storage_head),
234 if (res != TEE_SUCCESS || bytes != head.meta_size) {
235 res = TEE_ERROR_CORRUPT_OBJECT;
240 res = tee_obj_attr_from_binary(o, attr, head.meta_size);
241 if (res != TEE_SUCCESS)
244 o->info.dataSize = head.ds_size;
245 o->info.keySize = head.keySize;
246 o->info.objectUsage = head.objectUsage;
247 o->info.objectType = head.objectType;
248 o->have_attrs = head.have_attrs;
256 static TEE_Result tee_svc_storage_update_head(struct tee_obj *o,
259 size_t pos = offsetof(struct tee_svc_storage_head, ds_size);
261 return o->pobj->fops->write(o->fh, pos, &ds_size, sizeof(uint32_t));
264 static TEE_Result tee_svc_storage_init_file(struct tee_obj *o,
265 struct tee_obj *attr_o, void *data,
268 TEE_Result res = TEE_SUCCESS;
269 struct tee_svc_storage_head head;
270 const struct tee_file_operations *fops = o->pobj->fops;
272 size_t attr_size = 0;
274 res = fops->create(o->pobj, &o->fh);
275 if (res != TEE_SUCCESS)
279 res = tee_obj_set_type(o, attr_o->info.objectType,
280 attr_o->info.maxKeySize);
281 if (res != TEE_SUCCESS)
283 res = tee_obj_attr_copy_from(o, attr_o);
284 if (res != TEE_SUCCESS)
286 o->have_attrs = attr_o->have_attrs;
287 o->info.objectUsage = attr_o->info.objectUsage;
288 o->info.keySize = attr_o->info.keySize;
289 res = tee_obj_attr_to_binary(o, NULL, &attr_size);
290 if (res != TEE_SUCCESS)
293 attr = malloc(attr_size);
295 res = TEE_ERROR_OUT_OF_MEMORY;
298 res = tee_obj_attr_to_binary(o, attr, &attr_size);
299 if (res != TEE_SUCCESS)
303 res = tee_obj_set_type(o, TEE_TYPE_DATA, 0);
304 if (res != TEE_SUCCESS)
308 o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size;
311 head.magic = TEE_SVC_STORAGE_MAGIC;
312 head.head_size = sizeof(struct tee_svc_storage_head);
313 head.meta_size = attr_size;
315 head.keySize = o->info.keySize;
316 head.maxKeySize = o->info.maxKeySize;
317 head.objectUsage = o->info.objectUsage;
318 head.objectType = o->info.objectType;
319 head.have_attrs = o->have_attrs;
322 res = fops->write(o->fh, 0, &head, sizeof(struct tee_svc_storage_head));
323 if (res != TEE_SUCCESS)
327 res = fops->write(o->fh, sizeof(struct tee_svc_storage_head),
329 if (res != TEE_SUCCESS)
332 /* write init data */
333 o->info.dataSize = len;
335 /* write data to fs if needed */
337 res = fops->write(o->fh, o->ds_pos, data, len);
346 TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
347 size_t object_id_len, unsigned long flags,
351 struct tee_ta_session *sess;
352 struct tee_obj *o = NULL;
354 struct tee_pobj *po = NULL;
355 struct user_ta_ctx *utc;
356 const struct tee_file_operations *fops = file_ops(storage_id);
360 res = TEE_ERROR_ITEM_NOT_FOUND;
364 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) {
365 res = TEE_ERROR_BAD_PARAMETERS;
369 res = tee_ta_get_current_session(&sess);
370 if (res != TEE_SUCCESS)
372 utc = to_user_ta_ctx(sess->ctx);
374 res = tee_mmu_check_access_rights(utc,
375 TEE_MEMORY_ACCESS_READ |
376 TEE_MEMORY_ACCESS_ANY_OWNER,
379 if (res != TEE_SUCCESS)
382 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
383 object_id_len, flags, false, fops, &po);
384 if (res != TEE_SUCCESS)
389 tee_pobj_release(po);
390 res = TEE_ERROR_OUT_OF_MEMORY;
394 o->info.handleFlags =
395 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
400 res = tee_svc_storage_read_head(o);
401 if (res != TEE_SUCCESS) {
402 if (res == TEE_ERROR_CORRUPT_OBJECT) {
403 EMSG("Object corrupt");
409 res = tee_svc_copy_kaddr_to_uref(obj, o);
410 if (res != TEE_SUCCESS)
413 res = tee_obj_attr_to_binary(o, NULL, &attr_size);
414 if (res != TEE_SUCCESS)
420 tee_obj_close(utc, o);
424 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT)
425 res = TEE_ERROR_CORRUPT_OBJECT;
426 if (res == TEE_ERROR_CORRUPT_OBJECT && o)
427 tee_svc_storage_remove_corrupt_obj(sess, o);
435 TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
436 size_t object_id_len, unsigned long flags,
437 unsigned long attr, void *data, size_t len,
441 struct tee_ta_session *sess;
442 struct tee_obj *o = NULL;
443 struct tee_obj *attr_o = NULL;
444 struct tee_pobj *po = NULL;
445 struct user_ta_ctx *utc;
446 const struct tee_file_operations *fops = file_ops(storage_id);
450 return TEE_ERROR_ITEM_NOT_FOUND;
452 if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
453 return TEE_ERROR_BAD_PARAMETERS;
455 res = tee_ta_get_current_session(&sess);
456 if (res != TEE_SUCCESS)
458 utc = to_user_ta_ctx(sess->ctx);
460 res = tee_mmu_check_access_rights(utc,
461 TEE_MEMORY_ACCESS_READ |
462 TEE_MEMORY_ACCESS_ANY_OWNER,
465 if (res != TEE_SUCCESS)
468 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
469 object_id_len, flags, true, fops, &po);
470 if (res != TEE_SUCCESS)
473 /* check rights of the provided buffer */
475 res = tee_mmu_check_access_rights(utc,
476 TEE_MEMORY_ACCESS_READ |
477 TEE_MEMORY_ACCESS_ANY_OWNER,
478 (uaddr_t) data, len);
480 if (res != TEE_SUCCESS)
486 res = TEE_ERROR_OUT_OF_MEMORY;
490 o->info.handleFlags =
491 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
495 if (attr != TEE_HANDLE_NULL) {
496 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(attr),
498 if (res != TEE_SUCCESS)
502 res = tee_svc_storage_init_file(o, attr_o, data, len);
503 if (res != TEE_SUCCESS)
506 /* rename temporary persistent object filename */
507 po->temporary = false;
508 res = fops->rename(po, NULL, !!(flags & TEE_DATA_FLAG_OVERWRITE));
509 if (res != TEE_SUCCESS)
512 res = fops->open(po, &o->fh);
513 if (res != TEE_SUCCESS)
518 res = tee_svc_copy_kaddr_to_uref(obj, o);
519 if (res != TEE_SUCCESS)
522 res = tee_obj_attr_to_binary(o, NULL, &attr_size);
523 if (res != TEE_SUCCESS)
529 tee_obj_close(utc, o);
536 if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT)
537 res = TEE_ERROR_CORRUPT_OBJECT;
538 if (res == TEE_ERROR_CORRUPT_OBJECT && po)
543 tee_pobj_release(po);
549 TEE_Result syscall_storage_obj_del(unsigned long obj)
552 struct tee_ta_session *sess;
554 struct user_ta_ctx *utc;
556 res = tee_ta_get_current_session(&sess);
557 if (res != TEE_SUCCESS)
559 utc = to_user_ta_ctx(sess->ctx);
561 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
562 if (res != TEE_SUCCESS)
565 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META))
566 return TEE_ERROR_ACCESS_CONFLICT;
568 if (o->pobj == NULL || o->pobj->obj_id == NULL)
569 return TEE_ERROR_BAD_STATE;
571 res = o->pobj->fops->remove(o->pobj);
572 tee_obj_close(utc, o);
577 TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id,
578 size_t object_id_len)
581 struct tee_ta_session *sess;
583 struct tee_pobj *po = NULL;
584 char *new_file = NULL;
585 char *old_file = NULL;
586 struct user_ta_ctx *utc;
587 const struct tee_file_operations *fops;
589 if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
590 return TEE_ERROR_BAD_PARAMETERS;
592 res = tee_ta_get_current_session(&sess);
593 if (res != TEE_SUCCESS)
595 utc = to_user_ta_ctx(sess->ctx);
597 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
598 if (res != TEE_SUCCESS)
601 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
602 res = TEE_ERROR_BAD_STATE;
606 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
607 res = TEE_ERROR_BAD_STATE;
611 if (o->pobj == NULL || o->pobj->obj_id == NULL) {
612 res = TEE_ERROR_BAD_STATE;
616 res = tee_mmu_check_access_rights(utc,
617 TEE_MEMORY_ACCESS_READ |
618 TEE_MEMORY_ACCESS_ANY_OWNER,
619 (uaddr_t) object_id, object_id_len);
620 if (res != TEE_SUCCESS)
623 /* reserve dest name */
624 fops = o->pobj->fops;
625 res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
626 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META,
628 if (res != TEE_SUCCESS)
632 res = fops->rename(o->pobj, po, false /* no overwrite */);
633 if (res == TEE_ERROR_GENERIC)
636 res = tee_pobj_rename(o->pobj, object_id, object_id_len);
639 tee_pobj_release(po);
647 TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum)
649 struct tee_storage_enum *e;
650 struct tee_ta_session *sess;
652 struct user_ta_ctx *utc;
654 if (obj_enum == NULL)
655 return TEE_ERROR_BAD_PARAMETERS;
657 res = tee_ta_get_current_session(&sess);
658 if (res != TEE_SUCCESS)
660 utc = to_user_ta_ctx(sess->ctx);
662 e = malloc(sizeof(struct tee_storage_enum));
664 return TEE_ERROR_OUT_OF_MEMORY;
668 TAILQ_INSERT_TAIL(&utc->storage_enums, e, link);
670 return tee_svc_copy_kaddr_to_uref(obj_enum, e);
673 TEE_Result syscall_storage_free_enum(unsigned long obj_enum)
675 struct tee_storage_enum *e;
677 struct tee_ta_session *sess;
678 struct user_ta_ctx *utc;
680 res = tee_ta_get_current_session(&sess);
681 if (res != TEE_SUCCESS)
683 utc = to_user_ta_ctx(sess->ctx);
685 res = tee_svc_storage_get_enum(utc,
686 tee_svc_uref_to_vaddr(obj_enum), &e);
687 if (res != TEE_SUCCESS)
690 return tee_svc_close_enum(utc, e);
693 TEE_Result syscall_storage_reset_enum(unsigned long obj_enum)
695 struct tee_storage_enum *e;
697 struct tee_ta_session *sess;
699 res = tee_ta_get_current_session(&sess);
700 if (res != TEE_SUCCESS)
703 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx),
704 tee_svc_uref_to_vaddr(obj_enum), &e);
705 if (res != TEE_SUCCESS)
709 e->fops->closedir(e->dir);
718 static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d,
719 const struct tee_file_operations *fops,
722 o->info.handleFlags =
723 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
724 o->info.objectUsage = TEE_USAGE_DEFAULT;
726 o->pobj->obj_id = malloc(d->oidlen);
727 if (!o->pobj->obj_id)
728 return TEE_ERROR_OUT_OF_MEMORY;
730 memcpy(o->pobj->obj_id, d->oid, d->oidlen);
731 o->pobj->obj_id_len = d->oidlen;
732 o->pobj->fops = fops;
737 TEE_Result syscall_storage_start_enum(unsigned long obj_enum,
738 unsigned long storage_id)
740 struct tee_storage_enum *e;
742 struct tee_ta_session *sess;
743 const struct tee_file_operations *fops = file_ops(storage_id);
745 res = tee_ta_get_current_session(&sess);
746 if (res != TEE_SUCCESS)
749 res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx),
750 tee_svc_uref_to_vaddr(obj_enum), &e);
751 if (res != TEE_SUCCESS)
755 return TEE_ERROR_ITEM_NOT_FOUND;
759 return fops->opendir(&sess->ctx->uuid, &e->dir);
762 TEE_Result syscall_storage_next_enum(unsigned long obj_enum,
763 TEE_ObjectInfo *info, void *obj_id, uint64_t *len)
765 struct tee_storage_enum *e;
766 struct tee_fs_dirent *d;
767 TEE_Result res = TEE_SUCCESS;
768 struct tee_ta_session *sess;
769 struct tee_obj *o = NULL;
771 struct user_ta_ctx *utc;
773 res = tee_ta_get_current_session(&sess);
774 if (res != TEE_SUCCESS)
776 utc = to_user_ta_ctx(sess->ctx);
778 res = tee_svc_storage_get_enum(utc,
779 tee_svc_uref_to_vaddr(obj_enum), &e);
780 if (res != TEE_SUCCESS)
783 /* check rights of the provided buffers */
784 res = tee_mmu_check_access_rights(utc,
785 TEE_MEMORY_ACCESS_WRITE |
786 TEE_MEMORY_ACCESS_ANY_OWNER,
788 sizeof(TEE_ObjectInfo));
789 if (res != TEE_SUCCESS)
792 res = tee_mmu_check_access_rights(utc,
793 TEE_MEMORY_ACCESS_WRITE |
794 TEE_MEMORY_ACCESS_ANY_OWNER,
796 TEE_OBJECT_ID_MAX_LEN);
797 if (res != TEE_SUCCESS)
801 res = TEE_ERROR_ITEM_NOT_FOUND;
805 res = e->fops->readdir(e->dir, &d);
806 if (res != TEE_SUCCESS)
811 res = TEE_ERROR_OUT_OF_MEMORY;
814 o->flags = TEE_DATA_FLAG_SHARE_READ;
816 o->pobj = calloc(1, sizeof(struct tee_pobj));
818 res = TEE_ERROR_OUT_OF_MEMORY;
822 o->pobj->uuid = sess->ctx->uuid;
823 res = tee_svc_storage_set_enum(d, e->fops, o);
824 if (res != TEE_SUCCESS)
827 res = tee_svc_storage_read_head(o);
828 if (res != TEE_SUCCESS)
831 memcpy(info, &o->info, sizeof(TEE_ObjectInfo));
832 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len);
834 l = o->pobj->obj_id_len;
835 res = tee_svc_copy_to_user(len, &l, sizeof(*len));
840 o->pobj->fops->close(&o->fh);
841 free(o->pobj->obj_id);
850 TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len,
854 struct tee_ta_session *sess;
857 struct user_ta_ctx *utc;
860 res = tee_ta_get_current_session(&sess);
861 if (res != TEE_SUCCESS)
863 utc = to_user_ta_ctx(sess->ctx);
865 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
866 if (res != TEE_SUCCESS)
869 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
870 res = TEE_ERROR_BAD_STATE;
874 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) {
875 res = TEE_ERROR_ACCESS_CONFLICT;
879 /* check rights of the provided buffer */
880 res = tee_mmu_check_access_rights(utc,
881 TEE_MEMORY_ACCESS_WRITE |
882 TEE_MEMORY_ACCESS_ANY_OWNER,
883 (uaddr_t) data, len);
884 if (res != TEE_SUCCESS)
888 res = o->pobj->fops->read(o->fh, o->ds_pos + o->info.dataPosition,
890 if (res != TEE_SUCCESS) {
891 EMSG("Error code=%x\n", (uint32_t)res);
892 if (res == TEE_ERROR_CORRUPT_OBJECT) {
893 EMSG("Object corrupt\n");
894 tee_svc_storage_remove_corrupt_obj(sess, o);
899 o->info.dataPosition += bytes;
902 res = tee_svc_copy_to_user(count, &u_count, sizeof(*count));
907 TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len)
910 struct tee_ta_session *sess;
912 struct user_ta_ctx *utc;
914 res = tee_ta_get_current_session(&sess);
915 if (res != TEE_SUCCESS)
917 utc = to_user_ta_ctx(sess->ctx);
919 res = tee_obj_get(utc, tee_svc_uref_to_vaddr(obj), &o);
920 if (res != TEE_SUCCESS)
923 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
924 res = TEE_ERROR_BAD_STATE;
928 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) {
929 res = TEE_ERROR_ACCESS_CONFLICT;
933 /* check rights of the provided buffer */
934 res = tee_mmu_check_access_rights(utc,
935 TEE_MEMORY_ACCESS_READ |
936 TEE_MEMORY_ACCESS_ANY_OWNER,
937 (uaddr_t) data, len);
938 if (res != TEE_SUCCESS)
941 res = o->pobj->fops->write(o->fh, o->ds_pos + o->info.dataPosition,
943 if (res != TEE_SUCCESS)
946 o->info.dataPosition += len;
947 if (o->info.dataPosition > o->info.dataSize) {
948 res = tee_svc_storage_update_head(o, o->info.dataPosition);
949 if (res != TEE_SUCCESS)
951 o->info.dataSize = o->info.dataPosition;
958 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len)
961 struct tee_ta_session *sess;
966 res = tee_ta_get_current_session(&sess);
967 if (res != TEE_SUCCESS)
970 res = tee_obj_get(to_user_ta_ctx(sess->ctx),
971 tee_svc_uref_to_vaddr(obj), &o);
972 if (res != TEE_SUCCESS)
975 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
976 res = TEE_ERROR_BAD_STATE;
980 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) {
981 res = TEE_ERROR_ACCESS_CONFLICT;
985 res = tee_obj_attr_to_binary(o, NULL, &attr_size);
986 if (res != TEE_SUCCESS)
989 off = sizeof(struct tee_svc_storage_head) + attr_size;
990 res = o->pobj->fops->truncate(o->fh, len + off);
991 if (res != TEE_SUCCESS) {
992 if (res == TEE_ERROR_CORRUPT_OBJECT) {
993 EMSG("Object corrupt\n");
994 res = tee_svc_storage_remove_corrupt_obj(sess, o);
995 if (res != TEE_SUCCESS)
997 res = TEE_ERROR_CORRUPT_OBJECT;
1000 res = TEE_ERROR_GENERIC;
1007 TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset,
1008 unsigned long whence)
1011 struct tee_ta_session *sess;
1014 tee_fs_off_t new_pos;
1016 res = tee_ta_get_current_session(&sess);
1017 if (res != TEE_SUCCESS)
1020 res = tee_obj_get(to_user_ta_ctx(sess->ctx),
1021 tee_svc_uref_to_vaddr(obj), &o);
1022 if (res != TEE_SUCCESS)
1025 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT))
1026 return TEE_ERROR_BAD_STATE;
1028 res = tee_obj_attr_to_binary(o, NULL, &attr_size);
1029 if (res != TEE_SUCCESS)
1033 case TEE_DATA_SEEK_SET:
1036 case TEE_DATA_SEEK_CUR:
1037 new_pos = o->info.dataPosition + offset;
1039 case TEE_DATA_SEEK_END:
1040 new_pos = o->info.dataSize + offset;
1043 return TEE_ERROR_BAD_PARAMETERS;
1049 if (new_pos > TEE_DATA_MAX_POSITION) {
1050 EMSG("Position is beyond TEE_DATA_MAX_POSITION");
1051 return TEE_ERROR_BAD_PARAMETERS;
1054 o->info.dataPosition = new_pos;
1059 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc)
1061 struct tee_storage_enum_head *eh = &utc->storage_enums;
1063 /* disregard return value */
1064 while (!TAILQ_EMPTY(eh))
1065 tee_svc_close_enum(utc, TAILQ_FIRST(eh));