summaryrefslogtreecommitdiff
path: root/core/tee/tee_ree_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/tee/tee_ree_fs.c')
-rw-r--r--core/tee/tee_ree_fs.c706
1 files changed, 207 insertions, 499 deletions
diff --git a/core/tee/tee_ree_fs.c b/core/tee/tee_ree_fs.c
index 7a82acb..544ed3e 100644
--- a/core/tee/tee_ree_fs.c
+++ b/core/tee/tee_ree_fs.c
@@ -26,125 +26,45 @@
*/
#include <assert.h>
-#include <kernel/thread.h>
#include <kernel/mutex.h>
#include <kernel/panic.h>
+#include <kernel/thread.h>
#include <mm/core_memprot.h>
#include <optee_msg_supplicant.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <string_ext.h>
+#include <string.h>
#include <sys/queue.h>
+#include <tee/fs_htree.h>
#include <tee/tee_cryp_provider.h>
#include <tee/tee_fs.h>
-#include <tee/tee_fs_defs.h>
#include <tee/tee_fs_rpc.h>
-#include <tee/tee_fs_key_manager.h>
#include <trace.h>
#include <utee_defines.h>
#include <util.h>
-/*
- * This file implements the tee_file_operations structure for a secure
- * filesystem based on single file in normal world.
- *
- * All fields in the REE file are duplicated with two versions 0 and 1. The
- * active meta-data block is selected by the lowest bit in the
- * meta-counter. The active file block is selected by corresponding bit
- * number in struct tee_fs_file_info.backup_version_table.
- *
- * The atomicity of each operation is ensured by updating meta-counter when
- * everything in the secondary blocks (both meta-data and file-data blocks)
- * are successfully written. The main purpose of the code below is to
- * perform block encryption and authentication of the file data, and
- * properly handle seeking through the file. One file (in the sense of
- * struct tee_file_operations) maps to one file in the REE filesystem, and
- * has the following structure:
- *
- * [ 4 bytes meta-counter]
- * [ meta-data version 0][ meta-data version 1 ]
- * [ Block 0 version 0 ][ Block 0 version 1 ]
- * [ Block 1 version 0 ][ Block 1 version 1 ]
- * ...
- * [ Block n version 0 ][ Block n version 1 ]
- *
- * One meta-data block is built up as:
- * [ struct meta_header | struct tee_fs_get_header_size ]
- *
- * One data block is built up as:
- * [ struct block_header | BLOCK_FILE_SIZE bytes ]
- *
- * struct meta_header and struct block_header are defined in
- * tee_fs_key_manager.h.
- *
- */
-
#define BLOCK_SHIFT 12
#define BLOCK_SIZE (1 << BLOCK_SHIFT)
-#define MAX_FILE_SIZE (BLOCK_SIZE * NUM_BLOCKS_PER_FILE)
-
struct tee_fs_fd {
- uint32_t meta_counter;
- struct tee_fs_file_meta meta;
- tee_fs_off_t pos;
- uint32_t flags;
- bool is_new_file;
+ struct tee_fs_htree *ht;
int fd;
};
-static inline int pos_to_block_num(int position)
+static int pos_to_block_num(int position)
{
return position >> BLOCK_SHIFT;
}
-static inline int get_last_block_num(size_t size)
-{
- return pos_to_block_num(size - 1);
-}
-
-static bool get_backup_version_of_block(struct tee_fs_file_meta *meta,
- size_t block_num)
-{
- uint32_t index = (block_num / 32);
- uint32_t block_mask = 1 << (block_num % 32);
-
- return !!(meta->info.backup_version_table[index] & block_mask);
-}
-
-static inline void toggle_backup_version_of_block(
- struct tee_fs_file_meta *meta,
- size_t block_num)
-{
- uint32_t index = (block_num / 32);
- uint32_t block_mask = 1 << (block_num % 32);
-
- meta->info.backup_version_table[index] ^= block_mask;
-}
-
-struct block_operations {
-
- /*
- * Read a block from REE File System which is corresponding
- * to the given block_num.
- */
- struct block *(*read)(struct tee_fs_fd *fdp, int block_num);
-
- /*
- * Write the given block to REE File System
- */
- int (*write)(struct tee_fs_fd *fdp, struct block *b,
- struct tee_fs_file_meta *new_meta);
-};
-
static struct mutex ree_fs_mutex = MUTEX_INITIALIZER;
-static TEE_Result ree_fs_opendir_rpc(const char *name, struct tee_fs_dir **d)
+static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid,
+ struct tee_fs_dir **d)
{
- return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_FS, name, d);
+ return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_FS, uuid, d);
}
static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
@@ -159,330 +79,187 @@ static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d,
return tee_fs_rpc_readdir(OPTEE_MSG_RPC_CMD_FS, d, ent);
}
-static size_t meta_size(void)
-{
- return tee_fs_get_header_size(META_FILE) +
- sizeof(struct tee_fs_file_meta);
-}
-
-static size_t meta_pos_raw(struct tee_fs_fd *fdp, bool active)
-{
- size_t offs = sizeof(uint32_t);
-
- if ((fdp->meta_counter & 1) == active)
- offs += meta_size();
- return offs;
-}
-
-static size_t block_size_raw(void)
-{
- return tee_fs_get_header_size(BLOCK_FILE) + BLOCK_SIZE;
-}
-
-static size_t block_pos_raw(struct tee_fs_file_meta *meta, size_t block_num,
- bool active)
-{
- size_t n = block_num * 2;
-
- if (active == get_backup_version_of_block(meta, block_num))
- n++;
-
- return sizeof(uint32_t) + meta_size() * 2 + n * block_size_raw();
-}
-
-/*
- * encrypted_fek: as input for META_FILE and BLOCK_FILE
- */
-static TEE_Result encrypt_and_write_file(struct tee_fs_fd *fdp,
- enum tee_fs_file_type file_type, size_t offs,
- void *data_in, size_t data_in_size,
- uint8_t *encrypted_fek)
+static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, size_t pos,
+ const void *buf, size_t len)
{
TEE_Result res;
- struct tee_fs_rpc_operation op;
- void *ciphertext;
- size_t header_size = tee_fs_get_header_size(file_type);
- size_t ciphertext_size = header_size + data_in_size;
-
+ size_t start_block_num = pos_to_block_num(pos);
+ size_t end_block_num = pos_to_block_num(pos + len - 1);
+ size_t remain_bytes = len;
+ uint8_t *data_ptr = (uint8_t *)buf;
+ uint8_t *block;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
- offs, ciphertext_size, &ciphertext);
- if (res != TEE_SUCCESS)
- return res;
+ block = malloc(BLOCK_SIZE);
+ if (!block)
+ return TEE_ERROR_OUT_OF_MEMORY;
- res = tee_fs_encrypt_file(file_type, data_in, data_in_size,
- ciphertext, &ciphertext_size, encrypted_fek);
- if (res != TEE_SUCCESS)
- return res;
+ while (start_block_num <= end_block_num) {
+ size_t offset = pos % BLOCK_SIZE;
+ size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);
- return tee_fs_rpc_write_final(&op);
-}
+ if (size_to_write + offset > BLOCK_SIZE)
+ size_to_write = BLOCK_SIZE - offset;
-/*
- * encrypted_fek: as output for META_FILE
- * as input for BLOCK_FILE
- */
-static TEE_Result read_and_decrypt_file(struct tee_fs_fd *fdp,
- enum tee_fs_file_type file_type, size_t offs,
- void *data_out, size_t *data_out_size,
- uint8_t *encrypted_fek)
-{
- TEE_Result res;
- struct tee_fs_rpc_operation op;
- size_t bytes;
- void *ciphertext;
+ if (start_block_num * BLOCK_SIZE <
+ ROUNDUP(meta->length, BLOCK_SIZE)) {
+ res = tee_fs_htree_read_block(&fdp->ht,
+ start_block_num, block);
+ if (res != TEE_SUCCESS)
+ goto exit;
+ } else {
+ memset(block, 0, BLOCK_SIZE);
+ }
- bytes = *data_out_size + tee_fs_get_header_size(file_type);
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, offs,
- bytes, &ciphertext);
- if (res != TEE_SUCCESS)
- return res;
+ if (data_ptr)
+ memcpy(block + offset, data_ptr, size_to_write);
+ else
+ memset(block + offset, 0, size_to_write);
- res = tee_fs_rpc_read_final(&op, &bytes);
- if (res != TEE_SUCCESS)
- return res;
+ res = tee_fs_htree_write_block(&fdp->ht, start_block_num,
+ block);
+ if (res != TEE_SUCCESS)
+ goto exit;
- if (!bytes) {
- *data_out_size = 0;
- return TEE_SUCCESS;
+ if (data_ptr)
+ data_ptr += size_to_write;
+ remain_bytes -= size_to_write;
+ start_block_num++;
+ pos += size_to_write;
}
- res = tee_fs_decrypt_file(file_type, ciphertext, bytes, data_out,
- data_out_size, encrypted_fek);
- if (res != TEE_SUCCESS)
- return TEE_ERROR_CORRUPT_OBJECT;
- return TEE_SUCCESS;
-}
-
-static TEE_Result write_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *meta)
-{
- size_t offs = meta_pos_raw(fdp, false);
-
- return encrypt_and_write_file(fdp, META_FILE, offs,
- (void *)&meta->info, sizeof(meta->info),
- meta->encrypted_fek);
-}
+ if (pos > meta->length)
+ meta->length = pos;
-static TEE_Result write_meta_counter(struct tee_fs_fd *fdp)
-{
- TEE_Result res;
- struct tee_fs_rpc_operation op;
- size_t bytes = sizeof(uint32_t);
- void *data;
-
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, 0,
- bytes, &data);
- if (res != TEE_SUCCESS)
- return res;
-
- memcpy(data, &fdp->meta_counter, bytes);
-
- return tee_fs_rpc_write_final(&op);
-}
-
-static TEE_Result create_meta(struct tee_fs_fd *fdp, const char *fname)
-{
- TEE_Result res;
-
- memset(fdp->meta.info.backup_version_table, 0xff,
- sizeof(fdp->meta.info.backup_version_table));
- fdp->meta.info.length = 0;
-
- res = tee_fs_generate_fek(fdp->meta.encrypted_fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
- if (res != TEE_SUCCESS)
- return res;
-
- fdp->meta.counter = fdp->meta_counter;
-
- res = write_meta_file(fdp, &fdp->meta);
- if (res != TEE_SUCCESS)
- return res;
- return write_meta_counter(fdp);
+exit:
+ free(block);
+ return res;
}
-static TEE_Result commit_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *new_meta)
+static TEE_Result get_offs_size(enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, size_t *offs, size_t *size)
{
- TEE_Result res;
-
- new_meta->counter = fdp->meta_counter + 1;
+ const size_t node_size = sizeof(struct tee_fs_htree_node_image);
+ const size_t block_nodes = BLOCK_SIZE / (node_size * 2);
+ size_t pbn;
+ size_t bidx;
- res = write_meta_file(fdp, new_meta);
- if (res != TEE_SUCCESS)
- return res;
+ assert(vers == 0 || vers == 1);
/*
- * From now on the new meta is successfully committed,
- * change tee_fs_fd accordingly
+ * File layout
+ *
+ * phys block 0:
+ * tee_fs_htree_image vers 0 @ offs = 0
+ * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image)
+ *
+ * phys block 1:
+ * tee_fs_htree_node_image 0 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 0 vers 1 @ offs = node_size
+ * tee_fs_htree_node_image 1 vers 0 @ offs = node_size * 2
+ * tee_fs_htree_node_image 1 vers 1 @ offs = node_size * 3
+ * ...
+ * tee_fs_htree_node_image 61 vers 0 @ offs = node_size * 122
+ * tee_fs_htree_node_image 61 vers 1 @ offs = node_size * 123
+ *
+ * phys block 2:
+ * data block 0 vers 0
+ *
+ * phys block 3:
+ * data block 0 vers 1
+ *
+ * ...
+ * phys block 63:
+ * data block 61 vers 0
+ *
+ * phys block 64:
+ * data block 61 vers 1
+ *
+ * phys block 65:
+ * tee_fs_htree_node_image 62 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 62 vers 1 @ offs = node_size
+ * tee_fs_htree_node_image 63 vers 0 @ offs = node_size * 2
+ * tee_fs_htree_node_image 63 vers 1 @ offs = node_size * 3
+ * ...
+ * tee_fs_htree_node_image 121 vers 0 @ offs = node_size * 122
+ * tee_fs_htree_node_image 121 vers 1 @ offs = node_size * 123
+ *
+ * ...
*/
- fdp->meta = *new_meta;
- fdp->meta_counter = fdp->meta.counter;
- return write_meta_counter(fdp);
-}
-
-static TEE_Result read_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *meta)
-{
- size_t meta_info_size = sizeof(struct tee_fs_file_info);
- size_t offs = meta_pos_raw(fdp, true);
-
- return read_and_decrypt_file(fdp, META_FILE, offs,
- &meta->info, &meta_info_size,
- meta->encrypted_fek);
+ switch (type) {
+ case TEE_FS_HTREE_TYPE_HEAD:
+ *offs = sizeof(struct tee_fs_htree_image) * vers;
+ *size = sizeof(struct tee_fs_htree_image);
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_NODE:
+ pbn = 1 + ((idx / block_nodes) * block_nodes * 2);
+ *offs = pbn * BLOCK_SIZE +
+ 2 * node_size * (idx % block_nodes) +
+ node_size * vers;
+ *size = node_size;
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_BLOCK:
+ bidx = 2 * idx + vers;
+ pbn = 2 + bidx + bidx / (block_nodes * 2 - 1);
+ *offs = pbn * BLOCK_SIZE;
+ *size = BLOCK_SIZE;
+ return TEE_SUCCESS;
+ default:
+ return TEE_ERROR_GENERIC;
+ }
}
-static TEE_Result read_meta_counter(struct tee_fs_fd *fdp)
+static TEE_Result ree_fs_rpc_read_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
{
+ struct tee_fs_fd *fdp = aux;
TEE_Result res;
- struct tee_fs_rpc_operation op;
- void *data;
- size_t bytes = sizeof(uint32_t);
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, 0,
- bytes, &data);
- if (res != TEE_SUCCESS)
- return res;
+ size_t offs;
+ size_t size;
- res = tee_fs_rpc_read_final(&op, &bytes);
+ res = get_offs_size(type, idx, vers, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- if (bytes != sizeof(uint32_t))
- return TEE_ERROR_CORRUPT_OBJECT;
-
- memcpy(&fdp->meta_counter, data, bytes);
-
- return TEE_SUCCESS;
+ return tee_fs_rpc_read_init(op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs, size, data);
}
-static TEE_Result read_meta(struct tee_fs_fd *fdp, const char *fname)
+static TEE_Result ree_fs_rpc_write_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
{
+ struct tee_fs_fd *fdp = aux;
TEE_Result res;
+ size_t offs;
+ size_t size;
- res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
- if (res != TEE_SUCCESS)
- return res;
-
- res = read_meta_counter(fdp);
- if (res != TEE_SUCCESS)
- return res;
-
- return read_meta_file(fdp, &fdp->meta);
-}
-
-static TEE_Result read_block(struct tee_fs_fd *fdp, int bnum, uint8_t *data)
-{
- TEE_Result res;
- size_t ct_size = block_size_raw();
- size_t out_size = BLOCK_SIZE;
- ssize_t pos = block_pos_raw(&fdp->meta, bnum, true);
- size_t bytes;
- void *ct;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, pos,
- ct_size, &ct);
- if (res != TEE_SUCCESS)
- return res;
- res = tee_fs_rpc_read_final(&op, &bytes);
+ res = get_offs_size(type, idx, vers, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- if (!bytes) {
- memset(data, 0, BLOCK_SIZE);
- return TEE_SUCCESS; /* Block does not exist */
- }
- return tee_fs_decrypt_file(BLOCK_FILE, ct, bytes, data,
- &out_size, fdp->meta.encrypted_fek);
+ return tee_fs_rpc_write_init(op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs, size, data);
}
-static TEE_Result write_block(struct tee_fs_fd *fdp, size_t bnum, uint8_t *data,
- struct tee_fs_file_meta *new_meta)
-{
- TEE_Result res;
- size_t offs = block_pos_raw(new_meta, bnum, false);
-
- res = encrypt_and_write_file(fdp, BLOCK_FILE, offs, data,
- BLOCK_SIZE, new_meta->encrypted_fek);
- if (res == TEE_SUCCESS)
- toggle_backup_version_of_block(new_meta, bnum);
- return res;
-}
-
-static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
- size_t len, struct tee_fs_file_meta *new_meta)
-{
- TEE_Result res;
- int start_block_num = pos_to_block_num(fdp->pos);
- int end_block_num = pos_to_block_num(fdp->pos + len - 1);
- size_t remain_bytes = len;
- uint8_t *data_ptr = (uint8_t *)buf;
- uint8_t *block;
- int orig_pos = fdp->pos;
-
- block = malloc(BLOCK_SIZE);
- if (!block)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- while (start_block_num <= end_block_num) {
- int offset = fdp->pos % BLOCK_SIZE;
- size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);
-
- if (size_to_write + offset > BLOCK_SIZE)
- size_to_write = BLOCK_SIZE - offset;
-
- res = read_block(fdp, start_block_num, block);
- if (res == TEE_ERROR_ITEM_NOT_FOUND)
- memset(block, 0, BLOCK_SIZE);
- else if (res != TEE_SUCCESS)
- goto exit;
-
- if (data_ptr)
- memcpy(block + offset, data_ptr, size_to_write);
- else
- memset(block + offset, 0, size_to_write);
-
- res = write_block(fdp, start_block_num, block, new_meta);
- if (res != TEE_SUCCESS)
- goto exit;
-
- if (data_ptr)
- data_ptr += size_to_write;
- remain_bytes -= size_to_write;
- start_block_num++;
- fdp->pos += size_to_write;
- }
-
- if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
- new_meta->info.length = fdp->pos;
-
-exit:
- free(block);
- if (res != TEE_SUCCESS)
- fdp->pos = orig_pos;
- return res;
-}
+static const struct tee_fs_htree_storage ree_fs_storage_ops = {
+ .block_size = BLOCK_SIZE,
+ .rpc_read_init = ree_fs_rpc_read_init,
+ .rpc_read_final = tee_fs_rpc_read_final,
+ .rpc_write_init = ree_fs_rpc_write_init,
+ .rpc_write_final = tee_fs_rpc_write_final,
+};
-static TEE_Result open_internal(const char *file, bool create,
+static TEE_Result open_internal(struct tee_pobj *po, bool create,
struct tee_file_handle **fh)
{
TEE_Result res;
- size_t len;
struct tee_fs_fd *fdp = NULL;
- if (!file)
- return TEE_ERROR_BAD_PARAMETERS;
-
- len = strlen(file) + 1;
- if (len > TEE_FS_NAME_MAX)
- return TEE_ERROR_BAD_PARAMETERS;
-
fdp = calloc(1, sizeof(struct tee_fs_fd));
if (!fdp)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -491,17 +268,22 @@ static TEE_Result open_internal(const char *file, bool create,
mutex_lock(&ree_fs_mutex);
if (create)
- res = create_meta(fdp, file);
+ res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_FS, po, &fdp->fd);
else
- res = read_meta(fdp, file);
+ res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_FS, po, &fdp->fd);
+
+ if (res != TEE_SUCCESS)
+ goto out;
+ res = tee_fs_htree_open(create, &ree_fs_storage_ops, fdp, &fdp->ht);
+out:
if (res == TEE_SUCCESS) {
*fh = (struct tee_file_handle *)fdp;
} else {
if (fdp->fd != -1)
tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
if (create)
- tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, file);
+ tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, po);
free(fdp);
}
@@ -509,14 +291,15 @@ static TEE_Result open_internal(const char *file, bool create,
return res;
}
-static TEE_Result ree_fs_open(const char *file, struct tee_file_handle **fh)
+static TEE_Result ree_fs_open(struct tee_pobj *po, struct tee_file_handle **fh)
{
- return open_internal(file, false, fh);
+ return open_internal(po, false, fh);
}
-static TEE_Result ree_fs_create(const char *file, struct tee_file_handle **fh)
+static TEE_Result ree_fs_create(struct tee_pobj *po,
+ struct tee_file_handle **fh)
{
- return open_internal(file, true, fh);
+ return open_internal(po, true, fh);
}
static void ree_fs_close(struct tee_file_handle **fh)
@@ -524,106 +307,53 @@ static void ree_fs_close(struct tee_file_handle **fh)
struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh;
if (fdp) {
+ tee_fs_htree_close(&fdp->ht);
tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
free(fdp);
*fh = NULL;
}
}
-static TEE_Result ree_fs_seek(struct tee_file_handle *fh, int32_t offset,
- TEE_Whence whence, int32_t *new_offs)
-{
- TEE_Result res;
- tee_fs_off_t new_pos;
- size_t filelen;
- struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
-
- mutex_lock(&ree_fs_mutex);
-
- DMSG("offset=%d, whence=%d", (int)offset, whence);
-
- filelen = fdp->meta.info.length;
-
- switch (whence) {
- case TEE_DATA_SEEK_SET:
- new_pos = offset;
- break;
-
- case TEE_DATA_SEEK_CUR:
- new_pos = fdp->pos + offset;
- break;
-
- case TEE_DATA_SEEK_END:
- new_pos = filelen + offset;
- break;
-
- default:
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit;
- }
-
- if (new_pos < 0)
- new_pos = 0;
-
- if (new_pos > TEE_DATA_MAX_POSITION) {
- EMSG("Position is beyond TEE_DATA_MAX_POSITION");
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit;
- }
-
- fdp->pos = new_pos;
- if (new_offs)
- *new_offs = new_pos;
- res = TEE_SUCCESS;
-exit:
- mutex_unlock(&ree_fs_mutex);
- return res;
-}
-
-/*
- * To ensure atomic truncate operation, we can:
- *
- * - update file length to new length
- * - commit new meta
- *
- * To ensure atomic extend operation, we can:
- *
- * - update file length to new length
- * - allocate and fill zero data to new blocks
- * - commit new meta
- *
- * Any failure before committing new meta is considered as
- * update failed, and the file content will not be updated
- */
static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp,
tee_fs_off_t new_file_len)
{
TEE_Result res;
- size_t old_file_len = fdp->meta.info.length;
- struct tee_fs_file_meta new_meta;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
- if (new_file_len > MAX_FILE_SIZE)
- return TEE_ERROR_BAD_PARAMETERS;
+ if ((size_t)new_file_len > meta->length) {
+ size_t ext_len = new_file_len - meta->length;
- new_meta = fdp->meta;
- new_meta.info.length = new_file_len;
+ res = out_of_place_write(fdp, meta->length, NULL, ext_len);
+ if (res != TEE_SUCCESS)
+ return res;
+ } else {
+ size_t offs;
+ size_t sz;
+
+ res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK,
+ ROUNDUP(new_file_len, BLOCK_SIZE) /
+ BLOCK_SIZE, 1, &offs, &sz);
+ if (res != TEE_SUCCESS)
+ return res;
- if ((size_t)new_file_len > old_file_len) {
- size_t ext_len = new_file_len - old_file_len;
- int orig_pos = fdp->pos;
+ res = tee_fs_htree_truncate(&fdp->ht,
+ new_file_len / BLOCK_SIZE);
+ if (res != TEE_SUCCESS)
+ return res;
- fdp->pos = old_file_len;
- res = out_of_place_write(fdp, NULL, ext_len, &new_meta);
- fdp->pos = orig_pos;
+ res = tee_fs_rpc_truncate(OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs + sz);
if (res != TEE_SUCCESS)
return res;
+
+ meta->length = new_file_len;
}
- return commit_meta_file(fdp, &new_meta);
+ return tee_fs_htree_sync_to_storage(&fdp->ht);
}
-static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
- size_t *len)
+static TEE_Result ree_fs_read(struct tee_file_handle *fh, size_t pos,
+ void *buf, size_t *len)
{
TEE_Result res;
int start_block_num;
@@ -632,16 +362,15 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
uint8_t *data_ptr = buf;
uint8_t *block = NULL;
struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
mutex_lock(&ree_fs_mutex);
remain_bytes = *len;
- if ((fdp->pos + remain_bytes) < remain_bytes ||
- fdp->pos > (tee_fs_off_t)fdp->meta.info.length)
+ if ((pos + remain_bytes) < remain_bytes || pos > meta->length)
remain_bytes = 0;
- else if (fdp->pos + (tee_fs_off_t)remain_bytes >
- (tee_fs_off_t)fdp->meta.info.length)
- remain_bytes = fdp->meta.info.length - fdp->pos;
+ else if (pos + remain_bytes > meta->length)
+ remain_bytes = meta->length - pos;
*len = remain_bytes;
@@ -650,8 +379,8 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
goto exit;
}
- start_block_num = pos_to_block_num(fdp->pos);
- end_block_num = pos_to_block_num(fdp->pos + remain_bytes - 1);
+ start_block_num = pos_to_block_num(pos);
+ end_block_num = pos_to_block_num(pos + remain_bytes - 1);
block = malloc(BLOCK_SIZE);
if (!block) {
@@ -660,24 +389,21 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
}
while (start_block_num <= end_block_num) {
- tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
+ size_t offset = pos % BLOCK_SIZE;
size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE);
if (size_to_read + offset > BLOCK_SIZE)
size_to_read = BLOCK_SIZE - offset;
- res = read_block(fdp, start_block_num, block);
- if (res != TEE_SUCCESS) {
- if (res == TEE_ERROR_MAC_INVALID)
- res = TEE_ERROR_CORRUPT_OBJECT;
+ res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block);
+ if (res != TEE_SUCCESS)
goto exit;
- }
memcpy(data_ptr, block + offset, size_to_read);
data_ptr += size_to_read;
remain_bytes -= size_to_read;
- fdp->pos += size_to_read;
+ pos += size_to_read;
start_block_num++;
}
@@ -688,27 +414,10 @@ exit:
return res;
}
-/*
- * To ensure atomicity of write operation, we need to
- * do the following steps:
- * (The sequence of operations is very important)
- *
- * - Create a new backup version of meta file as a copy
- * of current meta file.
- * - For each blocks to write:
- * - Create new backup version for current block.
- * - Write data to new backup version.
- * - Update the new meta file accordingly.
- * - Write the new meta file.
- *
- * (Any failure in above steps is considered as update failed,
- * and the file content will not be updated)
- */
-static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf,
- size_t len)
+static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos,
+ const void *buf, size_t len)
{
TEE_Result res;
- struct tee_fs_file_meta new_meta;
struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
size_t file_size;
@@ -717,31 +426,31 @@ static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf,
mutex_lock(&ree_fs_mutex);
- file_size = fdp->meta.info.length;
+ file_size = tee_fs_htree_get_meta(fdp->ht)->length;
- if ((fdp->pos + len) > MAX_FILE_SIZE || (fdp->pos + len) < len) {
+ if ((pos + len) < len) {
res = TEE_ERROR_BAD_PARAMETERS;
goto exit;
}
- if (file_size < (size_t)fdp->pos) {
- res = ree_fs_ftruncate_internal(fdp, fdp->pos);
+ if (file_size < pos) {
+ res = ree_fs_ftruncate_internal(fdp, pos);
if (res != TEE_SUCCESS)
goto exit;
}
- new_meta = fdp->meta;
- res = out_of_place_write(fdp, buf, len, &new_meta);
+ res = out_of_place_write(fdp, pos, buf, len);
if (res != TEE_SUCCESS)
goto exit;
- res = commit_meta_file(fdp, &new_meta);
exit:
+ if (res == TEE_SUCCESS)
+ res = tee_fs_htree_sync_to_storage(&fdp->ht);
mutex_unlock(&ree_fs_mutex);
return res;
}
-static TEE_Result ree_fs_rename(const char *old, const char *new,
+static TEE_Result ree_fs_rename(struct tee_pobj *old, struct tee_pobj *new,
bool overwrite)
{
TEE_Result res;
@@ -753,12 +462,12 @@ static TEE_Result ree_fs_rename(const char *old, const char *new,
return res;
}
-static TEE_Result ree_fs_remove(const char *file)
+static TEE_Result ree_fs_remove(struct tee_pobj *po)
{
TEE_Result res;
mutex_lock(&ree_fs_mutex);
- res = tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, file);
+ res = tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, po);
mutex_unlock(&ree_fs_mutex);
return res;
@@ -782,7 +491,6 @@ const struct tee_file_operations ree_fs_ops = {
.close = ree_fs_close,
.read = ree_fs_read,
.write = ree_fs_write,
- .seek = ree_fs_seek,
.truncate = ree_fs_truncate,
.rename = ree_fs_rename,
.remove = ree_fs_remove,