summaryrefslogtreecommitdiff
path: root/src/tee.c
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2021-02-03 08:00:00 +0000
committerDmitry V. Levin <ldv@strace.io>2021-02-03 08:00:00 +0000
commitecb3ed78107c851f71696df6730a15afff91ed3d (patch)
tree0b3d2b083040fc9b08d129f80d027ff41b995059 /src/tee.c
parentc47943de06204a269e16f732e7c9c71d4284b23f (diff)
downloadstrace-ecb3ed78107c851f71696df6730a15afff91ed3d.tar.gz
Move source files into src subdirectory
* src/Makefile.am: New file. * src/.gitignore: Likewise. * scno.am: Move into src subdirectory. * scno.head: Likewise. * strace-graph: Likewise. * strace-log-merge: Likewise. * linux/: Likewise. * types/: Likewise. * xlat/: Likewise. * *.awk: Likewise. * *.c: Likewise. * *.h: Likewise. * *.sh: Likewise. * .gitignore: Update. * Makefile.am: Update. * bootstrap: Update. * configure.ac: Update. * debian/rules: Update. * debian/strace-udeb.install: Update. * debian/strace.examples: Update. * debian/strace.install: Update. * debian/strace64.install: Update. * m4/gen_bpf_attr_m4.sh: Update. * m4/mpers.m4: Update. * tests/Makefile.am: Update. * tests/init.sh: Update. * tests/legacy_syscall_info.test: Update. * tests/strace-log-merge-error.test: Update. * tests/strace-log-merge-suffix.test: Update.
Diffstat (limited to 'src/tee.c')
-rw-r--r--src/tee.c594
1 files changed, 594 insertions, 0 deletions
diff --git a/src/tee.c b/src/tee.c
new file mode 100644
index 000000000..abd70fb64
--- /dev/null
+++ b/src/tee.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright (c) 2020 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+
+#include "types/tee.h"
+
+#define XLAT_MACROS_ONLY
+#include "xlat/tee_ioctl_cmds.h"
+#undef XLAT_MACROS_ONLY
+
+#include "xlat/tee_ioctl_gen_caps.h"
+#include "xlat/tee_ioctl_impl_ids.h"
+#include "xlat/tee_ioctl_login_types.h"
+#include "xlat/tee_ioctl_max_arg_size.h"
+#include "xlat/tee_ioctl_origins.h"
+#include "xlat/tee_ioctl_optee_caps.h"
+#include "xlat/tee_ioctl_param_attr_types.h"
+#include "xlat/tee_ioctl_shm_flags.h"
+
+#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct_tee_ioctl_param) * (x))
+
+#define TEE_FETCH_BUF_DATA(buf_, arg_, params_) \
+ tee_fetch_buf_data(tcp, arg, &buf_, sizeof(arg_), \
+ &arg_, &arg_.num_params, \
+ params_)
+
+/* session id is printed as 0x%x in libteec */
+#define PRINT_FIELD_SESSION(where_, field_) \
+ PRINT_FIELD_X(where_, field_)
+
+static void
+tee_print_buf(struct_tee_ioctl_buf_data *buf)
+{
+ tprint_struct_begin();
+ PRINT_FIELD_U(*buf, buf_len);
+ tprint_struct_next();
+ PRINT_FIELD_ADDR64(*buf, buf_ptr);
+ tprint_struct_end();
+}
+
+static int
+tee_fetch_buf_data(struct tcb *const tcp,
+ const kernel_ulong_t arg,
+ struct_tee_ioctl_buf_data *buf,
+ size_t arg_size,
+ void *arg_struct,
+ unsigned *num_params,
+ uint64_t *params)
+{
+ if (umove_or_printaddr(tcp, arg, buf))
+ return RVAL_IOCTL_DECODED;
+ if (buf->buf_len > TEE_MAX_ARG_SIZE || buf->buf_len < arg_size) {
+ tee_print_buf(buf);
+ return RVAL_IOCTL_DECODED;
+ }
+ if (umoven(tcp, buf->buf_ptr, arg_size, arg_struct)) {
+ tee_print_buf(buf);
+ return RVAL_IOCTL_DECODED;
+ }
+ if (entering(tcp) &&
+ (arg_size + TEE_IOCTL_PARAM_SIZE(*num_params) != buf->buf_len)) {
+ /*
+ * We could print whatever number of params
+ * is in buf_data, but the kernel would ignore
+ * them anyway (and return -EINVAL) if
+ * the above condition is not satisfied.
+ *
+ * Except for on exiting. The kernel has the right
+ * to update num_params but not buf_len
+ * (see tee_ioctl_supp_recv)
+ */
+ tee_print_buf(buf);
+ return RVAL_IOCTL_DECODED;
+ }
+ if (*num_params) {
+ *params = buf->buf_ptr + arg_size;
+ } else {
+ *params = 0;
+ }
+
+ return 0;
+}
+
+static bool
+tee_print_param_fn(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+ struct_tee_ioctl_param *param = (struct_tee_ioctl_param *) elem_buf;
+
+ tprint_struct_begin();
+ tprints_field_name("attr");
+ printxval(tee_ioctl_param_attr_types,
+ param->attr & ~TEE_IOCTL_PARAM_ATTR_META,
+ "TEE_IOCTL_PARAM_ATTR_");
+ if (param->attr & TEE_IOCTL_PARAM_ATTR_META)
+ tprints("|TEE_IOCTL_PARAM_ATTR_META");
+
+ switch (param->attr) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+ break;
+
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ tprint_struct_next();
+ tprints_field_name("shm_offs");
+ tprintf("%#llx", (unsigned long long) param->a);
+ tprint_struct_next();
+ tprints_field_name("size");
+ tprintf("%#llx", (unsigned long long) param->b);
+ tprint_struct_next();
+ tprints_field_name("shm_id");
+ tprintf("%llu", (unsigned long long) param->c);
+ break;
+
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ default:
+ tprint_struct_next();
+ PRINT_FIELD_X(*param, a);
+ tprint_struct_next();
+ PRINT_FIELD_X(*param, b);
+ tprint_struct_next();
+ PRINT_FIELD_X(*param, c);
+ break;
+ }
+ tprint_struct_end();
+ return true;
+}
+
+static void
+tee_print_params(struct tcb *const tcp, uint64_t params_start, unsigned num_params)
+{
+ struct_tee_ioctl_param param_buffer;
+
+ tprint_struct_next();
+ tprints_field_name("params");
+ print_array(tcp, params_start, num_params, &param_buffer, sizeof(param_buffer),
+ tfetch_mem, tee_print_param_fn, NULL);
+}
+
+static int
+tee_version(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_version_data version;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ return 0;
+ }
+
+ if (umove_or_printaddr(tcp, arg, &version))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_XVAL(version, impl_id,
+ tee_ioctl_impl_ids, "TEE_IMPL_ID_???");
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(version, gen_caps,
+ tee_ioctl_gen_caps, "TEE_GEN_CAP_???");
+ if (version.impl_id == TEE_IMPL_ID_OPTEE) {
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(version, impl_caps,
+ tee_ioctl_optee_caps, "TEE_OPTEE_CAP_???");
+ } else {
+ tprint_struct_next();
+ PRINT_FIELD_X(version, impl_caps);
+ }
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+}
+
+static int
+tee_open_session(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ int rval;
+ struct_tee_ioctl_buf_data buf_data;
+ struct_tee_ioctl_open_session_arg open_session;
+ uint64_t params;
+ gid_t gid;
+
+ if (entering(tcp)) {
+ tprints(", ");
+
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, open_session, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(buf_data, buf_len);
+ tprint_struct_next();
+ tprints_field_name("buf_ptr");
+ tprint_struct_begin();
+ PRINT_FIELD_UUID(open_session, uuid);
+ tprint_struct_next();
+ PRINT_FIELD_XVAL(open_session, clnt_login,
+ tee_ioctl_login_types, "TEE_IOCTL_LOGIN_???");
+ /*
+ * tee_ioctl_open_session_arg.clnt_uuid is used to pass
+ * connectionData, which is currently only used to indicate
+ * which group the client application wishes to authenticate as
+ * (when TEE_IOCTL_LOGIN_GROUP or TEE_IOCTL_LOGIN_GROUP_APPLICATION
+ * are used).
+ *
+ * It is not an UUID; actual client UUID is computed in the kernel.
+ */
+ switch (open_session.clnt_login) {
+ case TEE_IOCTL_LOGIN_PUBLIC:
+ case TEE_IOCTL_LOGIN_USER:
+ case TEE_IOCTL_LOGIN_APPLICATION:
+ case TEE_IOCTL_LOGIN_USER_APPLICATION:
+ break;
+ case TEE_IOCTL_LOGIN_GROUP:
+ case TEE_IOCTL_LOGIN_GROUP_APPLICATION:
+ memcpy(&gid, open_session.clnt_uuid, sizeof(gid));
+ printuid(", clnt_uuid=", gid);
+ break;
+ default:
+ tprint_struct_next();
+ PRINT_FIELD_X_ARRAY(open_session, clnt_uuid);
+ }
+ tprint_struct_next();
+ PRINT_FIELD_U(open_session, cancel_id);
+ tprint_struct_next();
+ PRINT_FIELD_U(open_session, num_params);
+ tee_print_params(tcp, params, open_session.num_params);
+
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ /*
+ * Yes, params are [in/out] for TEE_IOC_OPEN_SESSION.
+ * As for all other operations they are used in.
+ */
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, open_session, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_SESSION(open_session, session);
+ tprint_struct_next();
+ PRINT_FIELD_U(open_session, ret);
+ tprint_struct_next();
+ PRINT_FIELD_XVAL(open_session, ret_origin, tee_ioctl_origins,
+ "TEEC_ORIGIN_???");
+ tee_print_params(tcp, params, open_session.num_params);
+
+ tprint_struct_end();
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_invoke(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ int rval;
+ struct_tee_ioctl_buf_data buf_data;
+ struct_tee_ioctl_invoke_arg invoke;
+ uint64_t params;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, invoke, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(buf_data, buf_len);
+ tprint_struct_next();
+ tprints_field_name("buf_ptr");
+ tprint_struct_begin();
+ PRINT_FIELD_U(invoke, func);
+ tprint_struct_next();
+ PRINT_FIELD_SESSION(invoke, session);
+ tprint_struct_next();
+ PRINT_FIELD_U(invoke, cancel_id);
+ tprint_struct_next();
+ PRINT_FIELD_U(invoke, num_params);
+ tee_print_params(tcp, params, invoke.num_params);
+
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, invoke, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(invoke, ret);
+ tprint_struct_next();
+ PRINT_FIELD_XVAL(invoke, ret_origin, tee_ioctl_origins,
+ "TEEC_ORIGIN_???");
+ tee_print_params(tcp, params, invoke.num_params);
+
+ tprint_struct_end();
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_cancel(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_cancel_arg cancel;
+
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &cancel))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(cancel, cancel_id);
+ tprint_struct_next();
+ PRINT_FIELD_SESSION(cancel, session);
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+}
+
+static int
+tee_close_session(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_close_session_arg close_session;
+
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &close_session))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_SESSION(close_session, session);
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+}
+
+static int
+tee_suppl_recv(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ int rval;
+ struct_tee_ioctl_buf_data buf_data;
+ struct_tee_iocl_supp_recv_arg supp_recv;
+ uint64_t params;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_recv, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(buf_data, buf_len);
+ tprint_struct_next();
+ tprints_field_name("buf_ptr");
+ tprint_struct_begin();
+ PRINT_FIELD_U(supp_recv, func);
+ tprint_struct_next();
+ PRINT_FIELD_U(supp_recv, num_params);
+ tee_print_params(tcp, params, supp_recv.num_params);
+
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_recv, &params)))
+ return rval;
+
+ /* num_params is [in/out] for TEE_IOC_SUPPL_RECV only */
+ tprint_struct_begin();
+ PRINT_FIELD_U(supp_recv, num_params);
+ tee_print_params(tcp, params, supp_recv.num_params);
+
+ tprint_struct_end();
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_suppl_send(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ int rval;
+ struct_tee_ioctl_buf_data buf_data;
+ struct_tee_iocl_supp_send_arg supp_send;
+ uint64_t params;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_send, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(buf_data, buf_len);
+ tprint_struct_next();
+ tprints_field_name("buf_ptr");
+ tprint_struct_begin();
+ PRINT_FIELD_U(supp_send, num_params);
+ tee_print_params(tcp, params, supp_send.num_params);
+
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_send, &params)))
+ return rval;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(supp_send, ret);
+ tee_print_params(tcp, params, supp_send.num_params);
+
+ tprint_struct_end();
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_shm_alloc(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_shm_alloc_data shm_alloc;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &shm_alloc))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_X(shm_alloc, size);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(shm_alloc, flags,
+ tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if (umove_or_printaddr(tcp, arg, &shm_alloc))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_X(shm_alloc, size);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(shm_alloc, flags,
+ tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
+ tprint_struct_next();
+ PRINT_FIELD_D(shm_alloc, id);
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_shm_register_fd(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_shm_register_fd_data shm_register_fd;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &shm_register_fd))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_FD(shm_register_fd, fd, tcp);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(shm_register_fd, flags,
+ tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if (umove_or_printaddr(tcp, arg, &shm_register_fd))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_X(shm_register_fd, size);
+ tprint_struct_next();
+ PRINT_FIELD_D(shm_register_fd, id);
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+static int
+tee_shm_register(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_tee_ioctl_shm_register_data shm_register;
+
+ if (entering(tcp)) {
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &shm_register))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_ADDR64(shm_register, addr);
+ tprint_struct_next();
+ PRINT_FIELD_X(shm_register, length);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(shm_register, flags,
+ tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
+ tprint_struct_end();
+ return 0;
+
+ } else if (syserror(tcp)) {
+ return RVAL_IOCTL_DECODED;
+
+ } else {
+ tprint_value_changed();
+ if (umove_or_printaddr(tcp, arg, &shm_register))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_X(shm_register, length);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(shm_register, flags,
+ tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
+ tprint_struct_next();
+ PRINT_FIELD_D(shm_register, id);
+
+ tprint_struct_end();
+ return RVAL_IOCTL_DECODED;
+ }
+}
+
+int
+tee_ioctl(struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
+{
+ switch (code) {
+ case TEE_IOC_VERSION:
+ return tee_version(tcp, arg);
+
+ case TEE_IOC_OPEN_SESSION:
+ return tee_open_session(tcp, arg);
+
+ case TEE_IOC_INVOKE:
+ return tee_invoke(tcp, arg);
+
+ case TEE_IOC_CANCEL:
+ return tee_cancel(tcp, arg);
+
+ case TEE_IOC_CLOSE_SESSION:
+ return tee_close_session(tcp, arg);
+
+ case TEE_IOC_SUPPL_RECV:
+ return tee_suppl_recv(tcp, arg);
+
+ case TEE_IOC_SUPPL_SEND:
+ return tee_suppl_send(tcp, arg);
+
+ case TEE_IOC_SHM_ALLOC:
+ return tee_shm_alloc(tcp, arg);
+
+ case TEE_IOC_SHM_REGISTER_FD:
+ /* This one isn't upstream */
+ return tee_shm_register_fd(tcp, arg);
+
+ case TEE_IOC_SHM_REGISTER:
+ return tee_shm_register(tcp, arg);
+
+ default:
+ return RVAL_DECODED;
+ }
+}