{"action":"created","comment":{"url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/comments/71506267","id":71506267,"diff_hunk":"@@ -0,0 +1,879 @@\n+/*\n+ * Copyright (c) 2016, Linaro Limited\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice,\n+ * this list of conditions and the following disclaimer.\n+ *\n+ * 2. Redistributions in binary form must reproduce the above copyright notice,\n+ * this list of conditions and the following disclaimer in the documentation\n+ * and/or other materials provided with the distribution.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n+ * POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+/*\n+ * This file implements the tee_file_operations structure for a secure\n+ * filesystem based on an SQLite database in normal world.\n+ * The atomicity of each operation is ensured by using SQL transactions.\n+ * The main purpose of the code below is to perform block encryption and\n+ * authentication of the file data, and properly handle seeking through the\n+ * file. One file (in the sense of struct tee_file_operations) maps to one\n+ * file in the SQL filesystem, and has the following structure:\n+ *\n+ * [       File meta-data       ][      Block #0        ][Block #1]...\n+ * [meta_header|sql_fs_file_meta][block_header|user data][        ]...\n+ *\n+ * meta_header and block_header are defined in tee_fs_key_manager.h.\n+ */\n+\n+#include <assert.h>\n+#include <kernel/tee_common_unpg.h>\n+#include <kernel/handle.h>\n+#include <optee_msg.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <string_ext.h>\n+#include <sys/queue.h>\n+#include <tee/tee_cryp_provider.h>\n+#include <tee/tee_fs.h>\n+#include <tee/tee_fs_defs.h>\n+#include <tee/tee_fs_key_manager.h>\n+#include <tee/tee_fs_rpc.h>\n+#include <trace.h>\n+#include <utee_defines.h>\n+#include <util.h>\n+\n+/* Block size for encryption */\n+#define BLOCK_SHIFT 12\n+#define BLOCK_SIZE (1 << BLOCK_SHIFT)\n+\n+struct sql_fs_file_meta {\n+\tsize_t length;\n+\tuint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE];\n+};\n+\n+/* File descriptor */\n+struct sql_fs_fd {\n+\tstruct sql_fs_file_meta meta;\n+\ttee_fs_off_t pos;\n+\tint fd; /* returned by normal world */\n+\tint flags; /* open flags */\n+};\n+\n+struct tee_fs_dir {\n+\tint nw_dir;\n+\tstruct tee_fs_dirent d;\n+};\n+\n+/* Container for file descriptors (struct sql_fs_fd) */\n+static struct handle_db fs_db = HANDLE_DB_INITIALIZER;\n+\n+/*\n+ * Interface with tee-supplicant\n+ */\n+\n+static int sql_fs_access_rpc(const char *name, int mode)\n+{\n+\treturn tee_fs_rpc_access(OPTEE_MSG_RPC_CMD_SQL_FS, name, mode);\n+}\n+\n+static int sql_fs_begin_transaction_rpc(void)\n+{\n+\treturn tee_fs_rpc_begin_transaction(OPTEE_MSG_RPC_CMD_SQL_FS);\n+}\n+\n+static int sql_fs_close_rpc(int fd)\n+{\n+\treturn tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_SQL_FS, fd);\n+}\n+\n+static int sql_fs_end_transaction_rpc(bool rollback)\n+{\n+\treturn tee_fs_rpc_end_transaction(OPTEE_MSG_RPC_CMD_SQL_FS, rollback);\n+}\n+\n+static int sql_fs_ftruncate_rpc(int fd, tee_fs_off_t length)\n+{\n+\treturn tee_fs_rpc_ftruncate(OPTEE_MSG_RPC_CMD_SQL_FS, fd, length);\n+}\n+\n+static tee_fs_off_t sql_fs_lseek_rpc(int fd, tee_fs_off_t offset, int whence)\n+{\n+\treturn tee_fs_rpc_lseek_rpc(OPTEE_MSG_RPC_CMD_SQL_FS, fd, offset,\n+\t\t\t\t    whence);\n+}\n+\n+static int sql_fs_mkdir_rpc(const char *path, tee_fs_mode_t mode)\n+{\n+\treturn tee_fs_rpc_mkdir(OPTEE_MSG_RPC_CMD_SQL_FS, path, mode);\n+}\n+\n+static int sql_fs_open_rpc(TEE_Result *errno, const char *file, int flags, ...)\n+{\n+\treturn tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_SQL_FS, errno, file, flags);\n+}\n+\n+static struct tee_fs_dir *sql_fs_opendir_rpc(const char *name)\n+{\n+\treturn tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_SQL_FS, name);\n+}\n+\n+static int sql_fs_read_rpc(int fd, void *buf, size_t len)\n+{\n+\treturn tee_fs_rpc_read(OPTEE_MSG_RPC_CMD_SQL_FS, fd, buf, len);\n+}\n+\n+static struct tee_fs_dirent *sql_fs_readdir_rpc(struct tee_fs_dir *d)\n+{\n+\treturn tee_fs_rpc_readdir(OPTEE_MSG_RPC_CMD_SQL_FS, d);\n+}\n+\n+static int sql_fs_rename_rpc(const char *old, const char *nw)\n+{\n+\treturn tee_fs_rpc_rename_rpc(OPTEE_MSG_RPC_CMD_SQL_FS, old, nw);\n+}\n+\n+static int sql_fs_write_rpc(int fd, const void *buf, size_t len)\n+{\n+\treturn tee_fs_rpc_write(OPTEE_MSG_RPC_CMD_SQL_FS, fd, buf, len);\n+}\n+\n+static int sql_fs_closedir_rpc(struct tee_fs_dir *d)\n+{\n+\treturn tee_fs_rpc_closedir(OPTEE_MSG_RPC_CMD_SQL_FS, d);\n+}\n+\n+static int sql_fs_rmdir_rpc(const char *name)\n+{\n+\treturn tee_fs_rpc_rmdir(OPTEE_MSG_RPC_CMD_SQL_FS, name);\n+}\n+\n+static int sql_fs_unlink_rpc(const char *file)\n+{\n+\treturn tee_fs_rpc_unlink(OPTEE_MSG_RPC_CMD_SQL_FS, file);\n+}\n+\n+/*\n+ * End of interface with tee-supplicant\n+ */\n+\n+static size_t meta_size(void)\n+{\n+\treturn tee_fs_get_header_size(META_FILE) +\n+\t       sizeof(struct sql_fs_file_meta);\n+}\n+\n+static size_t block_header_size(void)\n+{\n+\treturn tee_fs_get_header_size(BLOCK_FILE);\n+}\n+\n+static size_t block_size_raw(void)\n+{\n+\treturn block_header_size() + BLOCK_SIZE;\n+}\n+\n+/* Return the block number from a position in the user data */\n+static ssize_t block_num(tee_fs_off_t pos)\n+{\n+\treturn pos / BLOCK_SIZE;\n+}\n+\n+/* Return the block number from a position in the DB file */\n+static ssize_t block_num_raw(tee_fs_off_t raw_pos)\n+{\n+\treturn (raw_pos - meta_size()) / block_size_raw();\n+}\n+\n+/* Return the position of a block in the DB file */\n+static ssize_t block_pos_raw(size_t block_num)\n+{\n+\treturn meta_size() + block_num * block_size_raw();\n+}\n+\n+/* Given a position in the user data, return the offset in the DB file */\n+static tee_fs_off_t pos_to_raw(tee_fs_off_t pos)\n+{\n+\ttee_fs_off_t res;\n+\n+\tif (pos < 0)\n+\t\treturn -1;\n+\tres = meta_size() + block_num(pos) * block_size_raw();\n+\tif (pos % BLOCK_SIZE) {\n+\t\tres += block_header_size();\n+\t\tres += pos % BLOCK_SIZE;\n+\t}\n+\n+\treturn res;\n+}\n+\n+/* Given a position in the DB file, return the offset in the user data */\n+static tee_fs_off_t raw_to_pos(tee_fs_off_t raw_pos)\n+{\n+\ttee_fs_off_t pos = raw_pos;\n+\tssize_t n = block_num_raw(raw_pos);\n+\n+\tif (n < 0)\n+\t\treturn -1;\n+\n+\tpos -= meta_size();\n+\tpos -= block_header_size();\n+\tif (pos < 0)\n+\t\treturn -1;\n+\n+\treturn (n * BLOCK_SIZE) + (pos % BLOCK_SIZE);\n+}\n+\n+static void put_fdp(struct sql_fs_fd *fdp)\n+{\n+\thandle_put(&fs_db, fdp->fd);\n+\tfree(fdp);\n+}\n+\n+#ifndef CFG_ENC_FS\n+static void copy_data(enum tee_fs_file_type type, uint8_t *raw_block,\n+\t\t      const uint8_t *data, size_t len)\n+{\n+\tsize_t header_size = tee_fs_get_header_size(type);\n+\n+\tassert(type == META_FILE || type == BLOCK_FILE);\n+\n+\tmemset(raw_block, 0xFF, header_size);\n+\tmemcpy(raw_block + header_size, data, len);\n+}\n+#endif\n+\n+static int write_meta(TEE_Result *errno, struct sql_fs_fd *fdp)\n+{\n+\tint fd = fdp->fd;\n+\tsize_t ct_size = meta_size();\n+\tuint8_t *ct;\n+\tint rc = -1;\n+\n+\tct = malloc(ct_size);\n+\tif (!ct) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = sql_fs_lseek_rpc(fd, 0, TEE_FS_SEEK_SET);\n+\tif (rc < 0)\n+\t\tgoto exit;\n+\n+#ifdef CFG_ENC_FS\n+\t{\n+\t\tTEE_Result res;\n+\n+\t\tres = tee_fs_encrypt_file(META_FILE,\n+\t\t\t\t\t  (const uint8_t *)&fdp->meta,\n+\t\t\t\t\t  sizeof(fdp->meta), ct, &ct_size,\n+\t\t\t\t\t  fdp->meta.encrypted_fek);\n+\t\tif (res != TEE_SUCCESS) {\n+\t\t\t*errno = res;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+#else\n+\tcopy_data(META_FILE, ct, (const uint8_t *)&fdp->meta,\n+\t\t  sizeof(fdp->meta));\n+#endif\n+\n+\trc = sql_fs_write_rpc(fdp->fd, ct, ct_size);\n+\tif (rc != (int)ct_size)\n+\t\trc = -1;\n+\telse\n+\t\trc = 0;\n+\n+exit:\n+\tfree(ct);\n+\treturn rc;\n+}\n+\n+static int create_meta(TEE_Result *errno, struct sql_fs_fd *fdp)\n+{\n+\tTEE_Result res;\n+\n+\tmemset(&fdp->meta, 0, sizeof(fdp->meta));\n+\n+\tres = tee_fs_generate_fek(fdp->meta.encrypted_fek, TEE_FS_KM_FEK_SIZE);\n+\tif (res != TEE_SUCCESS)\n+\t\treturn -1;\n+\n+\treturn write_meta(errno, fdp);\n+}\n+\n+/*\n+ * Read metadata block from disk, possibly create it if it does not exist and\n+ * and open flags allow\n+ */\n+static int read_meta(TEE_Result *errno, struct sql_fs_fd *fdp)\n+{\n+\tsize_t msize = meta_size();\n+\tsize_t out_size = sizeof(fdp->meta);\n+\tuint8_t *meta = NULL;\n+\tint rc = -1;\n+\n+\t*errno = TEE_ERROR_GENERIC;\n+\n+\tmeta = malloc(msize);\n+\tif (!meta) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = sql_fs_lseek_rpc(fdp->fd, 0, TEE_FS_SEEK_SET);\n+\tif (rc < 0)\n+\t\tgoto exit;\n+\n+\trc = sql_fs_read_rpc(fdp->fd, meta, msize);\n+\tif (rc < 0) {\n+\t\t/* Read error */\n+\t\tgoto exit;\n+\t} else if (rc == 0) {\n+\t\t/* No meta data on disk yet */\n+\t\tif (!(fdp->flags & TEE_FS_O_CREATE))\n+\t\t\tgoto exit;\n+\t\trc = create_meta(errno, fdp);\n+\t} else if (rc == (int)msize) {\n+#ifdef CFG_ENC_FS\n+\t\tTEE_Result res;\n+\n+\t\tres = tee_fs_decrypt_file(META_FILE, meta, msize,\n+\t\t\t\t\t  (uint8_t *)&fdp->meta, &out_size,\n+\t\t\t\t\t  fdp->meta.encrypted_fek);\n+\t\tif (res != TEE_SUCCESS) {\n+\t\t\t*errno = res;\n+\t\t\tgoto exit;\n+\t\t}\n+#else\n+\t\tmemcpy((uint8_t *)&fdp->meta,\n+\t\t       meta + tee_fs_get_header_size(META_FILE),\n+\t\t       out_size);\n+#endif\n+\t} else {\n+\t\t/* Unexpected data length */\n+\t}\n+\n+\tif (rc >= 0)\n+\t\t*errno = TEE_SUCCESS;\n+exit:\n+\tfree(meta);\n+\treturn rc;\n+}\n+\n+\n+/*\n+ * Read one block of user data.\n+ * Returns:\n+ *  < 0: read error\n+ *    0: block does not exist (reading past last block)\n+ *  > 0: success\n+ */\n+static int read_block(TEE_Result *errno, struct sql_fs_fd *fdp, size_t bnum,\n+\t\t      uint8_t *data)\n+{\n+\tsize_t ct_size = block_size_raw();\n+\tsize_t out_size = BLOCK_SIZE;\n+\tssize_t pos = block_pos_raw(bnum);\n+\tuint8_t *ct = NULL;\n+\tint rc = -1;\n+\n+\tct = malloc(ct_size);\n+\tif (!ct) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = sql_fs_lseek_rpc(fdp->fd, pos, TEE_FS_SEEK_SET);\n+\tif (rc < 0) {\n+\t\t*errno = TEE_ERROR_GENERIC;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = sql_fs_read_rpc(fdp->fd, ct, ct_size);\n+\tif (rc < 0) {\n+\t\t*errno = TEE_ERROR_GENERIC;\n+\t\tgoto exit;\n+\t}\n+\tif (rc == 0) {\n+\t\t/* Block does not exist */\n+\t\tgoto exit;\n+\t}\n+\n+#ifdef CFG_ENC_FS\n+\t{\n+\t\tTEE_Result res;\n+\n+\t\tres = tee_fs_decrypt_file(BLOCK_FILE, ct, ct_size, data,\n+\t\t\t\t\t  &out_size, fdp->meta.encrypted_fek);\n+\t\tif (res != TEE_SUCCESS) {\n+\t\t\t*errno = res;\n+\t\t\trc = -1;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+#else\n+\tmemcpy(data, ct + tee_fs_get_header_size(BLOCK_FILE), out_size);\n+#endif\n+\n+exit:\n+\tfree(ct);\n+\treturn rc;\n+}\n+\n+/* Write one block of user data */\n+static int write_block(TEE_Result *errno, struct sql_fs_fd *fdp,\n+\t\t       size_t bnum, uint8_t *data)\n+{\n+\tsize_t ct_size = block_size_raw();\n+\tssize_t pos = block_pos_raw(bnum);\n+\tuint8_t *ct = NULL;\n+\tint rc = -1;\n+\n+\tct = malloc(ct_size);\n+\tif (!ct) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = sql_fs_lseek_rpc(fdp->fd, pos, TEE_FS_SEEK_SET);\n+\tif (rc < 0) {\n+\t\t*errno = TEE_ERROR_GENERIC;\n+\t\tgoto exit;\n+\t}\n+\n+#ifdef CFG_ENC_FS\n+\t{\n+\t\tTEE_Result res;\n+\n+\t\tres = tee_fs_encrypt_file(BLOCK_FILE, data, BLOCK_SIZE, ct,\n+\t\t\t\t\t  &ct_size, fdp->meta.encrypted_fek);\n+\t\tif (res != TEE_SUCCESS) {\n+\t\t\t*errno = res;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+#else\n+\tcopy_data(BLOCK_FILE, ct, data, BLOCK_SIZE);\n+#endif\n+\n+\trc = sql_fs_write_rpc(fdp->fd, ct, ct_size);\n+\tif (rc < 0) {\n+\t\t*errno = TEE_ERROR_GENERIC;\n+\t\tgoto exit;\n+\t}\n+\n+exit:\n+\tfree(ct);\n+\treturn rc;\n+}\n+\n+/* Partial write (< BLOCK_SIZE) into a block: read/update/write */\n+static int write_block_partial(TEE_Result *errno, struct sql_fs_fd *fdp,\n+\t\t\t       size_t bnum, const uint8_t *data, size_t len,\n+\t\t\t       size_t offset)\n+{\n+\tsize_t buf_size = BLOCK_SIZE;\n+\tuint8_t *buf = NULL;\n+\tint rc = -1;\n+\n+\tif ((offset >= buf_size) || (offset + len > buf_size)) {\n+\t\t*errno = TEE_ERROR_BAD_PARAMETERS;\n+\t\tgoto exit;\n+\t}\n+\n+\tbuf = malloc(buf_size);\n+\tif (!buf) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = read_block(errno, fdp, bnum, buf);\n+\tif (rc < 0)\n+\t\tgoto exit;\n+\n+\tmemcpy(buf + offset, data, len);\n+\n+\trc = write_block(errno, fdp, bnum, buf);\n+\n+exit:\n+\tfree(buf);\n+\treturn rc;\n+}\n+\n+static int sql_fs_ftruncate(TEE_Result *errno, int fd, tee_fs_off_t new_length)\n+{\n+\tstruct sql_fs_fd *fdp = handle_lookup(&fs_db, fd);\n+\ttee_fs_off_t old_length;\n+\tuint8_t *buf = NULL;\n+\tint rc = -1;\n+\n+\tDMSG(\"(fd: %d, new_length: %\" PRId64 \")...\", fd, new_length);\n+\n+\tif (!fdp) {\n+\t\t*errno = TEE_ERROR_BAD_PARAMETERS;\n+\t\tgoto exit_ret;\n+\t}\n+\n+\told_length = (tee_fs_off_t)fdp->meta.length;\n+\n+\tif (new_length == old_length) {\n+\t\trc = 0;\n+\t\tgoto exit_ret;\n+\t}\n+\n+\tsql_fs_begin_transaction_rpc();\n+\n+\tif (new_length < old_length) {\n+\t\t/* Trim unused blocks */\n+\t\tint old_last_block = block_num(old_length);\n+\t\tint last_block = block_num(new_length);\n+\t\ttee_fs_off_t off;\n+\n+\t\tif (last_block < old_last_block) {\n+\t\t\toff = block_pos_raw(last_block);\n+\t\t\trc = sql_fs_ftruncate_rpc(fd, off);\n+\t\t\tif (rc < 0)\n+\t\t\t\tgoto exit;\n+\t\t}\n+\t} else {\n+\t\t/* Extend file with zeroes */\n+\t\ttee_fs_off_t off = old_length % BLOCK_SIZE;\n+\t\tsize_t bnum = block_num(old_length);\n+\t\tsize_t end_bnum = block_num(new_length);\n+\n+\t\tbuf = calloc(1, BLOCK_SIZE);\n+\t\tif (!buf) {\n+\t\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\t\tgoto exit;\n+\t\t}\n+\n+\t\twhile (bnum <= end_bnum) {\n+\t\t\tsize_t len = (size_t)BLOCK_SIZE - (size_t)off;\n+\n+\t\t\trc = write_block_partial(errno, fdp, bnum, buf, len,\n+\t\t\t\t\t\t off);\n+\t\t\tif (rc < 0)\n+\t\t\t\tgoto exit;\n+\t\t\toff = 0;\n+\t\t\tbnum++;\n+\t\t}\n+\t}\n+\n+\tfdp->meta.length = new_length;\n+\trc = write_meta(errno, fdp);\n+\n+exit:\n+\tsql_fs_end_transaction_rpc(rc < 0);\n+\tfree(buf);\n+exit_ret:\n+\tDMSG(\"...%d\", rc);\n+\treturn rc;\n+}\n+\n+static tee_fs_off_t sql_fs_lseek(TEE_Result *errno, int fd,\n+\t\t\t\t tee_fs_off_t offset, int whence)\n+{\n+\tstruct sql_fs_fd *fdp = handle_lookup(&fs_db, fd);\n+\ttee_fs_off_t ret = -1;\n+\ttee_fs_off_t raw_pos;\n+\ttee_fs_off_t pos;\n+\n+\tDMSG(\"(fd: %d, offset: %\" PRId64 \", whence: %d)...\", fd, offset,\n+\t     whence);\n+\n+\tif (!fdp)\n+\t\tgoto exit_ret;\n+\n+\t*errno = TEE_ERROR_GENERIC;\n+\n+\tsql_fs_begin_transaction_rpc();\n+\n+\tswitch (whence) {\n+\tcase TEE_FS_SEEK_SET:\n+\t\tpos = offset;\n+\t\tbreak;\n+\n+\tcase TEE_FS_SEEK_CUR:\n+\t\tpos = fdp->pos + offset;\n+\t\tbreak;\n+\n+\tcase TEE_FS_SEEK_END:\n+\t\tpos = fdp->meta.length + offset;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\t*errno = TEE_ERROR_BAD_PARAMETERS;\n+\t\tgoto exit;\n+\t}\n+\n+\traw_pos = pos_to_raw(pos);\n+\tif (raw_pos < 0)\n+\t\tgoto exit;\n+\traw_pos = sql_fs_lseek_rpc(fd, raw_pos, TEE_FS_SEEK_SET);\n+\tif (raw_pos < 0)\n+\t\tgoto exit;\n+\tret = raw_to_pos(raw_pos);\n+\tif (ret < 0)\n+\t\tgoto exit;\n+\t*errno = TEE_SUCCESS;\n+exit:\n+\tsql_fs_end_transaction_rpc(ret < 0);\n+\tfdp->pos = ret;\n+exit_ret:\n+\tDMSG(\"...%\" PRId64, ret);\n+\treturn ret;\n+}\n+\n+static int sql_fs_close(int fd)\n+{\n+\tstruct sql_fs_fd *fdp = handle_lookup(&fs_db, fd);\n+\tint ret = -1;\n+\n+\tDMSG(\"(fd: %d)...\", fd);\n+\n+\tif (!fdp)\n+\t\tgoto exit;\n+\n+\tsql_fs_close_rpc(fd);\n+\tput_fdp(fdp);\n+\n+\tret = 0;\n+exit:\n+\tDMSG(\"...%d\", ret);\n+\treturn ret;\n+}\n+\n+static int sql_fs_open(TEE_Result *errno, const char *file, int flags, ...)\n+{\n+\tstruct sql_fs_fd *fdp = NULL;\n+\tint rflags = flags | TEE_FS_O_RDWR; /* Need to read/write meta */\n+\tint exists;\n+\tint fd = -1;\n+\n+\tDMSG(\"(file: %s, flags: %d)...\", file, flags);\n+\n+\texists = !sql_fs_access_rpc(file, TEE_FS_F_OK);\n+\tif (flags & TEE_FS_O_CREATE) {\n+\t\tif ((flags & TEE_FS_O_EXCL) && exists) {\n+\t\t\t*errno = TEE_ERROR_ACCESS_CONFLICT;\n+\t\t\tgoto exit;\n+\t\t}\n+\t} else {\n+\t\tif (!exists) {\n+\t\t\t*errno = TEE_ERROR_ITEM_NOT_FOUND;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+\n+\tfdp = (struct sql_fs_fd *)calloc(1, sizeof(*fdp));\n+\tif (!fdp) {\n+\t\t*errno = TEE_ERROR_OUT_OF_MEMORY;\n+\t\tgoto exit;\n+\t}\n+\n+\tfdp->fd = sql_fs_open_rpc(errno, file, rflags);\n+\tif (fdp->fd < 0)\n+\t\tgoto exit;\n+\n+\tfdp->flags = flags;\n+\n+\tfd = read_meta(errno, fdp);\n+\tif (fd < 0)\n+\t\tgoto exit;\n+\n+\tfd = handle_get(&fs_db, fdp);\n+\n+exit:\n+\tif (fd < 0)\n+\t\tfree(fdp);\n+\tDMSG(\"...%d\", fd);\n+\treturn fd;\n+}\n+\n+static int sql_fs_read(TEE_Result *errno, int fd, void *buf, size_t len)\n+{\n+\tstruct sql_fs_fd *fdp = handle_lookup(&fs_db, fd);\n+\tsize_t remain_bytes = len;\n+\tuint8_t *data_ptr = buf;\n+\tuint8_t *block = NULL;\n+\tint start_block_num;\n+\tint end_block_num;\n+\tint res = -1;\n+\tint ret;\n+\n+\tDMSG(\"(fd: %d, buf: %p, len: %zu)...\", fd, (void *)buf, len);\n+\n+\tif (!fdp) {\n+\t\t*errno = TEE_ERROR_BAD_PARAMETERS;\n+\t\tgoto exit;\n+\t}\n+\n+\tif (fdp->pos + len > fdp->meta.length)\n+\t\tlen = fdp->meta.length - fdp->pos;\n+\n+\tif (!len) {\n+\t\tres = 0;\n+\t\tgoto exit;\n+\t}\n+\n+\tif (!buf) {\n+\t\t*errno = TEE_ERROR_BAD_PARAMETERS;\n+\t\tgoto exit;\n+\t}\n+\n+\tif (fdp->flags & TEE_FS_O_WRONLY) {\n+\t\t*errno = TEE_ERROR_ACCESS_CONFLICT;\n+\t\tgoto exit;\n+\t}\n+\n+\tstart_block_num = block_num(fdp->pos);\n+\tend_block_num = block_num(fdp->pos + len + 1);","path":"core/tee/tee_sql_fs.c","position":746,"original_position":746,"commit_id":"772653438970a01729cab6910e1776e840697056","original_commit_id":"772653438970a01729cab6910e1776e840697056","user":{"login":"etiennec-linaro","id":19990310,"avatar_url":"https://avatars.githubusercontent.com/u/19990310?v=3","gravatar_id":"","url":"https://api.github.com/users/etiennec-linaro","html_url":"https://github.com/etiennec-linaro","followers_url":"https://api.github.com/users/etiennec-linaro/followers","following_url":"https://api.github.com/users/etiennec-linaro/following{/other_user}","gists_url":"https://api.github.com/users/etiennec-linaro/gists{/gist_id}","starred_url":"https://api.github.com/users/etiennec-linaro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/etiennec-linaro/subscriptions","organizations_url":"https://api.github.com/users/etiennec-linaro/orgs","repos_url":"https://api.github.com/users/etiennec-linaro/repos","events_url":"https://api.github.com/users/etiennec-linaro/events{/privacy}","received_events_url":"https://api.github.com/users/etiennec-linaro/received_events","type":"User","site_admin":false},"body":"if `(fdp->pos + len)` equals the start address of a block, `end_block_num = block_num(fdp->pos + len + 1);` will go 1 block ahead than expected.","created_at":"2016-07-20T11:15:12Z","updated_at":"2016-07-20T11:15:12Z","html_url":"https://github.com/OP-TEE/optee_os/pull/797#discussion_r71506267","pull_request_url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797","_links":{"self":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/comments/71506267"},"html":{"href":"https://github.com/OP-TEE/optee_os/pull/797#discussion_r71506267"},"pull_request":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797"}}},"pull_request":{"url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797","id":70530109,"html_url":"https://github.com/OP-TEE/optee_os/pull/797","diff_url":"https://github.com/OP-TEE/optee_os/pull/797.diff","patch_url":"https://github.com/OP-TEE/optee_os/pull/797.patch","issue_url":"https://api.github.com/repos/OP-TEE/optee_os/issues/797","number":797,"state":"open","locked":false,"title":"SQL FS","user":{"login":"jforissier","id":8288195,"avatar_url":"https://avatars.githubusercontent.com/u/8288195?v=3","gravatar_id":"","url":"https://api.github.com/users/jforissier","html_url":"https://github.com/jforissier","followers_url":"https://api.github.com/users/jforissier/followers","following_url":"https://api.github.com/users/jforissier/following{/other_user}","gists_url":"https://api.github.com/users/jforissier/gists{/gist_id}","starred_url":"https://api.github.com/users/jforissier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jforissier/subscriptions","organizations_url":"https://api.github.com/users/jforissier/orgs","repos_url":"https://api.github.com/users/jforissier/repos","events_url":"https://api.github.com/users/jforissier/events{/privacy}","received_events_url":"https://api.github.com/users/jforissier/received_events","type":"User","site_admin":false},"body":"Depends on https://github.com/OP-TEE/optee_client/pull/50.","created_at":"2016-05-18T13:44:48Z","updated_at":"2016-07-20T11:15:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bed8cf1ce1debd4849311b6ba859ea35d2e43596","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797/commits","review_comments_url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797/comments","review_comment_url":"https://api.github.com/repos/OP-TEE/optee_os/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OP-TEE/optee_os/issues/797/comments","statuses_url":"https://api.github.com/repos/OP-TEE/optee_os/statuses/772653438970a01729cab6910e1776e840697056","head":{"label":"jforissier:sqlfs","ref":"sqlfs","sha":"772653438970a01729cab6910e1776e840697056","user":{"login":"jforissier","id":8288195,"avatar_url":"https://avatars.githubusercontent.com/u/8288195?v=3","gravatar_id":"","url":"https://api.github.com/users/jforissier","html_url":"https://github.com/jforissier","followers_url":"https://api.github.com/users/jforissier/followers","following_url":"https://api.github.com/users/jforissier/following{/other_user}","gists_url":"https://api.github.com/users/jforissier/gists{/gist_id}","starred_url":"https://api.github.com/users/jforissier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jforissier/subscriptions","organizations_url":"https://api.github.com/users/jforissier/orgs","repos_url":"https://api.github.com/users/jforissier/repos","events_url":"https://api.github.com/users/jforissier/events{/privacy}","received_events_url":"https://api.github.com/users/jforissier/received_events","type":"User","site_admin":false},"repo":{"id":22514248,"name":"optee_os","full_name":"jforissier/optee_os","owner":{"login":"jforissier","id":8288195,"avatar_url":"https://avatars.githubusercontent.com/u/8288195?v=3","gravatar_id":"","url":"https://api.github.com/users/jforissier","html_url":"https://github.com/jforissier","followers_url":"https://api.github.com/users/jforissier/followers","following_url":"https://api.github.com/users/jforissier/following{/other_user}","gists_url":"https://api.github.com/users/jforissier/gists{/gist_id}","starred_url":"https://api.github.com/users/jforissier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jforissier/subscriptions","organizations_url":"https://api.github.com/users/jforissier/orgs","repos_url":"https://api.github.com/users/jforissier/repos","events_url":"https://api.github.com/users/jforissier/events{/privacy}","received_events_url":"https://api.github.com/users/jforissier/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jforissier/optee_os","description":"Trusted side of the TEE","fork":true,"url":"https://api.github.com/repos/jforissier/optee_os","forks_url":"https://api.github.com/repos/jforissier/optee_os/forks","keys_url":"https://api.github.com/repos/jforissier/optee_os/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jforissier/optee_os/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jforissier/optee_os/teams","hooks_url":"https://api.github.com/repos/jforissier/optee_os/hooks","issue_events_url":"https://api.github.com/repos/jforissier/optee_os/issues/events{/number}","events_url":"https://api.github.com/repos/jforissier/optee_os/events","assignees_url":"https://api.github.com/repos/jforissier/optee_os/assignees{/user}","branches_url":"https://api.github.com/repos/jforissier/optee_os/branches{/branch}","tags_url":"https://api.github.com/repos/jforissier/optee_os/tags","blobs_url":"https://api.github.com/repos/jforissier/optee_os/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jforissier/optee_os/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jforissier/optee_os/git/refs{/sha}","trees_url":"https://api.github.com/repos/jforissier/optee_os/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jforissier/optee_os/statuses/{sha}","languages_url":"https://api.github.com/repos/jforissier/optee_os/languages","stargazers_url":"https://api.github.com/repos/jforissier/optee_os/stargazers","contributors_url":"https://api.github.com/repos/jforissier/optee_os/contributors","subscribers_url":"https://api.github.com/repos/jforissier/optee_os/subscribers","subscription_url":"https://api.github.com/repos/jforissier/optee_os/subscription","commits_url":"https://api.github.com/repos/jforissier/optee_os/commits{/sha}","git_commits_url":"https://api.github.com/repos/jforissier/optee_os/git/commits{/sha}","comments_url":"https://api.github.com/repos/jforissier/optee_os/comments{/number}","issue_comment_url":"https://api.github.com/repos/jforissier/optee_os/issues/comments{/number}","contents_url":"https://api.github.com/repos/jforissier/optee_os/contents/{+path}","compare_url":"https://api.github.com/repos/jforissier/optee_os/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jforissier/optee_os/merges","archive_url":"https://api.github.com/repos/jforissier/optee_os/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jforissier/optee_os/downloads","issues_url":"https://api.github.com/repos/jforissier/optee_os/issues{/number}","pulls_url":"https://api.github.com/repos/jforissier/optee_os/pulls{/number}","milestones_url":"https://api.github.com/repos/jforissier/optee_os/milestones{/number}","notifications_url":"https://api.github.com/repos/jforissier/optee_os/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jforissier/optee_os/labels{/name}","releases_url":"https://api.github.com/repos/jforissier/optee_os/releases{/id}","deployments_url":"https://api.github.com/repos/jforissier/optee_os/deployments","created_at":"2014-08-01T14:48:31Z","updated_at":"2016-03-11T08:17:47Z","pushed_at":"2016-07-19T09:27:00Z","git_url":"git://github.com/jforissier/optee_os.git","ssh_url":"git@github.com:jforissier/optee_os.git","clone_url":"https://github.com/jforissier/optee_os.git","svn_url":"https://github.com/jforissier/optee_os","homepage":null,"size":9482,"stargazers_count":2,"watchers_count":2,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":2,"default_branch":"master"}},"base":{"label":"OP-TEE:master","ref":"master","sha":"2a7f41713ebc204566268e8e94517ee4ee879d44","user":{"login":"OP-TEE","id":7488961,"avatar_url":"https://avatars.githubusercontent.com/u/7488961?v=3","gravatar_id":"","url":"https://api.github.com/users/OP-TEE","html_url":"https://github.com/OP-TEE","followers_url":"https://api.github.com/users/OP-TEE/followers","following_url":"https://api.github.com/users/OP-TEE/following{/other_user}","gists_url":"https://api.github.com/users/OP-TEE/gists{/gist_id}","starred_url":"https://api.github.com/users/OP-TEE/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OP-TEE/subscriptions","organizations_url":"https://api.github.com/users/OP-TEE/orgs","repos_url":"https://api.github.com/users/OP-TEE/repos","events_url":"https://api.github.com/users/OP-TEE/events{/privacy}","received_events_url":"https://api.github.com/users/OP-TEE/received_events","type":"Organization","site_admin":false},"repo":{"id":20193261,"name":"optee_os","full_name":"OP-TEE/optee_os","owner":{"login":"OP-TEE","id":7488961,"avatar_url":"https://avatars.githubusercontent.com/u/7488961?v=3","gravatar_id":"","url":"https://api.github.com/users/OP-TEE","html_url":"https://github.com/OP-TEE","followers_url":"https://api.github.com/users/OP-TEE/followers","following_url":"https://api.github.com/users/OP-TEE/following{/other_user}","gists_url":"https://api.github.com/users/OP-TEE/gists{/gist_id}","starred_url":"https://api.github.com/users/OP-TEE/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OP-TEE/subscriptions","organizations_url":"https://api.github.com/users/OP-TEE/orgs","repos_url":"https://api.github.com/users/OP-TEE/repos","events_url":"https://api.github.com/users/OP-TEE/events{/privacy}","received_events_url":"https://api.github.com/users/OP-TEE/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OP-TEE/optee_os","description":"Trusted side of the TEE","fork":false,"url":"https://api.github.com/repos/OP-TEE/optee_os","forks_url":"https://api.github.com/repos/OP-TEE/optee_os/forks","keys_url":"https://api.github.com/repos/OP-TEE/optee_os/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OP-TEE/optee_os/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OP-TEE/optee_os/teams","hooks_url":"https://api.github.com/repos/OP-TEE/optee_os/hooks","issue_events_url":"https://api.github.com/repos/OP-TEE/optee_os/issues/events{/number}","events_url":"https://api.github.com/repos/OP-TEE/optee_os/events","assignees_url":"https://api.github.com/repos/OP-TEE/optee_os/assignees{/user}","branches_url":"https://api.github.com/repos/OP-TEE/optee_os/branches{/branch}","tags_url":"https://api.github.com/repos/OP-TEE/optee_os/tags","blobs_url":"https://api.github.com/repos/OP-TEE/optee_os/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OP-TEE/optee_os/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OP-TEE/optee_os/git/refs{/sha}","trees_url":"https://api.github.com/repos/OP-TEE/optee_os/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OP-TEE/optee_os/statuses/{sha}","languages_url":"https://api.github.com/repos/OP-TEE/optee_os/languages","stargazers_url":"https://api.github.com/repos/OP-TEE/optee_os/stargazers","contributors_url":"https://api.github.com/repos/OP-TEE/optee_os/contributors","subscribers_url":"https://api.github.com/repos/OP-TEE/optee_os/subscribers","subscription_url":"https://api.github.com/repos/OP-TEE/optee_os/subscription","commits_url":"https://api.github.com/repos/OP-TEE/optee_os/commits{/sha}","git_commits_url":"https://api.github.com/repos/OP-TEE/optee_os/git/commits{/sha}","comments_url":"https://api.github.com/repos/OP-TEE/optee_os/comments{/number}","issue_comment_url":"https://api.github.com/repos/OP-TEE/optee_os/issues/comments{/number}","contents_url":"https://api.github.com/repos/OP-TEE/optee_os/contents/{+path}","compare_url":"https://api.github.com/repos/OP-TEE/optee_os/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OP-TEE/optee_os/merges","archive_url":"https://api.github.com/repos/OP-TEE/optee_os/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OP-TEE/optee_os/downloads","issues_url":"https://api.github.com/repos/OP-TEE/optee_os/issues{/number}","pulls_url":"https://api.github.com/repos/OP-TEE/optee_os/pulls{/number}","milestones_url":"https://api.github.com/repos/OP-TEE/optee_os/milestones{/number}","notifications_url":"https://api.github.com/repos/OP-TEE/optee_os/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OP-TEE/optee_os/labels{/name}","releases_url":"https://api.github.com/repos/OP-TEE/optee_os/releases{/id}","deployments_url":"https://api.github.com/repos/OP-TEE/optee_os/deployments","created_at":"2014-05-26T17:18:57Z","updated_at":"2016-07-18T09:29:32Z","pushed_at":"2016-07-20T08:22:19Z","git_url":"git://github.com/OP-TEE/optee_os.git","ssh_url":"git@github.com:OP-TEE/optee_os.git","clone_url":"https://github.com/OP-TEE/optee_os.git","svn_url":"https://github.com/OP-TEE/optee_os","homepage":null,"size":10702,"stargazers_count":136,"watchers_count":136,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":141,"mirror_url":null,"open_issues_count":39,"forks":141,"open_issues":39,"watchers":136,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797"},"html":{"href":"https://github.com/OP-TEE/optee_os/pull/797"},"issue":{"href":"https://api.github.com/repos/OP-TEE/optee_os/issues/797"},"comments":{"href":"https://api.github.com/repos/OP-TEE/optee_os/issues/797/comments"},"review_comments":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797/comments"},"review_comment":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OP-TEE/optee_os/pulls/797/commits"},"statuses":{"href":"https://api.github.com/repos/OP-TEE/optee_os/statuses/772653438970a01729cab6910e1776e840697056"}}}}
{"actor":{"display_login":"etiennec-linaro"}}