in optee/call.c [140:218]
int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param)
{
struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_context_data *ctxdata = ctx->data;
int rc;
struct tee_shm *shm;
struct optee_msg_arg *msg_arg;
struct optee_session *sess = NULL;
uuid_t client_uuid;
/* +2 for the meta parameters added below */
shm = optee_get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
if (IS_ERR(shm))
return PTR_ERR(shm);
msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
msg_arg->cancel_id = arg->cancel_id;
/*
* Initialize and add the meta parameters needed when opening a
* session.
*/
msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
OPTEE_MSG_ATTR_META;
msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
OPTEE_MSG_ATTR_META;
memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
msg_arg->params[1].u.value.c = arg->clnt_login;
rc = tee_session_calc_client_uuid(&client_uuid, arg->clnt_login,
arg->clnt_uuid);
if (rc)
goto out;
export_uuid(msg_arg->params[1].u.octets, &client_uuid);
rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
arg->num_params, param);
if (rc)
goto out;
sess = kzalloc(sizeof(*sess), GFP_KERNEL);
if (!sess) {
rc = -ENOMEM;
goto out;
}
if (optee->ops->do_call_with_arg(ctx, shm)) {
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}
if (msg_arg->ret == TEEC_SUCCESS) {
/* A new session has been created, add it to the list. */
sess->session_id = msg_arg->session;
mutex_lock(&ctxdata->mutex);
list_add(&sess->list_node, &ctxdata->sess_list);
mutex_unlock(&ctxdata->mutex);
} else {
kfree(sess);
}
if (optee->ops->from_msg_param(optee, param, arg->num_params,
msg_arg->params + 2)) {
arg->ret = TEEC_ERROR_COMMUNICATION;
arg->ret_origin = TEEC_ORIGIN_COMMS;
/* Close session again to avoid leakage */
optee_close_session(ctx, msg_arg->session);
} else {
arg->session = msg_arg->session;
arg->ret = msg_arg->ret;
arg->ret_origin = msg_arg->ret_origin;
}
out:
tee_shm_free(shm);
return rc;
}