tee: amdtee: fix memory leak in amdtee_open_session()

On these error paths the "sess" variable isn't freed.  It's a refcounted
pointer so we need to call kref_put().  I re-arranged the code a bit so
the error case is always handled before the success case and the error
paths are indented two tabs.

Fixes: 757cc3e9ff ("tee: add AMD-TEE driver")
Reviewed-by: Rijo Thomas <Rijo-john.Thomas@amd.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
This commit is contained in:
Dan Carpenter 2020-02-24 13:51:39 +03:00 committed by Jens Wiklander
parent 11a48a5a18
commit b83685bcee

View File

@ -212,6 +212,19 @@ unlock:
return rc;
}
static void destroy_session(struct kref *ref)
{
struct amdtee_session *sess = container_of(ref, struct amdtee_session,
refcount);
/* Unload the TA from TEE */
handle_unload_ta(sess->ta_handle);
mutex_lock(&session_list_mutex);
list_del(&sess->list_node);
mutex_unlock(&session_list_mutex);
kfree(sess);
}
int amdtee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param)
@ -236,15 +249,13 @@ int amdtee_open_session(struct tee_context *ctx,
/* Load the TA binary into TEE environment */
handle_load_ta(ta, ta_size, arg);
if (arg->ret == TEEC_SUCCESS) {
mutex_lock(&session_list_mutex);
sess = alloc_session(ctxdata, arg->session);
mutex_unlock(&session_list_mutex);
}
if (arg->ret != TEEC_SUCCESS)
goto out;
mutex_lock(&session_list_mutex);
sess = alloc_session(ctxdata, arg->session);
mutex_unlock(&session_list_mutex);
if (!sess) {
rc = -ENOMEM;
goto out;
@ -259,40 +270,29 @@ int amdtee_open_session(struct tee_context *ctx,
if (i >= TEE_NUM_SESSIONS) {
pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
kref_put(&sess->refcount, destroy_session);
rc = -ENOMEM;
goto out;
}
/* Open session with loaded TA */
handle_open_session(arg, &session_info, param);
if (arg->ret == TEEC_SUCCESS) {
sess->session_info[i] = session_info;
set_session_id(sess->ta_handle, i, &arg->session);
} else {
if (arg->ret != TEEC_SUCCESS) {
pr_err("open_session failed %d\n", arg->ret);
spin_lock(&sess->lock);
clear_bit(i, sess->sess_mask);
spin_unlock(&sess->lock);
kref_put(&sess->refcount, destroy_session);
goto out;
}
sess->session_info[i] = session_info;
set_session_id(sess->ta_handle, i, &arg->session);
out:
free_pages((u64)ta, get_order(ta_size));
return rc;
}
static void destroy_session(struct kref *ref)
{
struct amdtee_session *sess = container_of(ref, struct amdtee_session,
refcount);
/* Unload the TA from TEE */
handle_unload_ta(sess->ta_handle);
mutex_lock(&session_list_mutex);
list_del(&sess->list_node);
mutex_unlock(&session_list_mutex);
kfree(sess);
}
int amdtee_close_session(struct tee_context *ctx, u32 session)
{
struct amdtee_context_data *ctxdata = ctx->data;