OP-TEE: fix operate user pointer bug in optee driver
authorZhang Zhijie <zhangzj@rock-chips.com>
Tue, 18 Apr 2017 07:40:59 +0000 (15:40 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 20 Apr 2017 00:55:05 +0000 (08:55 +0800)
Fix operate user pointer bug which causes panic in kernel.

Change-Id: I7fcf74fb68dd0959e5ba64635c614f954d065281
Signed-off-by: Zhang Zhijie <zhangzj@rock-chips.com>
security/optee_linuxdriver/core/tee_session.c

index 987e7c954c84f1b4b7dc260d5ee3492930955e62..a1b7a71539b4958906dd4e1394b0b2388c7ac5b4 100644 (file)
@@ -676,6 +676,7 @@ static void _update_client_tee_cmd(struct tee_session *sess,
 {
        int idx;
        struct tee_context *ctx;
+       TEEC_Operation op;
 
        BUG_ON(!cmd_io);
        BUG_ON(!cmd_io->op);
@@ -694,6 +695,9 @@ static void _update_client_tee_cmd(struct tee_session *sess,
                        TEEC_NONE, TEEC_NONE, TEEC_NONE))
                return;
 
+       if (tee_context_copy_from_client(ctx, &op, cmd_io->op, sizeof(op)))
+               return;
+
        for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) {
                int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx);
                int offset = 0;
@@ -728,11 +732,11 @@ static void _update_client_tee_cmd(struct tee_session *sess,
                        /* Returned updated size */
                        size_new = cmd->param.params[idx].shm->size_req;
                        if (size_new !=
-                               cmd_io->op->params[idx].tmpref.size) {
+                               op.params[idx].tmpref.size) {
                                dev_dbg(_DEV_TEE,
                                        "Size has been updated by the TA %zd != %zd\n",
                                        size_new,
-                                       cmd_io->op->params[idx].tmpref.size);
+                                       op.params[idx].tmpref.size);
                                tee_put_user(ctx, size_new,
                                     &cmd_io->op->params[idx].tmpref.size);
                        }
@@ -741,15 +745,15 @@ static void _update_client_tee_cmd(struct tee_session *sess,
                                cmd->param.params[idx].shm->kaddr);
 
                        /* ensure we do not exceed the shared buffer length */
-                       if (size_new > cmd_io->op->params[idx].tmpref.size)
+                       if (size_new > op.params[idx].tmpref.size)
                                dev_err(_DEV_TEE,
                                        "  *** Wrong returned size from %d:%zd > %zd\n",
                                        idx, size_new,
-                                       cmd_io->op->params[idx].tmpref.size);
+                                       op.params[idx].tmpref.size);
 
                        else if (tee_copy_to_user
                                 (ctx,
-                                 cmd_io->op->params[idx].tmpref.buffer,
+                                 op.params[idx].tmpref.buffer,
                                  cmd->param.params[idx].shm->kaddr,
                                  size_new))
                                dev_err(_DEV_TEE,
@@ -765,8 +769,8 @@ static void _update_client_tee_cmd(struct tee_session *sess,
                                offset = 0;
                                size = parent->size;
                        } else {
-                               offset = cmd_io->op->params[idx].memref.offset;
-                               size = cmd_io->op->params[idx].memref.size;
+                               offset = op.params[idx].memref.offset;
+                               size = op.params[idx].memref.size;
                        }
 
                        /* Returned updated size */