Add new RPC FS functions with useful error codes
As the interface is changed to use proper error codes, the way
parameters are passed is also updated.
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (HiKey)
Tested-by: Jens Wiklander <jens.wiklander@linaro.org> (QEMU)
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/tee-supplicant/src/optee_msg_fs.h b/tee-supplicant/src/optee_msg_fs.h
new file mode 100644
index 0000000..6a5fcd7
--- /dev/null
+++ b/tee-supplicant/src/optee_msg_fs.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OPTEE_MSG_FS_H
+#define __OPTEE_MSG_FS_H
+
+/*
+ * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_FS
+ * and first parameter has the attribute OPTEE_MSG_ATTR_TYPE_VALUE_INPUT.
+ */
+
+/*
+ * Open a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_OPEN
+ * [in] param[1].u.tmem a string holding the file name
+ * [out] param[2].u.value.a file descriptor of open file
+ */
+#define OPTEE_MRF_OPEN 0
+
+/*
+ * Create a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_CREATE
+ * [in] param[1].u.tmem a string holding the file name
+ * [out] param[2].u.value.a file descriptor of open file
+ */
+#define OPTEE_MRF_CREATE 1
+
+/*
+ * Close a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_CLOSE
+ * [in] param[0].u.value.b file descriptor of open file.
+ */
+#define OPTEE_MRF_CLOSE 2
+
+/*
+ * Read from a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_READ
+ * [in] param[0].u.value.b file descriptor of open file
+ * [in] param[0].u.value.c offset into file
+ * [out] param[1].u.tmem buffer to hold returned data
+ */
+#define OPTEE_MRF_READ 3
+
+/*
+ * Write to a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_WRITE
+ * [in] param[0].u.value.b file descriptor of open file
+ * [in] param[0].u.value.c offset into file
+ * [in] param[1].u.tmem buffer holding data to be written
+ */
+#define OPTEE_MRF_WRITE 4
+
+/*
+ * Truncate a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_TRUNCATE
+ * [in] param[0].u.value.b file descriptor of open file
+ * [in] param[0].u.value.c length of file.
+ */
+#define OPTEE_MRF_TRUNCATE 5
+
+/*
+ * Remove a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_REMOVE
+ * [in] param[1].u.tmem a string holding the file name
+ */
+#define OPTEE_MRF_REMOVE 6
+
+/*
+ * Rename a file
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_RENAME
+ * [in] param[0].u.value.b true if existing target should be removed
+ * [in] param[1].u.tmem a string holding the old file name
+ * [in] param[2].u.tmem a string holding the new file name
+ */
+#define OPTEE_MRF_RENAME 7
+
+/*
+ * Opens a directory for file listing
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_OPENDIR
+ * [in] param[1].u.tmem a string holding the name of the directory
+ * [out] param[2].u.value.a handle to open directory
+ */
+#define OPTEE_MRF_OPENDIR 8
+
+/*
+ * Closes a directory handle
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_CLOSEDIR
+ * [in] param[0].u.value.b handle to open directory
+ */
+#define OPTEE_MRF_CLOSEDIR 9
+
+/*
+ * Read next file name of directory
+ *
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_READDIR
+ * [in] param[0].u.value.b handle to open directory
+ * [out] param[1].u.tmem a string holding the file name
+ */
+#define OPTEE_MRF_READDIR 10
+
+/*
+ * Begins a new transaction (only valid for SQL FS)
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_BEGIN_TRANSACTION
+ */
+#define OPTEE_MRF_BEGIN_TRANSACTION 11
+
+/*
+ * Ends a transaction (only valid for SQL FS)
+ *
+ * [in] param[0].u.value.a OPTEE_MRF_END_TRANSACTION
+ * [in] param[0].u.value.b true if rolling back to previous state
+ */
+#define OPTEE_MRF_END_TRANSACTION 12
+
+#endif /*__OPTEE_MSG_FS_H*/
diff --git a/tee-supplicant/src/sql_fs.c b/tee-supplicant/src/sql_fs.c
index b96748d..329fbe6 100644
--- a/tee-supplicant/src/sql_fs.c
+++ b/tee-supplicant/src/sql_fs.c
@@ -28,6 +28,8 @@
#include <assert.h>
#include <errno.h>
#include <handle.h>
+#include <libgen.h>
+#include <optee_msg_fs.h>
#include <sql_fs.h>
#include <sqlfs.h>
#include <sqlfs_internal.h>
@@ -35,9 +37,15 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
-#include <tee_fs.h>
-
#include <teec_trace.h>
+#include <tee_fs.h>
+#include <tee_supplicant.h>
+
+
+#ifndef __aligned
+#define __aligned(x) __attribute__((__aligned__(x)))
+#endif
+#include <linux/tee.h>
/*
* File handles
@@ -450,74 +458,503 @@
* used for convenience (debugging). The caller (OP-TEE) should not depend on
* these exact values as they obviously depend on the Operating System.
*/
-int sql_fs_process(void *cmd, size_t cmd_size)
+static TEEC_Result sql_fs_process_primitive(void *cmd, size_t cmd_size)
{
struct tee_fs_rpc *fsrpc = cmd;
- int st;
if (cmd_size < sizeof(struct tee_fs_rpc))
- return -1;
+ return TEEC_ERROR_BAD_PARAMETERS;
if (!cmd)
- return -1;
+ return TEEC_ERROR_BAD_PARAMETERS;
switch (fsrpc->op) {
case TEE_FS_OPEN:
- st = sql_fs_open(fsrpc);
+ fsrpc->res = sql_fs_open(fsrpc);
break;
case TEE_FS_CLOSE:
- st = sql_fs_close(fsrpc);
+ fsrpc->res = sql_fs_close(fsrpc);
break;
case TEE_FS_READ:
- st = sql_fs_read(fsrpc);
+ fsrpc->res = sql_fs_read(fsrpc);
break;
case TEE_FS_WRITE:
- st = sql_fs_write(fsrpc);
+ fsrpc->res = sql_fs_write(fsrpc);
break;
case TEE_FS_SEEK:
- st = sql_fs_seek(fsrpc);
+ fsrpc->res = sql_fs_seek(fsrpc);
break;
case TEE_FS_UNLINK:
- st = sql_fs_unlink(fsrpc);
+ fsrpc->res = sql_fs_unlink(fsrpc);
break;
case TEE_FS_RENAME:
- st = sql_fs_rename(fsrpc);
+ fsrpc->res = sql_fs_rename(fsrpc);
break;
case TEE_FS_TRUNC:
- st = sql_fs_truncate(fsrpc);
+ fsrpc->res = sql_fs_truncate(fsrpc);
break;
case TEE_FS_MKDIR:
- st = sql_fs_mkdir(fsrpc);
+ fsrpc->res = sql_fs_mkdir(fsrpc);
break;
case TEE_FS_OPENDIR:
- st = sql_fs_opendir(fsrpc);
+ fsrpc->res = sql_fs_opendir(fsrpc);
break;
case TEE_FS_CLOSEDIR:
- st = sql_fs_closedir(fsrpc);
+ fsrpc->res = sql_fs_closedir(fsrpc);
break;
case TEE_FS_READDIR:
- st = sql_fs_readdir(fsrpc);
+ fsrpc->res = sql_fs_readdir(fsrpc);
break;
case TEE_FS_RMDIR:
- st = sql_fs_rmdir(fsrpc);
+ fsrpc->res = sql_fs_rmdir(fsrpc);
break;
case TEE_FS_ACCESS:
- st = sql_fs_access(fsrpc);
+ fsrpc->res = sql_fs_access(fsrpc);
break;
case TEE_FS_LINK:
- st = -ENOTSUP;
+ fsrpc->res = -ENOTSUP;
break;
case TEE_FS_BEGIN:
- st = sql_fs_begin();
+ fsrpc->res = sql_fs_begin();
break;
case TEE_FS_END:
- st = sql_fs_end(fsrpc);
+ fsrpc->res = sql_fs_end(fsrpc);
break;
default:
EMSG("Unexpected SQL FS operation: %d", fsrpc->op);
- return -1;
+ return TEEC_ERROR_NOT_SUPPORTED;
}
- fsrpc->res = st;
- return 0;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_open(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+ char *fname;
+ int rc;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = new_file(fname);
+ if (!fs)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ fs->fi.flags = O_RDWR;
+ rc = sqlfs_proc_open(db, fname, &fs->fi);
+ if (rc < 0) {
+ put_file(fs);
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ }
+
+ params[2].u.value.a = fs->fd;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_create(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+ char *fname;
+ int rc;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = new_file(fname);
+ if (!fs)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ fs->fi.flags = O_RDWR | O_CREAT | O_TRUNC;
+ rc = sqlfs_proc_open(db, fname, &fs->fi);
+ if (rc < 0) {
+ put_file(fs);
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ }
+
+ params[2].u.value.a = fs->fd;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_close(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = handle_lookup(&fd_db, params[0].u.value.b);
+ if (!fs)
+ return TEEC_ERROR_GENERIC;
+
+ put_file(fs);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_read(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+ void *buf;
+ size_t len;
+ off_t offs;
+ int rc;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = handle_lookup(&fd_db, params[0].u.value.b);
+ if (!fs)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ offs = params[0].u.value.c;
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ rc = sqlfs_proc_read(db, fs->path, buf, len, offs, &fs->fi);
+ if (rc < 0)
+ return TEEC_ERROR_GENERIC;
+
+ params[1].u.memref.size = rc;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_write(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+ void *buf;
+ size_t len;
+ off_t offs;
+ int rc;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = handle_lookup(&fd_db, params[0].u.value.b);
+ if (!fs)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ offs = params[0].u.value.c;
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ rc = sqlfs_proc_write(db, fs->path, buf, len, offs, &fs->fi);
+ if (rc != (int)len)
+ return TEEC_ERROR_GENERIC;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_truncate(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct file_state *fs;
+ size_t len;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fs = handle_lookup(&fd_db, params[0].u.value.b);
+ if (!fs)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ len = params[0].u.value.c;
+
+ if (sqlfs_proc_truncate(db, fs->path, len))
+ return TEEC_ERROR_GENERIC;
+
+ return TEEC_SUCCESS;
+}
+
+static void remove_dirname(const char *fname)
+{
+ char *dir = strdup(fname);
+ char *d;
+
+ if (!dir)
+ return;
+
+ d = dirname(dir);
+ sqlfs_proc_rmdir(db, d);
+ free(dir);
+}
+
+static TEEC_Result sql_fs_new_remove(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char *fname;
+ int rc;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ rc = sqlfs_proc_unlink(db, fname);
+ if (rc) {
+ if (rc == -ENOENT)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ return TEEC_ERROR_GENERIC;
+ }
+ remove_dirname(fname);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_rename(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char *old_fname;
+ char *new_fname;
+ bool overwrite;
+ int rc;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ overwrite = !!params[0].u.value.b;
+
+ old_fname = tee_supp_param_to_va(params + 1);
+ if (!old_fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ new_fname = tee_supp_param_to_va(params + 2);
+ if (!new_fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!overwrite) {
+ struct stat st;
+
+ if (!sqlfs_proc_getattr(db, new_fname, &st))
+ return TEEC_ERROR_ACCESS_CONFLICT;
+ }
+
+ rc = sqlfs_proc_rename(db, old_fname, new_fname);
+ if (rc) {
+ if (rc == -EIO)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ return TEEC_ERROR_GENERIC;
+ }
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_opendir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char *fname;
+ struct dir_state *ds;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ ds = new_dir();
+ if (!ds)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ if (sqlfs_proc_readdir(db, fname, ds, fill_dir, 0, NULL)) {
+ put_dir(ds);
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ }
+
+ params[2].u.value.a = ds->handle;
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_closedir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct dir_state *ds;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ ds = handle_lookup(&dir_db, params[0].u.value.b);
+ if (!ds)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ put_dir(ds);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_readdir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ struct dir_state *ds;
+ struct dir_entry *de;
+ char *buf;
+ size_t len;
+ size_t fname_len;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ ds = handle_lookup(&dir_db, params[0].u.value.b);
+ if (!ds)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ de = TAILQ_FIRST(&ds->dir_entries);
+ if (!de)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+
+ fname_len = strlen(de->name) + 1;
+ params[1].u.memref.size = fname_len;
+ if (fname_len > len)
+ return TEEC_ERROR_SHORT_BUFFER;
+
+ memcpy(buf, de->name, fname_len);
+ TAILQ_REMOVE(&ds->dir_entries, de, link);
+ free(de);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result sql_fs_new_begin_transaction(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (sqlfs_begin_transaction(db))
+ return TEEC_SUCCESS;
+ return TEEC_ERROR_GENERIC;
+}
+
+static TEEC_Result sql_fs_new_end_transaction(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (sqlfs_complete_transaction(db, !params[0].u.value.b))
+ return TEEC_SUCCESS;
+ return TEEC_ERROR_GENERIC;
+}
+
+TEEC_Result sql_fs_process(struct tee_iocl_supp_recv_arg *recv)
+{
+ struct tee_ioctl_param *param = (void *)(recv + 1);
+
+ if (recv->num_params == 1 && tee_supp_param_is_memref(param)) {
+ void *va = tee_supp_param_to_va(param);
+
+ if (!va)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ return sql_fs_process_primitive(va, param->u.memref.size);
+ }
+
+ if (!tee_supp_param_is_value(param))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ switch (param->u.value.a) {
+ case OPTEE_MRF_OPEN:
+ return sql_fs_new_open(recv->num_params, param);
+ case OPTEE_MRF_CREATE:
+ return sql_fs_new_create(recv->num_params, param);
+ case OPTEE_MRF_CLOSE:
+ return sql_fs_new_close(recv->num_params, param);
+ case OPTEE_MRF_READ:
+ return sql_fs_new_read(recv->num_params, param);
+ case OPTEE_MRF_WRITE:
+ return sql_fs_new_write(recv->num_params, param);
+ case OPTEE_MRF_TRUNCATE:
+ return sql_fs_new_truncate(recv->num_params, param);
+ case OPTEE_MRF_REMOVE:
+ return sql_fs_new_remove(recv->num_params, param);
+ case OPTEE_MRF_RENAME:
+ return sql_fs_new_rename(recv->num_params, param);
+ case OPTEE_MRF_OPENDIR:
+ return sql_fs_new_opendir(recv->num_params, param);
+ case OPTEE_MRF_CLOSEDIR:
+ return sql_fs_new_closedir(recv->num_params, param);
+ case OPTEE_MRF_READDIR:
+ return sql_fs_new_readdir(recv->num_params, param);
+ case OPTEE_MRF_BEGIN_TRANSACTION:
+ return sql_fs_new_begin_transaction(recv->num_params, param);
+ case OPTEE_MRF_END_TRANSACTION:
+ return sql_fs_new_end_transaction(recv->num_params, param);
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
}
diff --git a/tee-supplicant/src/sql_fs.h b/tee-supplicant/src/sql_fs.h
index d5d09a6..30ac1e3 100644
--- a/tee-supplicant/src/sql_fs.h
+++ b/tee-supplicant/src/sql_fs.h
@@ -27,26 +27,27 @@
#ifndef SQL_FS_H
#define SQL_FS_H
+#include <tee_client_api.h>
+
+struct tee_iocl_supp_recv_arg;
+
#ifdef CFG_SQL_FS
int sql_fs_init(void);
-int sql_fs_process(void *cmd, size_t cmd_size);
+TEEC_Result sql_fs_process(struct tee_iocl_supp_recv_arg *recv);
#else
-#include <errno.h>
-
static inline int sql_fs_init(void)
{
return 0;
}
-static inline int sql_fs_process(void *cmd, size_t cmd_size)
+static inline TEEC_Result sql_fs_process(struct tee_iocl_supp_recv_arg *recv)
{
- (void)cmd;
- (void)cmd_size;
+ (void)recv;
- return -ENOTSUP;
+ return TEEC_ERROR_NOT_SUPPORTED;
}
#endif
diff --git a/tee-supplicant/src/tee_supp_fs.c b/tee-supplicant/src/tee_supp_fs.c
index cf225b7..246c4a9 100644
--- a/tee-supplicant/src/tee_supp_fs.c
+++ b/tee-supplicant/src/tee_supp_fs.c
@@ -24,16 +24,28 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <stdint.h>
+#include <assert.h>
#include <dirent.h>
-#include <unistd.h>
-#include <string.h>
-#include <tee_supp_fs.h>
+#include <errno.h>
+#include <fcntl.h>
#include <handle.h>
+#include <libgen.h>
+#include <optee_msg_fs.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <teec_trace.h>
#include <tee_fs.h>
+#include <tee_supp_fs.h>
+#include <tee_supplicant.h>
+#include <unistd.h>
+
+#ifndef __aligned
+#define __aligned(x) __attribute__((__aligned__(x)))
+#endif
+#include <linux/tee.h>
/* Path to all secure storage files. */
#define TEE_FS_SUBPATH "/data"
@@ -187,10 +199,10 @@
static int tee_fs_mkdir(struct tee_fs_rpc *fsrpc)
{
char abs_dirname[PATH_MAX];
- char *dirname = (char *)(fsrpc + 1);
+ char *dname = (char *)(fsrpc + 1);
mode_t mode;
int ret = -1; /* Same as mkir on error */
- size_t filesize = tee_fs_get_absolute_filename(dirname, abs_dirname,
+ size_t filesize = tee_fs_get_absolute_filename(dname, abs_dirname,
sizeof(abs_dirname));
if (filesize) {
@@ -204,10 +216,10 @@
static int tee_fs_opendir(struct tee_fs_rpc *fsrpc)
{
char abs_dirname[PATH_MAX];
- char *dirname = (char *)(fsrpc + 1);
+ char *dname = (char *)(fsrpc + 1);
DIR *dir;
int handle = -1;
- size_t filesize = tee_fs_get_absolute_filename(dirname, abs_dirname,
+ size_t filesize = tee_fs_get_absolute_filename(dname, abs_dirname,
sizeof(abs_dirname));
if (!filesize)
goto exit;
@@ -232,7 +244,7 @@
static int tee_fs_readdir(struct tee_fs_rpc *fsrpc)
{
- char *dirname = (char *)(fsrpc + 1);
+ char *dname = (char *)(fsrpc + 1);
DIR *dir = handle_lookup(&dir_handle_db, fsrpc->arg);
struct dirent *dirent;
size_t len;
@@ -251,7 +263,7 @@
return -1;
len++;
- memcpy(dirname, dirent->d_name, len);
+ memcpy(dname, dirent->d_name, len);
fsrpc->len = len;
return 0;
@@ -260,9 +272,9 @@
static int tee_fs_rmdir(struct tee_fs_rpc *fsrpc)
{
char abs_dirname[PATH_MAX];
- char *dirname = (char *)(fsrpc + 1);
+ char *dname = (char *)(fsrpc + 1);
int ret = -1; /* Corresponds to the error value for rmdir */
- size_t filesize = tee_fs_get_absolute_filename(dirname, abs_dirname,
+ size_t filesize = tee_fs_get_absolute_filename(dname, abs_dirname,
sizeof(abs_dirname));
if (filesize)
@@ -298,67 +310,549 @@
return 0;
}
-int tee_supp_fs_process(void *cmd, size_t cmd_size)
+static TEEC_Result tee_supp_fs_process_primitive(void *cmd, size_t cmd_size)
{
struct tee_fs_rpc *fsrpc = cmd;
- int ret = -1;
if (cmd_size < sizeof(struct tee_fs_rpc))
- return ret;
+ return TEEC_ERROR_BAD_PARAMETERS;
- if (cmd == NULL)
- return ret;
+ if (!cmd)
+ return TEEC_ERROR_BAD_PARAMETERS;
switch (fsrpc->op) {
case TEE_FS_OPEN:
- ret = tee_fs_open(fsrpc);
+ fsrpc->res = tee_fs_open(fsrpc);
break;
case TEE_FS_CLOSE:
- ret = tee_fs_close(fsrpc);
+ fsrpc->res = tee_fs_close(fsrpc);
break;
case TEE_FS_READ:
- ret = tee_fs_read(fsrpc);
+ fsrpc->res = tee_fs_read(fsrpc);
break;
case TEE_FS_WRITE:
- ret = tee_fs_write(fsrpc);
+ fsrpc->res = tee_fs_write(fsrpc);
break;
case TEE_FS_SEEK:
- ret = tee_fs_seek(fsrpc);
+ fsrpc->res = tee_fs_seek(fsrpc);
break;
case TEE_FS_UNLINK:
- ret = tee_fs_unlink(fsrpc);
+ fsrpc->res = tee_fs_unlink(fsrpc);
break;
case TEE_FS_RENAME:
- ret = tee_fs_rename(fsrpc);
+ fsrpc->res = tee_fs_rename(fsrpc);
break;
case TEE_FS_TRUNC:
- ret = tee_fs_truncate(fsrpc);
+ fsrpc->res = tee_fs_truncate(fsrpc);
break;
case TEE_FS_MKDIR:
- ret = tee_fs_mkdir(fsrpc);
+ fsrpc->res = tee_fs_mkdir(fsrpc);
break;
case TEE_FS_OPENDIR:
- ret = tee_fs_opendir(fsrpc);
+ fsrpc->res = tee_fs_opendir(fsrpc);
break;
case TEE_FS_CLOSEDIR:
- ret = tee_fs_closedir(fsrpc);
+ fsrpc->res = tee_fs_closedir(fsrpc);
break;
case TEE_FS_READDIR:
- ret = tee_fs_readdir(fsrpc);
+ fsrpc->res = tee_fs_readdir(fsrpc);
break;
case TEE_FS_RMDIR:
- ret = tee_fs_rmdir(fsrpc);
+ fsrpc->res = tee_fs_rmdir(fsrpc);
break;
case TEE_FS_ACCESS:
- ret = tee_fs_access(fsrpc);
+ fsrpc->res = tee_fs_access(fsrpc);
break;
case TEE_FS_LINK:
- ret = tee_fs_link(fsrpc);
- default:
+ fsrpc->res = tee_fs_link(fsrpc);
break;
+ default:
+ EMSG("Unexpected REE FS operation: %d", fsrpc->op);
+ return TEEC_ERROR_NOT_SUPPORTED;
}
- fsrpc->res = ret;
+ return TEEC_SUCCESS;
+}
- return ret;
+static int open_wrapper(const char *fname, int flags)
+{
+ int fd;
+
+ while (true) {
+ fd = open(fname, flags);
+ if (fd >= 0 || errno != EINTR)
+ return fd;
+ }
+}
+
+static TEEC_Result ree_fs_new_open(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char abs_filename[PATH_MAX];
+ char *fname;
+ int fd;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(fname, abs_filename,
+ sizeof(abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = open_wrapper(abs_filename, O_RDWR);
+ if (fd < 0)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+
+ params[2].u.value.a = fd;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_create(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char abs_filename[PATH_MAX];
+ char abs_dir[PATH_MAX];
+ char *fname;
+ char *d;
+ int fd;
+ const int flags = O_RDWR | O_CREAT | O_TRUNC;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(fname, abs_filename,
+ sizeof(abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = open_wrapper(abs_filename, flags);
+ if (fd >= 0)
+ goto out;
+ if (errno != ENOENT)
+ return TEEC_ERROR_GENERIC;
+
+ /* Directory for file missing, try make to it */
+ strncpy(abs_dir, abs_filename, sizeof(abs_dir));
+ abs_dir[sizeof(abs_dir) - 1] = '\0';
+ d = dirname(abs_dir);
+ if (!mkdir(d, S_IRUSR | S_IWUSR | S_IXUSR)) {
+ fd = open_wrapper(abs_filename, flags);
+ if (fd >= 0)
+ goto out;
+ /*
+ * The directory was made but the file could still not be
+ * created.
+ */
+ rmdir(d);
+ return TEEC_ERROR_GENERIC;
+ }
+ if (errno != ENOENT)
+ return TEEC_ERROR_GENERIC;
+
+ /* Parent directory for file missing, try to make it */
+ d = dirname(d);
+ if (mkdir(d, S_IRUSR | S_IWUSR | S_IXUSR))
+ return TEEC_ERROR_GENERIC;
+
+ /* Try to make directory for file again */
+ strncpy(abs_dir, abs_filename, sizeof(abs_dir));
+ abs_dir[sizeof(abs_dir) - 1] = '\0';
+ d = dirname(abs_dir);
+ if (mkdir(d, S_IRUSR | S_IWUSR | S_IXUSR)) {
+ d = dirname(d);
+ rmdir(d);
+ return TEEC_ERROR_GENERIC;
+ }
+
+ fd = open_wrapper(abs_filename, flags);
+ if (fd < 0) {
+ rmdir(d);
+ d = dirname(d);
+ rmdir(d);
+ return TEEC_ERROR_GENERIC;
+ }
+
+out:
+ params[2].u.value.a = fd;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_close(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ int fd;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = params[0].u.value.b;
+ while (close(fd)) {
+ if (errno != EINTR)
+ return TEEC_ERROR_GENERIC;
+ }
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_read(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ uint8_t *buf;
+ size_t len;
+ off_t offs;
+ int fd;
+ ssize_t r;
+ size_t s;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = params[0].u.value.b;
+ offs = params[0].u.value.c;
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ s = 0;
+ r = -1;
+ while (r && len) {
+ r = pread(fd, buf, len, offs);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+ return TEEC_ERROR_GENERIC;
+ }
+ assert((size_t)r <= len);
+ buf += r;
+ len -= r;
+ offs += r;
+ s += r;
+ }
+
+ params[1].u.memref.size = s;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_write(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ uint8_t *buf;
+ size_t len;
+ off_t offs;
+ int fd;
+ ssize_t r;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = params[0].u.value.b;
+ offs = params[0].u.value.c;
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ while (len) {
+ r = pwrite(fd, buf, len, offs);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+ return TEEC_ERROR_GENERIC;
+ }
+ assert((size_t)r <= len);
+ buf += r;
+ len -= r;
+ offs += r;
+ }
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_truncate(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ size_t len;
+ int fd;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fd = params[0].u.value.b;
+ len = params[0].u.value.c;
+
+ while (ftruncate(fd, len)) {
+ if (errno != EINTR)
+ return TEEC_ERROR_GENERIC;
+ }
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_remove(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char abs_filename[PATH_MAX];
+ char *fname;
+ char *d;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(fname, abs_filename,
+ sizeof(abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (unlink(abs_filename)) {
+ if (errno == ENOENT)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ return TEEC_ERROR_GENERIC;
+ }
+
+ /* If a file is removed, maybe the directory can be removed to? */
+ d = dirname(abs_filename);
+ if (!rmdir(d)) {
+ /*
+ * If the directory was removed, maybe the parent directory
+ * can be removed too?
+ */
+ d = dirname(d);
+ rmdir(d);
+ }
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_rename(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char old_abs_filename[PATH_MAX];
+ char new_abs_filename[PATH_MAX];
+ char *old_fname;
+ char *new_fname;
+ bool overwrite;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ overwrite = !!params[0].u.value.b;
+
+ old_fname = tee_supp_param_to_va(params + 1);
+ if (!old_fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ new_fname = tee_supp_param_to_va(params + 2);
+ if (!new_fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(old_fname, old_abs_filename,
+ sizeof(old_abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(new_fname, new_abs_filename,
+ sizeof(new_abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!overwrite) {
+ struct stat st;
+
+ if (!stat(new_abs_filename, &st))
+ return TEEC_ERROR_ACCESS_CONFLICT;
+ }
+ if (rename(old_abs_filename, new_abs_filename)) {
+ if (errno == ENOENT)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ }
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_opendir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ char abs_filename[PATH_MAX];
+ char *fname;
+ DIR *dir;
+ int handle;
+
+ if (num_params != 3 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
+ (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ fname = tee_supp_param_to_va(params + 1);
+ if (!fname)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!tee_fs_get_absolute_filename(fname, abs_filename,
+ sizeof(abs_filename)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ dir = opendir(abs_filename);
+ if (!dir)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+
+ handle = handle_get(&dir_handle_db, dir);
+ if (handle < 0) {
+ closedir(dir);
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+
+ params[2].u.value.a = handle;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_closedir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ DIR *dir;
+
+ if (num_params != 1 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ dir = handle_put(&dir_handle_db, params[0].u.value.b);
+ if (!dir)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ closedir(dir);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result ree_fs_new_readdir(size_t num_params,
+ struct tee_ioctl_param *params)
+{
+ DIR *dir;
+ struct dirent *dirent;
+ char *buf;
+ size_t len;
+ size_t fname_len;
+
+ if (num_params != 2 ||
+ (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
+ (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+
+ buf = tee_supp_param_to_va(params + 1);
+ if (!buf)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ len = params[1].u.memref.size;
+
+ dir = handle_lookup(&dir_handle_db, params[0].u.value.b);
+ if (!dir)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ while (true) {
+ dirent = readdir(dir);
+ if (!dirent)
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+ if (dirent->d_name[0] != '.')
+ break;
+ }
+
+ fname_len = strlen(dirent->d_name) + 1;
+ params[1].u.memref.size = fname_len;
+ if (fname_len > len)
+ return TEEC_ERROR_SHORT_BUFFER;
+
+ memcpy(buf, dirent->d_name, fname_len);
+
+ return TEEC_SUCCESS;
+}
+
+TEEC_Result tee_supp_fs_process(struct tee_iocl_supp_recv_arg *recv)
+{
+ struct tee_ioctl_param *param = (void *)(recv + 1);
+
+ if (recv->num_params == 1 && tee_supp_param_is_memref(param)) {
+ void *va = tee_supp_param_to_va(param);
+
+ if (!va)
+ return TEEC_ERROR_BAD_PARAMETERS;
+ return tee_supp_fs_process_primitive(va, param->u.memref.size);
+ }
+
+ if (!tee_supp_param_is_value(param))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ switch (param->u.value.a) {
+ case OPTEE_MRF_OPEN:
+ return ree_fs_new_open(recv->num_params, param);
+ case OPTEE_MRF_CREATE:
+ return ree_fs_new_create(recv->num_params, param);
+ case OPTEE_MRF_CLOSE:
+ return ree_fs_new_close(recv->num_params, param);
+ case OPTEE_MRF_READ:
+ return ree_fs_new_read(recv->num_params, param);
+ case OPTEE_MRF_WRITE:
+ return ree_fs_new_write(recv->num_params, param);
+ case OPTEE_MRF_TRUNCATE:
+ return ree_fs_new_truncate(recv->num_params, param);
+ case OPTEE_MRF_REMOVE:
+ return ree_fs_new_remove(recv->num_params, param);
+ case OPTEE_MRF_RENAME:
+ return ree_fs_new_rename(recv->num_params, param);
+ case OPTEE_MRF_OPENDIR:
+ return ree_fs_new_opendir(recv->num_params, param);
+ case OPTEE_MRF_CLOSEDIR:
+ return ree_fs_new_closedir(recv->num_params, param);
+ case OPTEE_MRF_READDIR:
+ return ree_fs_new_readdir(recv->num_params, param);
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
}
diff --git a/tee-supplicant/src/tee_supp_fs.h b/tee-supplicant/src/tee_supp_fs.h
index 3d14a98..3342b7e 100644
--- a/tee-supplicant/src/tee_supp_fs.h
+++ b/tee-supplicant/src/tee_supp_fs.h
@@ -27,10 +27,11 @@
#ifndef TEE_SUPP_FS_H
#define TEE_SUPP_FS_H
-#include <stddef.h>
+#include <tee_client_api.h>
int tee_supp_fs_init(void);
-int tee_supp_fs_process(void *cmd, size_t cmd_size);
+struct tee_iocl_supp_recv_arg;
+TEEC_Result tee_supp_fs_process(struct tee_iocl_supp_recv_arg *recv);
#endif
diff --git a/tee-supplicant/src/tee_supplicant.c b/tee-supplicant/src/tee_supplicant.c
index 0892bd7..52a33b1 100644
--- a/tee-supplicant/src/tee_supplicant.c
+++ b/tee-supplicant/src/tee_supplicant.c
@@ -26,34 +26,36 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <stdint.h>
#include <inttypes.h>
+#include <rpmb.h>
+#include <sql_fs.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/mman.h>
#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <teec_trace.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <tee_client_api.h>
#include <teec_ta_load.h>
#include <tee_supp_fs.h>
+#include <teec_trace.h>
+#include <tee_supplicant.h>
+#include <unistd.h>
#ifndef __aligned
#define __aligned(x) __attribute__((__aligned__(x)))
#endif
#include <linux/tee.h>
-#include <rpmb.h>
-#include <sql_fs.h>
-#define RPC_NUM_PARAMS 2
+#define RPC_NUM_PARAMS 3
#define RPC_BUF_SIZE (sizeof(struct tee_iocl_supp_send_arg) + \
RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param))
@@ -105,6 +107,16 @@
}
}
+static struct tee_shm *find_tshm(int id)
+{
+ struct tee_shm *tshm;
+
+ tshm = shm_head;
+ while (tshm && tshm->id != id)
+ tshm = tshm->next;
+ return tshm;
+}
+
/* Get parameter allocated by secure world */
static int get_param(union tee_rpc_invoke *request, const uint32_t idx,
TEEC_SharedMemory *shm)
@@ -127,9 +139,7 @@
memset(shm, 0, sizeof(*shm));
- tshm = shm_head;
- while (tshm && tshm->id != params[idx].u.memref.shm_id)
- tshm = tshm->next;
+ tshm = find_tshm(params[idx].u.memref.shm_id);
if (!tshm) {
/*
* It doesn't make sense to query required size of an
@@ -161,37 +171,12 @@
static void process_fs(union tee_rpc_invoke *request)
{
- TEEC_SharedMemory shm;
-
- if (request->recv.num_params != 1 || get_param(request, 0, &shm)) {
- request->send.ret = TEEC_ERROR_BAD_PARAMETERS;
- return;
- }
-
- if (tee_supp_fs_process(shm.buffer, shm.size) < 0) {
- request->send.ret = TEEC_ERROR_BAD_PARAMETERS;
- return;
- }
-
- request->send.ret = TEEC_SUCCESS;
+ request->send.ret = tee_supp_fs_process(&request->recv);
}
-
static void process_sql_fs(union tee_rpc_invoke *request)
{
- TEEC_SharedMemory shm;
-
- if (request->recv.num_params != 1 || get_param(request, 0, &shm)) {
- request->send.ret = TEEC_ERROR_BAD_PARAMETERS;
- return;
- }
-
- if (sql_fs_process(shm.buffer, shm.size) < 0) {
- request->send.ret = TEEC_ERROR_BAD_PARAMETERS;
- return;
- }
-
- request->send.ret = TEEC_SUCCESS;
+ request->send.ret = sql_fs_process(&request->recv);
}
static void load_ta(union tee_rpc_invoke *request)
@@ -485,3 +470,50 @@
}
return 0;
}
+
+bool tee_supp_param_is_memref(struct tee_ioctl_param *param)
+{
+ switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool tee_supp_param_is_value(struct tee_ioctl_param *param)
+{
+ switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void *tee_supp_param_to_va(struct tee_ioctl_param *param)
+{
+ struct tee_shm *tshm;
+ size_t end_offs;
+
+ if (!tee_supp_param_is_memref(param))
+ return NULL;
+
+ end_offs = param->u.memref.size + param->u.memref.shm_offs;
+ if (end_offs < param->u.memref.size ||
+ end_offs < param->u.memref.shm_offs)
+ return NULL;
+
+ tshm = find_tshm(param->u.memref.shm_id);
+ if (!tshm)
+ return NULL;
+
+ if (end_offs > tshm->size)
+ return NULL;
+
+ return (uint8_t *)tshm->p + param->u.memref.shm_offs;
+}
diff --git a/tee-supplicant/src/tee_supplicant.h b/tee-supplicant/src/tee_supplicant.h
new file mode 100644
index 0000000..a21f0a3
--- /dev/null
+++ b/tee-supplicant/src/tee_supplicant.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TEE_SUPPLICANT_H
+#define TEE_SUPPLICANT_H
+
+#include <stdbool.h>
+
+struct tee_ioctl_param;
+
+bool tee_supp_param_is_memref(struct tee_ioctl_param *param);
+bool tee_supp_param_is_value(struct tee_ioctl_param *param);
+void *tee_supp_param_to_va(struct tee_ioctl_param *param);
+
+#endif /*TEE_SUPPLICANT_H*/