2 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/slab.h>
14 #include <linux/device.h>
15 #include <linux/types.h>
16 #include <linux/file.h>
17 #include <linux/atomic.h>
18 #include <linux/uaccess.h>
19 #include <linux/anon_inodes.h>
22 #include "tee_core_priv.h"
24 static int _init_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io,
26 static void _update_client_tee_cmd(struct tee_session *sess,
27 struct tee_cmd_io *cmd_io,
29 static void _release_tee_cmd(struct tee_session *sess, struct tee_cmd *cmd);
31 #define _DEV_TEE _DEV(sess->ctx->tee)
33 #define INMSG dev_dbg(_DEV_TEE, "%s: >\n", __func__)
34 #define OUTMSG(val) dev_dbg(_DEV_TEE, "%s: < %d\n", __func__, (int)val)
36 /******************************************************************************/
38 static inline bool flag_set(int val, int flags)
40 return (val & flags) == flags;
43 static inline bool is_mapped_temp(int flags)
45 return flag_set(flags, TEE_SHM_MAPPED | TEE_SHM_TEMP);
49 /******************************************************************************/
51 #define _UUID_STR_SIZE 35
52 static char *_uuid_to_str(const TEEC_UUID *uuid)
54 static char uuid_str[_UUID_STR_SIZE];
58 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
59 uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
60 uuid->clockSeqAndNode[0], uuid->clockSeqAndNode[1],
61 uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3],
62 uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5],
63 uuid->clockSeqAndNode[6], uuid->clockSeqAndNode[7]);
65 sprintf(uuid_str, "NULL");
71 static int tee_copy_from_user(struct tee_context *ctx, void *to, void *from,
74 if ((!to) || (!from) || (!size))
77 return copy_from_user(to, from, size);
79 memcpy(to, from, size);
84 static int tee_copy_to_user(struct tee_context *ctx, void *to, void *from,
87 if ((!to) || (!from) || (!size))
90 return copy_to_user(to, from, size);
92 memcpy(to, from, size);
97 /* Defined as macro to let the put_user macro see the types */
98 #define tee_put_user(ctx, from, to) \
100 if ((ctx)->usr_client) \
101 put_user(from, to); \
106 static inline int tee_session_is_opened(struct tee_session *sess)
108 if (sess && sess->sessid)
109 return (sess->sessid != 0);
113 static int tee_session_open_be(struct tee_session *sess,
114 struct tee_cmd_io *cmd_io)
120 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
122 tee = sess->ctx->tee;
124 dev_dbg(_DEV(tee), "%s: > open a new session", __func__);
127 ret = _init_tee_cmd(sess, cmd_io, &cmd);
132 dev_dbg(_DEV(tee), "%s: UUID=%s\n", __func__,
133 _uuid_to_str((TEEC_UUID *) cmd.uuid->kaddr));
136 ret = tee->ops->open(sess, &cmd);
138 _update_client_tee_cmd(sess, cmd_io, &cmd);
140 /* propagate the reason of the error */
141 cmd_io->origin = cmd.origin;
142 cmd_io->err = cmd.err;
146 _release_tee_cmd(sess, &cmd);
147 dev_dbg(_DEV(tee), "%s: < ret=%d, sessid=%08x", __func__, ret,
152 int tee_session_invoke_be(struct tee_session *sess, struct tee_cmd_io *cmd_io)
158 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
160 tee = sess->ctx->tee;
162 dev_dbg(_DEV(tee), "%s: > sessid=%08x, cmd=0x%08x\n", __func__,
163 sess->sessid, cmd_io->cmd);
165 ret = _init_tee_cmd(sess, cmd_io, &cmd);
169 ret = tee->ops->invoke(sess, &cmd);
171 _update_client_tee_cmd(sess, cmd_io, &cmd);
173 /* propagate the reason of the error */
174 cmd_io->origin = cmd.origin;
175 cmd_io->err = cmd.err;
179 _release_tee_cmd(sess, &cmd);
180 dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret);
184 static int tee_session_close_be(struct tee_session *sess)
189 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
191 tee = sess->ctx->tee;
193 dev_dbg(_DEV(tee), "%s: > sessid=%08x", __func__, sess->sessid);
195 ret = tee->ops->close(sess);
198 dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret);
202 static int tee_session_cancel_be(struct tee_session *sess,
203 struct tee_cmd_io *cmd_io)
209 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
211 tee = sess->ctx->tee;
213 dev_dbg(_DEV(tee), "%s: > sessid=%08x, cmd=0x%08x\n", __func__,
214 sess->sessid, cmd_io->cmd);
216 ret = _init_tee_cmd(sess, cmd_io, &cmd);
220 ret = tee->ops->cancel(sess, &cmd);
223 _release_tee_cmd(sess, &cmd);
224 dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret);
228 static int tee_do_invoke_command(struct tee_session *sess,
229 struct tee_cmd_io __user *u_cmd)
233 struct tee_cmd_io k_cmd;
234 struct tee_context *ctx;
237 BUG_ON(!sess->ctx->tee);
239 tee = sess->ctx->tee;
241 dev_dbg(_DEV(tee), "%s: > sessid=%08x\n", __func__, sess->sessid);
243 BUG_ON(!sess->sessid);
245 if (tee_copy_from_user
246 (ctx, &k_cmd, (void *)u_cmd, sizeof(struct tee_cmd_io))) {
247 dev_err(_DEV(tee), "%s: tee_copy_from_user failed\n", __func__);
251 if ((k_cmd.op == NULL) || (k_cmd.uuid != NULL) ||
252 (k_cmd.data != NULL) || (k_cmd.data_size != 0)) {
254 "%s: op or/and data parameters are not valid\n",
259 ret = tee_session_invoke_be(sess, &k_cmd);
261 dev_err(_DEV(tee), "%s: tee_invoke_command failed\n", __func__);
263 tee_put_user(ctx, k_cmd.err, &u_cmd->err);
264 tee_put_user(ctx, k_cmd.origin, &u_cmd->origin);
267 dev_dbg(_DEV(tee), "%s: < ret=%d\n", __func__, ret);
271 static int tee_do_cancel_cmd(struct tee_session *sess,
272 struct tee_cmd_io __user *u_cmd)
276 struct tee_cmd_io k_cmd;
277 struct tee_context *ctx;
280 BUG_ON(!sess->ctx->tee);
282 tee = sess->ctx->tee;
284 dev_dbg(sess->ctx->tee->dev, "%s: > sessid=%08x\n", __func__,
287 BUG_ON(!sess->sessid);
289 if (tee_copy_from_user
290 (ctx, &k_cmd, (void *)u_cmd, sizeof(struct tee_cmd_io))) {
291 dev_err(_DEV(tee), "%s: tee_copy_from_user failed\n", __func__);
295 if ((k_cmd.op == NULL) || (k_cmd.uuid != NULL) ||
296 (k_cmd.data != NULL) || (k_cmd.data_size != 0)) {
298 "%s: op or/and data parameters are not valid\n",
303 ret = tee_session_cancel_be(sess, &k_cmd);
305 dev_err(_DEV(tee), "%s: tee_invoke_command failed\n", __func__);
307 tee_put_user(ctx, k_cmd.err, &u_cmd->err);
308 tee_put_user(ctx, k_cmd.origin, &u_cmd->origin);
311 dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret);
315 static long tee_session_ioctl(struct file *filp, unsigned int cmd,
319 struct tee_session *sess = filp->private_data;
322 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
324 tee = sess->ctx->tee;
326 dev_dbg(_DEV(tee), "%s: > cmd nr=%d\n", __func__, _IOC_NR(cmd));
329 case TEE_INVOKE_COMMAND_IOC:
331 tee_do_invoke_command(sess,
332 (struct tee_cmd_io __user *)arg);
334 case TEE_REQUEST_CANCELLATION_IOC:
335 ret = tee_do_cancel_cmd(sess, (struct tee_cmd_io __user *)arg);
342 dev_dbg(_DEV(tee), "%s: < ret=%d\n", __func__, ret);
347 static int tee_session_release(struct inode *inode, struct file *filp)
349 struct tee_session *sess = filp->private_data;
353 BUG_ON(!sess || !sess->ctx || !sess->ctx->tee);
354 tee = sess->ctx->tee;
356 ret = tee_session_close_and_destroy(sess);
360 const struct file_operations tee_session_fops = {
361 .owner = THIS_MODULE,
363 .compat_ioctl = tee_session_ioctl,
365 .unlocked_ioctl = tee_session_ioctl,
366 .compat_ioctl = tee_session_ioctl,
367 .release = tee_session_release,
370 int tee_session_close_and_destroy(struct tee_session *sess)
374 struct tee_context *ctx;
376 if (!sess || !sess->ctx || !sess->ctx->tee)
382 dev_dbg(_DEV(tee), "%s: > sess=%p\n", __func__, sess);
384 if (!tee_session_is_opened(sess))
387 ret = tee_session_close_be(sess);
389 mutex_lock(&tee->lock);
390 tee_dec_stats(&tee->stats[TEE_STATS_SESSION_IDX]);
391 list_del(&sess->entry);
393 devm_kfree(_DEV(tee), sess);
394 tee_context_put(ctx);
396 mutex_unlock(&tee->lock);
398 dev_dbg(_DEV(tee), "%s: <\n", __func__);
402 struct tee_session *tee_session_create_and_open(struct tee_context *ctx,
403 struct tee_cmd_io *cmd_io)
406 struct tee_session *sess;
413 dev_dbg(_DEV(tee), "%s: >\n", __func__);
416 return ERR_PTR(-EBUSY);
418 sess = devm_kzalloc(_DEV(tee), sizeof(struct tee_session), GFP_KERNEL);
420 dev_err(_DEV(tee), "%s: tee_session allocation() failed\n",
423 return ERR_PTR(-ENOMEM);
426 tee_context_get(ctx);
429 ret = tee_session_open_be(sess, cmd_io);
430 mutex_lock(&tee->lock);
431 if (ret || !sess->sessid || cmd_io->err) {
432 dev_err(_DEV(tee), "%s: ERROR ret=%d (err=0x%08x, org=%d, sessid=0x%08x)\n",
433 __func__, ret, cmd_io->err,
434 cmd_io->origin, sess->sessid);
436 tee_context_put(ctx);
437 devm_kfree(_DEV(tee), sess);
438 mutex_unlock(&tee->lock);
445 tee_inc_stats(&tee->stats[TEE_STATS_SESSION_IDX]);
446 list_add_tail(&sess->entry, &ctx->list_sess);
447 mutex_unlock(&tee->lock);
449 dev_dbg(_DEV(tee), "%s: < sess=%p\n", __func__, sess);
453 int tee_session_create_fd(struct tee_context *ctx, struct tee_cmd_io *cmd_io)
456 struct tee_session *sess;
457 struct tee *tee = ctx->tee;
459 BUG_ON(cmd_io->fd_sess > 0);
461 dev_dbg(_DEV(tee), "%s: >\n", __func__);
463 sess = tee_session_create_and_open(ctx, cmd_io);
464 if (IS_ERR_OR_NULL(sess)) {
466 dev_dbg(_DEV(tee), "%s: ERROR can't create the session (ret=%d, err=0x%08x, org=%d)\n",
467 __func__, ret, cmd_io->err, cmd_io->origin);
468 cmd_io->fd_sess = -1;
473 cmd_io->fd_sess = -1;
475 anon_inode_getfd("tee_session", &tee_session_fops, sess, O_CLOEXEC);
477 dev_err(_DEV(tee), "%s: ERROR can't get a fd (ret=%d)\n",
479 tee_session_close_and_destroy(sess);
482 cmd_io->fd_sess = ret;
486 dev_dbg(_DEV(tee), "%s: < ret=%d, sess=%p, fd=%d\n", __func__,
487 ret, sess, cmd_io->fd_sess);
491 static bool tee_session_is_supported_type(struct tee_session *sess, int type)
495 case TEEC_VALUE_INPUT:
496 case TEEC_VALUE_OUTPUT:
497 case TEEC_VALUE_INOUT:
498 case TEEC_MEMREF_TEMP_INPUT:
499 case TEEC_MEMREF_TEMP_OUTPUT:
500 case TEEC_MEMREF_TEMP_INOUT:
501 case TEEC_MEMREF_WHOLE:
502 case TEEC_MEMREF_PARTIAL_INPUT:
503 case TEEC_MEMREF_PARTIAL_OUTPUT:
504 case TEEC_MEMREF_PARTIAL_INOUT:
507 dev_err(_DEV_TEE, "type is invalid (type %02x)\n", type);
512 static int to_memref_type(int flags)
514 if (flag_set(flags, TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))
515 return TEEC_MEMREF_TEMP_INOUT;
517 if (flag_set(flags, TEEC_MEM_INPUT))
518 return TEEC_MEMREF_TEMP_INPUT;
520 if (flag_set(flags, TEEC_MEM_OUTPUT))
521 return TEEC_MEMREF_TEMP_OUTPUT;
523 pr_err("%s: bad flags=%x\n", __func__, flags);
527 static int _init_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io,
533 struct tee_data *param = &cmd->param;
535 struct tee_context *ctx;
538 BUG_ON(!sess->ctx->tee);
540 tee = sess->ctx->tee;
542 dev_dbg(_DEV(tee), "%s: > sessid=%08x\n", __func__, sess->sessid);
544 memset(cmd, 0, sizeof(struct tee_cmd));
546 cmd->cmd = cmd_io->cmd;
547 cmd->origin = TEEC_ORIGIN_TEE;
548 cmd->err = TEEC_ERROR_BAD_PARAMETERS;
549 cmd_io->origin = cmd->origin;
550 cmd_io->err = cmd->err;
552 if (tee_context_copy_from_client(ctx, &op, cmd_io->op, sizeof(op)))
555 cmd->param.type_original = op.paramTypes;
557 for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
560 int type = TEEC_PARAM_TYPE_GET(op.paramTypes, idx);
566 case TEEC_VALUE_INPUT:
567 case TEEC_VALUE_OUTPUT:
568 case TEEC_VALUE_INOUT:
569 param->params[idx].value = op.params[idx].value;
571 "%s: param[%d]:type=%d,a=%08x,b=%08x (VALUE)\n",
572 __func__, idx, type, param->params[idx].value.a,
573 param->params[idx].value.b);
576 case TEEC_MEMREF_TEMP_INPUT:
577 case TEEC_MEMREF_TEMP_OUTPUT:
578 case TEEC_MEMREF_TEMP_INOUT:
580 "> param[%d]:type=%d,buffer=%p,s=%zu (TMPREF)\n",
581 idx, type, op.params[idx].tmpref.buffer,
582 op.params[idx].tmpref.size);
584 param->params[idx].shm =
585 tee_context_create_tmpref_buffer(ctx,
586 op.params[idx].tmpref.size,
587 op.params[idx].tmpref.buffer,
589 if (IS_ERR_OR_NULL(param->params[idx].shm))
592 dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx,
593 (void *)param->params[idx].shm->paddr,
594 param->params[idx].shm->size_alloc);
597 case TEEC_MEMREF_PARTIAL_INPUT:
598 case TEEC_MEMREF_PARTIAL_OUTPUT:
599 case TEEC_MEMREF_PARTIAL_INOUT:
600 case TEEC_MEMREF_WHOLE:
601 if (tee_copy_from_user(ctx, ¶m->c_shm[idx],
602 op.params[idx].memref.parent,
603 sizeof(param->c_shm[idx]))) {
607 if (type == TEEC_MEMREF_WHOLE) {
609 size = param->c_shm[idx].size;
610 } else { /* for PARTIAL, check the size */
611 offset = op.params[idx].memref.offset;
612 size = op.params[idx].memref.size;
613 if (param->c_shm[idx].size < size + offset) {
614 dev_err(_DEV(tee), "A PARTIAL parameter is bigger than the parent %zd < %d + %d\n",
615 param->c_shm[idx].size, size,
621 dev_dbg(_DEV_TEE, "> param[%d]:type=%d,buffer=%p, offset=%d size=%d\n",
622 idx, type, param->c_shm[idx].buffer,
625 type = to_memref_type(param->c_shm[idx].flags);
629 param->params[idx].shm = tee_shm_get(ctx,
630 ¶m->c_shm[idx], size, offset);
632 if (IS_ERR_OR_NULL(param->params[idx].shm)) {
633 param->params[idx].shm =
634 tee_context_create_tmpref_buffer(ctx, size,
635 param->c_shm[idx].buffer + offset, type);
637 if (IS_ERR_OR_NULL(param->params[idx].shm))
641 dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx,
642 (void *)param->params[idx].shm->paddr,
643 param->params[idx].shm->size_req);
650 param->type |= (type << (idx * 4));
653 if (cmd_io->uuid != NULL) {
654 dev_dbg(_DEV_TEE, "%s: copy UUID value...\n", __func__);
655 cmd->uuid = tee_context_alloc_shm_tmp(sess->ctx,
656 sizeof(*cmd_io->uuid), cmd_io->uuid, TEEC_MEM_INPUT);
657 if (IS_ERR_OR_NULL(cmd->uuid)) {
667 _release_tee_cmd(sess, cmd);
669 dev_dbg(_DEV_TEE, "%s: < ret=%d\n", __func__, ret);
673 static void _update_client_tee_cmd(struct tee_session *sess,
674 struct tee_cmd_io *cmd_io,
678 struct tee_context *ctx;
682 BUG_ON(!cmd_io->op->params);
687 dev_dbg(_DEV_TEE, "%s: returned err=0x%08x (origin=%d)\n", __func__,
688 cmd->err, cmd->origin);
690 cmd_io->origin = cmd->origin;
691 cmd_io->err = cmd->err;
693 if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE,
694 TEEC_NONE, TEEC_NONE, TEEC_NONE))
697 for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
698 int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx);
702 TEEC_SharedMemory *parent;
704 dev_dbg(_DEV_TEE, "%s: id %d type %d\n", __func__, idx, type);
705 BUG_ON(!tee_session_is_supported_type(sess, type));
708 case TEEC_VALUE_INPUT:
709 case TEEC_MEMREF_TEMP_INPUT:
710 case TEEC_MEMREF_PARTIAL_INPUT:
712 case TEEC_VALUE_OUTPUT:
713 case TEEC_VALUE_INOUT:
714 dev_dbg(_DEV_TEE, "%s: a=%08x, b=%08x\n",
716 cmd->param.params[idx].value.a,
717 cmd->param.params[idx].value.b);
719 (ctx, &cmd_io->op->params[idx].value,
720 &cmd->param.params[idx].value,
721 sizeof(cmd_io->op->params[idx].value)))
723 "%s:%d: can't update %d result to user\n",
724 __func__, __LINE__, idx);
726 case TEEC_MEMREF_TEMP_OUTPUT:
727 case TEEC_MEMREF_TEMP_INOUT:
728 /* Returned updated size */
729 size_new = cmd->param.params[idx].shm->size_req;
731 cmd_io->op->params[idx].tmpref.size) {
733 "Size has been updated by the TA %zd != %zd\n",
735 cmd_io->op->params[idx].tmpref.size);
736 tee_put_user(ctx, size_new,
737 &cmd_io->op->params[idx].tmpref.size);
740 dev_dbg(_DEV_TEE, "%s: tmpref %p\n", __func__,
741 cmd->param.params[idx].shm->kaddr);
743 /* ensure we do not exceed the shared buffer length */
744 if (size_new > cmd_io->op->params[idx].tmpref.size)
746 " *** Wrong returned size from %d:%zd > %zd\n",
748 cmd_io->op->params[idx].tmpref.size);
750 else if (tee_copy_to_user
752 cmd_io->op->params[idx].tmpref.buffer,
753 cmd->param.params[idx].shm->kaddr,
756 "%s:%d: can't update %d result to user\n",
757 __func__, __LINE__, idx);
760 case TEEC_MEMREF_PARTIAL_OUTPUT:
761 case TEEC_MEMREF_PARTIAL_INOUT:
762 case TEEC_MEMREF_WHOLE:
763 parent = &cmd->param.c_shm[idx];
764 if (type == TEEC_MEMREF_WHOLE) {
768 offset = cmd_io->op->params[idx].memref.offset;
769 size = cmd_io->op->params[idx].memref.size;
772 /* Returned updated size */
773 size_new = cmd->param.params[idx].shm->size_req;
774 tee_put_user(ctx, size_new,
775 &cmd_io->op->params[idx].memref.size);
778 * If we allocated a tmpref buffer,
779 * copy back data to the user buffer
781 if (is_mapped_temp(cmd->param.params[idx].shm->flags)) {
782 if (parent->buffer &&
783 offset + size_new <= parent->size) {
784 if (tee_copy_to_user(ctx,
785 parent->buffer + offset,
786 cmd->param.params[idx].shm->kaddr,
789 "%s: can't update %d data to user\n",
801 static void _release_tee_cmd(struct tee_session *sess, struct tee_cmd *cmd)
804 struct tee_context *ctx;
809 BUG_ON(!sess->ctx->tee);
813 dev_dbg(_DEV_TEE, "%s: > free the temporary objects...\n", __func__);
815 tee_shm_free(cmd->uuid);
817 if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE,
818 TEEC_NONE, TEEC_NONE, TEEC_NONE))
821 for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
822 int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx);
826 case TEEC_VALUE_INPUT:
827 case TEEC_VALUE_OUTPUT:
828 case TEEC_VALUE_INOUT:
830 case TEEC_MEMREF_TEMP_INPUT:
831 case TEEC_MEMREF_TEMP_OUTPUT:
832 case TEEC_MEMREF_TEMP_INOUT:
833 case TEEC_MEMREF_WHOLE:
834 case TEEC_MEMREF_PARTIAL_INPUT:
835 case TEEC_MEMREF_PARTIAL_OUTPUT:
836 case TEEC_MEMREF_PARTIAL_INOUT:
837 if (IS_ERR_OR_NULL(cmd->param.params[idx].shm))
840 shm = cmd->param.params[idx].shm;
842 if (is_mapped_temp(shm->flags))
845 tee_shm_put(ctx, shm);
853 memset(cmd, 0, sizeof(struct tee_cmd));
854 dev_dbg(_DEV_TEE, "%s: <\n", __func__);