diff options
author | r.tyminski <r.tyminski@partner.samsung.com> | 2017-06-05 12:44:25 +0200 |
---|---|---|
committer | r.tyminski <r.tyminski@partner.samsung.com> | 2017-06-05 12:44:25 +0200 |
commit | 146aec115cd05a164a88e6d7b07435c57a33817f (patch) | |
tree | d8099075c92576b1928069af274f9b833aca996e /core/tee/tee_svc_storage.c | |
parent | f9a43781767007462965b21f3f518c4cfc0744c7 (diff) | |
download | tef-optee_os-146aec115cd05a164a88e6d7b07435c57a33817f.tar.gz tef-optee_os-146aec115cd05a164a88e6d7b07435c57a33817f.tar.bz2 tef-optee_os-146aec115cd05a164a88e6d7b07435c57a33817f.zip |
Update from upstream to 2.4.0 versionupstream/2.4.0upstream
Change-Id: I2b3a30f20684d6629fe379d9cd7895aff759c301
Diffstat (limited to 'core/tee/tee_svc_storage.c')
-rw-r--r-- | core/tee/tee_svc_storage.c | 346 |
1 files changed, 102 insertions, 244 deletions
diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c index 916ddca..d852be1 100644 --- a/core/tee/tee_svc_storage.c +++ b/core/tee/tee_svc_storage.c @@ -32,7 +32,6 @@ #include <string.h> #include <tee_api_defines_extensions.h> #include <tee_api_defines.h> -#include <tee/tee_fs_defs.h> #include <tee/tee_fs.h> #include <tee/tee_obj.h> #include <tee/tee_pobj.h> @@ -99,12 +98,6 @@ struct tee_storage_enum { const struct tee_file_operations *fops; }; -/* - * Protect TA storage directory: avoid race conditions between (create - * directory + create file) and (remove directory) - */ -static struct mutex ta_dir_mutex = MUTEX_INITIALIZER; - static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, uint32_t enum_id, struct tee_storage_enum **e_out) @@ -140,114 +133,77 @@ static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, } /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ -char *tee_svc_storage_create_filename(struct tee_ta_session *sess, - void *object_id, - uint32_t object_id_len, - bool transient) +TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen, + struct tee_pobj *po, bool transient) { - uint8_t *file; + uint8_t *file = buf; uint32_t pos = 0; uint32_t hslen = 1 /* Leading slash */ - + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) + + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) + 1; /* Intermediate slash */ /* +1 for the '.' (temporary persistent object) */ if (transient) hslen++; - file = malloc(hslen); - if (!file) - return NULL; + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; file[pos++] = '/'; - pos += tee_b2hs((uint8_t *)&sess->ctx->uuid, &file[pos], + pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], sizeof(TEE_UUID), hslen); file[pos++] = '/'; if (transient) file[pos++] = '.'; - tee_b2hs(object_id, file + pos, object_id_len, hslen - pos); + tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); - return (char *)file; + return TEE_SUCCESS; } /* "/TA_uuid" */ -char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) +TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen, + const TEE_UUID *uuid) { - uint8_t *dir; + uint8_t *dir = buf; uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; - dir = malloc(hslen); - if (!dir) - return NULL; + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; dir[0] = '/'; - tee_b2hs((uint8_t *)&sess->ctx->uuid, dir + 1, sizeof(TEE_UUID), - hslen); + tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); - return (char *)dir; + return TEE_SUCCESS; } static TEE_Result tee_svc_storage_remove_corrupt_obj( struct tee_ta_session *sess, struct tee_obj *o) { - TEE_Result res; - char *file = NULL; - const struct tee_file_operations *fops = o->pobj->fops; - - file = tee_svc_storage_create_filename(sess, - o->pobj->obj_id, - o->pobj->obj_id_len, - false); - if (file == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - + o->pobj->fops->remove(o->pobj); tee_obj_close(to_user_ta_ctx(sess->ctx), o); - fops->remove(file); - free(file); - res = TEE_SUCCESS; - -exit: - return res; + return TEE_SUCCESS; } -static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, - struct tee_obj *o) +static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) { TEE_Result res = TEE_SUCCESS; size_t bytes; struct tee_svc_storage_head head; - char *file = NULL; - const struct tee_file_operations *fops; + const struct tee_file_operations *fops = o->pobj->fops; void *attr = NULL; - if (o == NULL || o->pobj == NULL) - return TEE_ERROR_BAD_PARAMETERS; - - fops = o->pobj->fops; - - file = tee_svc_storage_create_filename(sess, - o->pobj->obj_id, - o->pobj->obj_id_len, - false); - if (file == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - assert(!o->fh); - res = fops->open(file, &o->fh); + res = fops->open(o->pobj, &o->fh); if (res != TEE_SUCCESS) goto exit; /* read head */ bytes = sizeof(struct tee_svc_storage_head); - res = fops->read(o->fh, &head, &bytes); + res = fops->read(o->fh, 0, &head, &bytes); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) EMSG("Head corrupt\n"); @@ -263,6 +219,7 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, if (res != TEE_SUCCESS) goto exit; + o->ds_pos = sizeof(struct tee_svc_storage_head) + head.meta_size; if (head.meta_size) { attr = malloc(head.meta_size); if (!attr) { @@ -272,7 +229,8 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, /* read meta */ bytes = head.meta_size; - res = fops->read(o->fh, attr, &bytes); + res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), + attr, &bytes); if (res != TEE_SUCCESS || bytes != head.meta_size) { res = TEE_ERROR_CORRUPT_OBJECT; goto exit; @@ -291,7 +249,6 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, exit: free(attr); - free(file); return res; } @@ -299,63 +256,22 @@ exit: static TEE_Result tee_svc_storage_update_head(struct tee_obj *o, uint32_t ds_size) { - TEE_Result res; - const struct tee_file_operations *fops; - int32_t old_off; + size_t pos = offsetof(struct tee_svc_storage_head, ds_size); - fops = o->pobj->fops; - - /* save original offset */ - res = fops->seek(o->fh, 0, TEE_DATA_SEEK_CUR, &old_off); - if (res != TEE_SUCCESS) - return res; - - /* update head.ds_size */ - res = fops->seek(o->fh, offsetof(struct tee_svc_storage_head, - ds_size), TEE_DATA_SEEK_SET, NULL); - if (res != TEE_SUCCESS) - return res; - - res = fops->write(o->fh, &ds_size, sizeof(uint32_t)); - if (res != TEE_SUCCESS) - return res; - - /* restore original offset */ - res = fops->seek(o->fh, old_off, TEE_DATA_SEEK_SET, NULL); - return res; + return o->pobj->fops->write(o->fh, pos, &ds_size, sizeof(uint32_t)); } -static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, - struct tee_obj *o, +static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, struct tee_obj *attr_o, void *data, uint32_t len) { TEE_Result res = TEE_SUCCESS; struct tee_svc_storage_head head; - char *tmpfile = NULL; - const struct tee_file_operations *fops; + const struct tee_file_operations *fops = o->pobj->fops; void *attr = NULL; size_t attr_size = 0; - if (o == NULL || o->pobj == NULL) - return TEE_ERROR_BAD_PARAMETERS; - - fops = o->pobj->fops; - - /* create temporary persistent object filename */ - tmpfile = tee_svc_storage_create_filename(sess, - o->pobj->obj_id, - o->pobj->obj_id_len, - true); - - if (tmpfile == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - - mutex_lock(&ta_dir_mutex); - res = fops->create(tmpfile, &o->fh); - mutex_unlock(&ta_dir_mutex); + res = fops->create(o->pobj, &o->fh); if (res != TEE_SUCCESS) goto exit; @@ -389,6 +305,8 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, goto exit; } + o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; + /* write head */ head.magic = TEE_SVC_STORAGE_MAGIC; head.head_size = sizeof(struct tee_svc_storage_head); @@ -401,12 +319,13 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, head.have_attrs = o->have_attrs; /* write head */ - res = fops->write(o->fh, &head, sizeof(struct tee_svc_storage_head)); + res = fops->write(o->fh, 0, &head, sizeof(struct tee_svc_storage_head)); if (res != TEE_SUCCESS) goto exit; /* write meta */ - res = fops->write(o->fh, attr, attr_size); + res = fops->write(o->fh, sizeof(struct tee_svc_storage_head), + attr, attr_size); if (res != TEE_SUCCESS) goto exit; @@ -415,11 +334,10 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, /* write data to fs if needed */ if (data && len) - res = fops->write(o->fh, data, len); + res = fops->write(o->fh, o->ds_pos, data, len); exit: free(attr); - free(tmpfile); fops->close(&o->fh); return res; @@ -462,7 +380,7 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, goto err; res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, - object_id_len, flags, fops, &po); + object_id_len, flags, false, fops, &po); if (res != TEE_SUCCESS) goto err; @@ -479,7 +397,7 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, o->pobj = po; tee_obj_add(utc, o); - res = tee_svc_storage_read_head(sess, o); + res = tee_svc_storage_read_head(o); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); @@ -496,11 +414,6 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, if (res != TEE_SUCCESS) goto oclose; - res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, - TEE_DATA_SEEK_SET, NULL); - if (res != TEE_SUCCESS) - goto err; - goto exit; oclose: @@ -528,9 +441,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, struct tee_ta_session *sess; struct tee_obj *o = NULL; struct tee_obj *attr_o = NULL; - char *file = NULL; struct tee_pobj *po = NULL; - char *tmpfile = NULL; struct user_ta_ctx *utc; const struct tee_file_operations *fops = file_ops(storage_id); size_t attr_size; @@ -555,7 +466,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, goto err; res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, - object_id_len, flags, fops, &po); + object_id_len, flags, true, fops, &po); if (res != TEE_SUCCESS) goto err; @@ -588,33 +499,17 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, goto err; } - res = tee_svc_storage_init_file(sess, o, attr_o, data, len); + res = tee_svc_storage_init_file(o, attr_o, data, len); if (res != TEE_SUCCESS) goto err; - /* create persistent object filename */ - file = tee_svc_storage_create_filename(sess, object_id, - object_id_len, false); - if (file == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto err; - } - - /* create temporary persistent object filename */ - tmpfile = tee_svc_storage_create_filename(sess, object_id, - object_id_len, - true); - if (tmpfile == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto err; - } - /* rename temporary persistent object filename */ - res = fops->rename(tmpfile, file, !!(flags & TEE_DATA_FLAG_OVERWRITE)); + po->temporary = false; + res = fops->rename(po, NULL, !!(flags & TEE_DATA_FLAG_OVERWRITE)); if (res != TEE_SUCCESS) goto rmfile; - res = fops->open(file, &o->fh); + res = fops->open(po, &o->fh); if (res != TEE_SUCCESS) goto err; @@ -628,35 +523,26 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, if (res != TEE_SUCCESS) goto oclose; - res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size, - TEE_DATA_SEEK_SET, NULL); - if (res != TEE_SUCCESS) - goto oclose; - - goto exit; + return TEE_SUCCESS; oclose: tee_obj_close(utc, o); - goto exit; + return res; rmfile: - fops->remove(tmpfile); + fops->remove(po); err: if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) res = TEE_ERROR_CORRUPT_OBJECT; - if (res == TEE_ERROR_CORRUPT_OBJECT && file) - fops->remove(file); + if (res == TEE_ERROR_CORRUPT_OBJECT && po) + fops->remove(po); if (o) fops->close(&o->fh); if (po) tee_pobj_release(po); free(o); -exit: - free(file); - free(tmpfile); - return res; } @@ -665,9 +551,7 @@ TEE_Result syscall_storage_obj_del(unsigned long obj) TEE_Result res; struct tee_ta_session *sess; struct tee_obj *o; - char *file; struct user_ta_ctx *utc; - const struct tee_file_operations *fops; res = tee_ta_get_current_session(&sess); if (res != TEE_SUCCESS) @@ -684,16 +568,9 @@ TEE_Result syscall_storage_obj_del(unsigned long obj) if (o->pobj == NULL || o->pobj->obj_id == NULL) return TEE_ERROR_BAD_STATE; - file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, - o->pobj->obj_id_len, false); - if (file == NULL) - return TEE_ERROR_OUT_OF_MEMORY; - - fops = o->pobj->fops; + res = o->pobj->fops->remove(o->pobj); tee_obj_close(utc, o); - res = fops->remove(file); - free(file); return res; } @@ -743,31 +620,16 @@ TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, if (res != TEE_SUCCESS) goto exit; - /* get new ds name */ - new_file = tee_svc_storage_create_filename(sess, object_id, - object_id_len, false); - if (new_file == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - - old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id, - o->pobj->obj_id_len, false); - if (old_file == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - /* reserve dest name */ fops = o->pobj->fops; res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, - fops, &po); + false, fops, &po); if (res != TEE_SUCCESS) goto exit; /* move */ - res = fops->rename(old_file, new_file, false /* no overwrite */); + res = fops->rename(o->pobj, po, false /* no overwrite */); if (res == TEE_ERROR_GENERIC) goto exit; @@ -843,48 +705,39 @@ TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) if (res != TEE_SUCCESS) return res; - e->fops->closedir(e->dir); - e->fops = NULL; - e->dir = NULL; + if (e->fops) { + e->fops->closedir(e->dir); + e->fops = NULL; + e->dir = NULL; + } + assert(!e->dir); return TEE_SUCCESS; } -static TEE_Result tee_svc_storage_set_enum(char *d_name, +static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d, const struct tee_file_operations *fops, struct tee_obj *o) { - TEE_Result res; - uint32_t blen; - uint32_t hslen; - o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; o->info.objectUsage = TEE_USAGE_DEFAULT; - hslen = strlen(d_name); - blen = TEE_HS2B_BBUF_SIZE(hslen); - o->pobj->obj_id = malloc(blen); - if (!o->pobj->obj_id) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen); - o->pobj->obj_id_len = blen; - o->pobj->fops = fops; - - res = TEE_SUCCESS; + o->pobj->obj_id = malloc(d->oidlen); + if (!o->pobj->obj_id) + return TEE_ERROR_OUT_OF_MEMORY; -exit: - return res; + memcpy(o->pobj->obj_id, d->oid, d->oidlen); + o->pobj->obj_id_len = d->oidlen; + o->pobj->fops = fops; + return TEE_SUCCESS; } TEE_Result syscall_storage_start_enum(unsigned long obj_enum, unsigned long storage_id) { struct tee_storage_enum *e; - char *dir; TEE_Result res; struct tee_ta_session *sess; const struct tee_file_operations *fops = file_ops(storage_id); @@ -902,17 +755,8 @@ TEE_Result syscall_storage_start_enum(unsigned long obj_enum, return TEE_ERROR_ITEM_NOT_FOUND; e->fops = fops; - dir = tee_svc_storage_create_dirname(sess); - if (dir == NULL) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto exit; - } - assert(!e->dir); - res = fops->opendir(dir, &e->dir); - free(dir); -exit: - return res; + return fops->opendir(&sess->ctx->uuid, &e->dir); } TEE_Result syscall_storage_next_enum(unsigned long obj_enum, @@ -975,11 +819,12 @@ TEE_Result syscall_storage_next_enum(unsigned long obj_enum, goto exit; } - res = tee_svc_storage_set_enum(d->d_name, e->fops, o); + o->pobj->uuid = sess->ctx->uuid; + res = tee_svc_storage_set_enum(d, e->fops, o); if (res != TEE_SUCCESS) goto exit; - res = tee_svc_storage_read_head(sess, o); + res = tee_svc_storage_read_head(o); if (res != TEE_SUCCESS) goto exit; @@ -1040,7 +885,8 @@ TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, goto exit; bytes = len; - res = o->pobj->fops->read(o->fh, data, &bytes); + res = o->pobj->fops->read(o->fh, o->ds_pos + o->info.dataPosition, + data, &bytes); if (res != TEE_SUCCESS) { EMSG("Error code=%x\n", (uint32_t)res); if (res == TEE_ERROR_CORRUPT_OBJECT) { @@ -1092,7 +938,8 @@ TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) if (res != TEE_SUCCESS) goto exit; - res = o->pobj->fops->write(o->fh, data, len); + res = o->pobj->fops->write(o->fh, o->ds_pos + o->info.dataPosition, + data, len); if (res != TEE_SUCCESS) goto exit; @@ -1163,39 +1010,50 @@ TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, TEE_Result res; struct tee_ta_session *sess; struct tee_obj *o; - int32_t off; size_t attr_size; + tee_fs_off_t new_pos; res = tee_ta_get_current_session(&sess); if (res != TEE_SUCCESS) - goto exit; + return res; res = tee_obj_get(to_user_ta_ctx(sess->ctx), tee_svc_uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) - goto exit; + return res; - if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { - res = TEE_ERROR_BAD_STATE; - goto exit; - } + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) + return TEE_ERROR_BAD_STATE; res = tee_obj_attr_to_binary(o, NULL, &attr_size); if (res != TEE_SUCCESS) - goto exit; + return res; - off = offset; - if (whence == TEE_DATA_SEEK_SET) - off += sizeof(struct tee_svc_storage_head) + attr_size; + switch (whence) { + case TEE_DATA_SEEK_SET: + new_pos = offset; + break; + case TEE_DATA_SEEK_CUR: + new_pos = o->info.dataPosition + offset; + break; + case TEE_DATA_SEEK_END: + new_pos = o->info.dataSize + offset; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } - res = o->pobj->fops->seek(o->fh, off, whence, &off); - if (res != TEE_SUCCESS) - goto exit; - o->info.dataPosition = off - (sizeof(struct tee_svc_storage_head) + - attr_size); + if (new_pos < 0) + new_pos = 0; -exit: - return res; + if (new_pos > TEE_DATA_MAX_POSITION) { + EMSG("Position is beyond TEE_DATA_MAX_POSITION"); + return TEE_ERROR_BAD_PARAMETERS; + } + + o->info.dataPosition = new_pos; + + return TEE_SUCCESS; } void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) |